目錄
前言
繼上次寫了如何優雅的處理異常,這篇講一下如何實現JWT(json web token)認證方式;JWT是一種開放標準(RFC7519),具體的這裡就不重複介紹了,可以去檢視一些說明文件,這裡就簡單介紹一下egg裡面的應用。
推薦閱讀: 阮一峰的JWT介紹入門
自己實現中介軟體
我們首先介紹如何自己實現中介軟體來完成JWT鑑權
- 實現鑑權中介軟體,首先在上一篇文章的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();
}
}
複製程式碼
- 實現登入簽名介面和測試介面
// 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呼叫需要鑑權的介面 這裡使用了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相同的功能