Angular 有 Router Guard,是用來管制是否能進入 Component 的一道關卡,而在 NestJS 內也有一樣的機制,名字也叫做 Guard
Guard 的執行順序,會在每一個 middleware 之後,但在 interceptor 或是 pipe 之前,這順序要稍微記一下
建立
1  | nest g gu <guard name>  | 
建立出來 Guard 的基本內容
1  | import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';  | 
- 
需要實作
CanActivate介面 - 
回傳的結果為布林值,也可以是 Promise 或是 Observable 的格式
- true: 請求會繼續下去
 - false: 會拒絕連線請求
 
 - 
註冊方式與其他 filter/pipe 類似
1
2
3
4
5
6
7
8
9
10
11
12
13
14import { Controller, Get, UseGuards } from '@nestjs/common';
import { AppService } from './app.service';
import { AuthGuard } from './auth.guard';
()
export class AppController {
constructor(private readonly appService: AppService) {}
()
(AuthGuard)
getHello(): string {
return this.appService.getHello();
}
} - 
當連線被拒絕時,會收到此訊息
1
2
3
4
5{
statusCode: 403,
error: "Forbidden",
message: "Forbidden resource"
} 
ExecutionContext
在 canActivate 的方法,會有一個 context 的變數,其型別為 ExecutionContext
1  | canActivate(  | 
而這一個 ExecutionContext 是繼承 ArgumentsHost,而這個型別我們也在 Exception Filter 那邊有看過,相關細節的部分,可以再回去那個章節閱讀
1  | export interface ExecutionContext extends ArgumentsHost {  | 
範例: Role-based Auth
既然可以透過回傳 ture 或是 false 的方式決定是否能進入後續的請求流程,那再搭配其他的設定,不就能做到 Role-based 的權限控管了
官方文件內使用了 SetMetadata 與 Reflection 的方式來設定每一個 Controller method 的允許角色
1  | ()  | 
在 Guard 的地方可以用這種方式取得所設定的 metaData
1  | import { Reflector } from '@nestjs/core';  | 
既然能取得所設定的 metaData,那後續的動作就可以自由發揮了