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,那後續的動作就可以自由發揮了