koa-router如何给每个api添加一个基于jwt的token验证的方法?

// valid.js
module.exports = function(req) {
    const token = req.headers['x-access-token'];
    return jwt.verify(token, PRIMARY_KEY, function (err, decoded) {
        if (err) {
            return {
                success: false,
                data: {
                    code: -101,
                    message: 'Failed to authenticate token.'
                }
            }
        }
        return {
            success: true,
        }
    })
}
// api.js
const tokenValid = require('../tokenValid');

router.post('/api/a', async(ctx, next) => {
    const valid = tokenValid(ctx.request);
    if (!valid.success) {
      ctx.rest(valid.data);
      return;
    }
    // todo
})

如果我有很多个接口,岂不是每个api中都要写一段重复代码。但是如何对async进行封装,使得每个接口不需要在考虑token,除了登陆和注册。

阅读 5.3k
3 个回答

你需要将你的jwt验证逻辑包装Promise,返回true,false
中间件,检测登录

const checkLogin = async(ctx,next)=> {
    if(['/login'].indexOf(ctx.url)!==-1){
    await next();
    return;
    }
    const isLogin = await valid();
    if(!isLogin) {
        ctx.throw(401);
    }
    await next();
}

路由

cosnt router = new Router();
router.use(checkLogin);
// 接下来都是通过认证的

router.use() 方法需要指定指定一个路由,且这个路由只能进行完全匹配,eg:
router.use('/api/auth', tokenValid)只能对api/auth这个api做token验证。使用了正则做模糊匹配,好像也不行。

最后我在api.js 入口文件中,使用了如下代码

// token valid
app.use(async function (ctx, next) {
    // 必须保证是api,因为路由和资源请求好像也会经过这里
  if (ctx.url.indexOf('/api') > -1 && ctx.url.indexOf('/api/auth/') === -1) {
    const token = ctx.request.header['x-access-token']  // X-Access-Token 会被转换成小写
    jwt.verify(token, TOKEN_PRIMARY_KEY, function (err, decoded) {
      console.log('err: ', err);
      if (err) {
          ctx.response.status = 401;
          ctx.response.body = {
            code: -100,
            message: 'invalid token',
          };
      }
    })
  }
   // 这里有一个问题,即使验证没通过,也会接着执行
  await next();
})

这里使用app.use可以获取到每个路由,每个请求。但是呢,这里的ctx.requst只能获取到ctx.request.headers而获取不到ctx.request.body。这点没想明白,可能和安全有关系吧。

之后在前端代码对axios封装的时候,加上

headers: {
  'X-Access-Token': window.localStorage.getItem('token'),
  'X-Requested-With': 'XMLHttpRequest'
},

token是登录接口返回的,存在localstorage里面

新手上路,请多包涵

router.use的path参数是可选的

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题