Egg實現JWT鑑權

莫珂發表於2019-11-09

目錄

  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從全域性變數中獲取

Egg實現JWT鑑權

避免重複造輪子

使用現成的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相同的功能

相關文章