Egg实现JWT鉴权

2,794 阅读2分钟

目录

  1. Egg优雅的实现异常处理
  2. Egg实现JWT鉴权

前言

继上次写了如何优雅的处理异常,这篇讲一下如何实现JWT(json web token)认证方式;JWT是一种开放标准(RFC7519),具体的这里就不重复介绍了,可以去查看一些说明文档,这里就简单介绍一下egg里面的应用。

推荐阅读: 阮一峰的JWT介绍入门

自己实现中间件

我们首先介绍如何自己实现中间件来完成JWT鉴权

  1. 实现鉴权中间件,首先在上一篇文章的egg工程middleware目录下创建customAuth.js文件(这里我们假设使用secret字符串作为秘钥),实现从request header中获取autorization字段,根据jwt定义提取出秘钥串使用verify方法与验证
const jsonwebtoken = require('jsonwebtoken');

module.exports = options => {
  return async(ctx, next) => {
    const { authorization = '' } = ctx.request.header;
    const token = authorization.replace('Bearer ', '');
    try {
      const user = jsonwebtoken.verify(token, 'secret');
      ctx.state.user = user;
    } catch (err) {
      ctx.throw(401, err.message);
    }
      await next();
    }
}
  1. 实现登录签名接口和测试接口
// router.js
'use strict';

/**
 * @param {Egg.Application} app - egg application
 */
module.exports = app => {
  const auth = app.middleware.customAuth();
  const { router, controller } = app;
  router.get('/', controller.home.index);
  router.get('/login', controller.home.login);
  router.get('/testlogin', auth, controller.home.needLogin);
};
// controller/home.js
'use strict';
const jsonwebtoken = require('jsonwebtoken');
const Controller = require('egg').Controller;

class HomeController extends Controller {
  // login接口用于签名,正常情况这里校验用户名密码,这里demo直接调用sign方法签名,设置过期时间为1天
  async login() {
    const { ctx } = this;
    const secret = 'secert';
    const token = jsonwebtoken.sign({ key: 'value' }, secret, { expiresIn: '1d' });
    ctx.body = { token };
  }

  // 测试鉴权
  async needLogin() {
    const { ctx } = this;
    ctx.body = '这是验证过的接口返回的数据';
  }
}

module.exports = HomeController;

测试

在测试之前,我们需要在config.default.js文件中加入下面的代码,暂时关闭csrf插件(Cross-site request forgery这是一种防止跨站请求伪造安全机制,egg中默认开启,具体细节可以去官网查看)

  config.security = {
    enable: false,
  },

postman调用登录接口

登录接口

调用postman功能将token直接写入全局变量中方便测试

postman调用需要鉴权的接口 这里使用了postman自带的jwt鉴权方式,同实token从全局变量中获取

避免重复造轮子

使用现成的koa-jwt来实现鉴权,上一篇已经说了如何引用koa中间件,这里我们现在middleware下面创建auth.js文件

module.exports = require('koa-jwt');

修改router.js中的中间件引用

'use strict';

/**
 * @param {Egg.Application} app - egg application
 */
module.exports = app => {
  const auth = app.middleware.auth({ secret: 'secret' });
  const { router, controller } = app;
  router.get('/', controller.home.index);
  router.get('/login', controller.home.login);
  router.get('/testlogin', auth, controller.home.needLogin);
};

之后进行测试,依然可以得到与上述自己编写同样的效果;这里的koa-jwt就是简化了我们的代码,实现了与自己实现的中间件verify相同的功能