nestjs 使用 Guard 這個元件,來對使用輸入做驗證或檢核。比如授權驗證功能,權限驗證。
Guard 主要透過 ExcutionContext 來讀取當下的輸入參數,職責就是檢核當下的輸入,阻擋不符合逾期的輸入。
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const request = context.switchToHttp().getRequest();
return validateRequest(request);
}
}
以上範例中, validateRequest 代表透過 request 去做驗證的邏輯。回傳值會是 true 或是 false。如果回傳 true ,則直接往後執行。false ,則預設回傳 Forbidden Exception (http code= 403)。如果要根據邏輯自行修改,可以改拋出自行定義的 HttpException 。
Role base control Guard 可以設計,除出一個 Roles decorator 如下:
roles.decorator.ts
import { Reflector } from '@nestjs/core';
export const Roles = Reflector.createDecorator<string[]>();
然後在需要套用 role 規則的路由加入 Roles decorator 如下:
// limit only admin role could createCatDto
@Post()
@Roles(['admin'])
async create(@Body() createCatDto: CreateCatDto) {
this.catsService.create(createCatDto);
}
最後,由 RolesGuard 做驗證
mport { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Roles } from './roles.decorator';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
// 取出 decorator 設定的 roles
const roles = this.reflector.get(Roles, context.getHandler());
if (!roles) {
return true;
}
const request = context.switchToHttp().getRequest();
const user = request.user;
// 檢查 decorator 設定的 roles 與 request user 的 role 是否吻合
return matchRoles(roles, user.roles);
}
}
nestjs 透過 Guard 元件來把輸入做驗證或檢核的邏輯獨立出來,這樣可以讓原本 Controller 的職責更加單一。簡化複雜的設定,只要在 Guard 的部份把核心的檢核設定好。這樣就可以很方便的把功能抽換,並且因為是同一個格式所以方便閱讀。