Guard 是一種檢測機制,就像公司警衛一樣,沒有員工身份他不會讓你進入公司,同樣的道理,若用於需要會員身份的操作並且未使用會員身份,就會直接在 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
是放在環境變數檔裡面,並在 App
的 setEnvironment
動態改變,但 AppRoute
在 App
實例化的時間比它早,所以要將 AppRoute
實例化的時間點往後挪:
private route!: AppRoute;
private registerRoute(): void {
this.route = new AppRoute();
this.app.use('/', this.route.router);
}
透過 Postman 進行測試:
為了方便維護系統,我在這邊與大家分享我自己的規範:
其實這算是基本的運作模式,畢竟 Guard 就是要驗證是否符合主流程條件,符合才會進入主流程,若要替單一路由設置 Guard 的話,可以參考下方的範例:
this.router.get('/test',
this.guard.canActivate,
this.responseHandler(
this.controller.test
)
);
雖然這篇我是使用 express-jwt 這種現成的 Guard,但要自行設計也是可以的,不過非必要我們還是當使用輪子的人就好了
下一篇將會探討 TodoList 在會員機制下該如何調整,敬請期待!
你好~~,這個專案有github地址嗎?我想關注一下
您好,這是這個系列文用到的 GitHub repository。
如果對該設計方式感興趣,可以看看 NestJS 這個框架,我也有針對該框架撰寫系列文,歡迎入坑XD