iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 23
0
Software Development

今晚我想來點 Express 佐 MVC 分層架構系列 第 23

[今晚我想來點 Express 佐 MVC 分層架構] DAY 23 - Guard

什麼是 Guard?

Guard 是一種檢測機制,就像公司警衛一樣,沒有員工身份他不會讓你進入公司,同樣的道理,若用於需要會員身份的操作並且未使用會員身份,就會直接在 Guard 擋下,不會繼續進行主行程,可以是拋出錯誤,亦可以是走其他流程。

JWT Guard

有一個套件專門處理 Express 的 JWT 驗證,叫做 express-jwt,透過 npm 進行安裝:

npm install express-jwt

並安裝定義檔:

npm install @types/express-jwt --save-dev

使用方法很簡單,它是中介軟體,所以只要在請求發動時先執行它即可,我們直接在 ApiRoute 中使用:

import JWTGuard from 'express-jwt';
protected registerRoute(): void {
  this.router.use(
    JWTGuard(
      {
        secret: (process.env.JWT_SIGN as string),
        userProperty: 'payload',
        algorithms: ['HS256'] 
      }
    )
  );
  this.router.use('/todos', this.todoRoute.router);
}

secret 為簽章用的 key,userProperty 則為 JWT 解析後的使用者資訊屬性名稱,algorithms 則為 JWT 所用的加密演算法。

錯誤處理

express-jwt 在驗證不通過的時候,會拋出錯誤,而錯誤的物件是使用它設計的 UnauthorizedError,表示我們要將它的錯誤資訊處理過後再走回 DefaultException,所以我們在 exceptions 下新增一個 jwt.exception.ts

import { ErrorRequestHandler } from 'express';
import { UnauthorizedError } from 'express-jwt';
import { ResponseObject } from '../common/response/response.object';

export const JWTException: ErrorRequestHandler = (err, req, res, next) => {
  if ( err instanceof UnauthorizedError ) {
    err = new ResponseObject({ status: err.status, data: err.message });
  }
  next(err);
};

接著在 index.ts 中套用:

import { App } from './app';
import { JWTException } from './exceptions/jwt.exception';
import { DefaultException } from './exceptions/default.exception';

const bootstrap = () => {
  const app = new App();
  app.setException(JWTException);
  app.setException(DefaultException);
  app.launchDatabase();
  app.bootstrap();
};

bootstrap();

這邊要注意一件事,因為我們的 JWT_SIGN 是放在環境變數檔裡面,並在 AppsetEnvironment 動態改變,但 AppRouteApp 實例化的時間比它早,所以要將 AppRoute 實例化的時間點往後挪:

private route!: AppRoute;
private registerRoute(): void {
  this.route = new AppRoute();
  this.app.use('/', this.route.router);
}

透過 Postman 進行測試:
https://ithelp.ithome.com.tw/upload/images/20200909/20119338d2rZ4pgDCR.png

規範 Guard

為了方便維護系統,我在這邊與大家分享我自己的規範:

在主流程之前

其實這算是基本的運作模式,畢竟 Guard 就是要驗證是否符合主流程條件,符合才會進入主流程,若要替單一路由設置 Guard 的話,可以參考下方的範例:

this.router.get('/test',
  this.guard.canActivate,
  this.responseHandler(
    this.controller.test
  )
);

小結

雖然這篇我是使用 express-jwt 這種現成的 Guard,但要自行設計也是可以的,不過非必要我們還是當使用輪子的人就好了 /images/emoticon/emoticon37.gif
下一篇將會探討 TodoList 在會員機制下該如何調整,敬請期待!


上一篇
[今晚我想來點 Express 佐 MVC 分層架構] DAY 22 - 實作帳戶機制 (下)
下一篇
[今晚我想來點 Express 佐 MVC 分層架構] DAY 24 - 實作會員關聯資料
系列文
今晚我想來點 Express 佐 MVC 分層架構30

尚未有邦友留言

立即登入留言