NestJs 守衛

簡介

https://docs.nestjs.cn/9/guards

守衛是一個使用 @Injectable() 裝飾器的類。 守衛應該實現 CanActivate 接口。

img

守衛有一個單獨的責任。它們根據運行時出現的某些條件(例如權限,角色,訪問控制列表等)來確定給定的請求是否由路由處理程序處理。這通常稱爲授權。在傳統的 Express 應用程序中,通常由中間件處理授權(以及認證)。中間件是身份驗證的良好選擇,因爲諸如 token 驗證或添加屬性到 request 對象上與特定路由(及其元數據)沒有強關聯。

中間件不知道調用 next() 函數後會執行哪個處理程序。另一方面,守衛可以訪問 ExecutionContext 實例,因此確切地知道接下來要執行什麼。它們的設計與異常過濾器、管道和攔截器非常相似,目的是讓您在請求/響應週期的正確位置插入處理邏輯,並以聲明的方式進行插入。這有助於保持代碼的簡潔和聲明性。

守衛在每個中間件之後執行,但在任何攔截器或管道之前執行。

創建一個守衛

nest g gu [name]

例:
nest g gu role

注意:上面的命令在那個目錄下執行,就會在那個目錄下創建

image-20230407095153902

內容

守衛要求實現函數 給定參數context執行上下文 要求返回布爾值

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Observable } from 'rxjs';

@Injectable()
export class RoleGuard implements CanActivate {
  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    return true;
  }
}

image-20230407095326745

Controller 使用守衛

我們在守衛中打印一句

console.log('假設已經通過了守衛規則的校驗。。。。。。。。')

image-20230407095637140

在 p 模塊中使用

主要代碼

import { RoleGuard } from '../common/role/role.guard';
@UseGuards(RoleGuard)

image-20230407100052933

測試

http://localhost:3000/p/7f145099-e9c7-47d9-99fb-a0a3f9a39bd7?id=1314

image-20230407100427752

全局守衛

如果要註冊全局守衛,只需要在 main.ts 中註冊即可

創建守衛

nest g gu global

image-20230407100838570

守衛內容

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Observable } from 'rxjs';

@Injectable()
export class GlobalGuard implements CanActivate {
  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    console.log('這裏是全局守衛。。。。。。。。。');
    return true;
  }
}

main.ts 中註冊

// 註冊全局守衛
app.useGlobalGuards(new GlobalGuard)

image-20230407101103283

測試結果

image-20230407101148462

針對角色控制守衛

注意這裏只能裝飾 controller 的方法,不能全局

SetMetadata 裝飾器

第一個參數爲key,第二個參數自定義我們的例子是數組存放的權限

controller 中使用

@SetMetadata('role', ['admin'])

image-20230407105051154

角色守衛內容

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Observable } from 'rxjs';

import { Reflector } from '@nestjs/core'
import type { Request } from 'express'
@Injectable()
export class RoleGuard implements CanActivate {
  constructor(private Reflector: Reflector) { }
  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    // guard  使用  Reflector 反射讀取 setMetaData的值 
    const admin = this.Reflector.get<string[]>('role', context.getHandler())
    const request = context.switchToHttp().getRequest<Request>()
    // 去做判斷這邊例子是從url 判斷有沒有admin權限
    if (admin.includes(request.query.role as string)) {
      console.log('返回true');
      return true;
    }else{
      console.log('返回false');
      return false
    }

  }
}

image-20230407105327000

測試

正確的

http://localhost:3000/p?role=admin

image-20230407105419368

錯誤的

http://localhost:3000/p?role=test

image-20230407105513885

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章