Nestjs自定義註解實現接口權限控制詳解
正文
當業務接口開發完成之後,正式上線之前還需要對每個接口進行權限控制。比如刪除用戶隻能管理員角色操作,查詢全部用戶隻有管理員有權限等。
對接口實現權限控制有很多種方案,最簡單的實現是在每個接口的 controller 層進行判斷,但這樣不優雅,冗餘代碼多,且對業務侵入比較強。合理的權限控制方案應該是跟業務邏輯松耦合。
Nest 官方文檔為我們提供瞭幾種權限控制方式,我們來實現最基礎的基於角色的 RBAC(Role-based access control) 控制方案。
實現 RBAC 權限控制一共需要五步:
- 定義角色的枚舉類 Role
- 聲明自定義註解(裝飾器)roles.decorators.ts
- 實現角色守衛 RolesGuard
- 在 app.module.ts 的 providers 中引入 RolesGuard
- 在需要的接口上添加註解:
@Roles(Role.Admin, Role.SuperAdmin)�
定義角色枚舉
梳理好系統中一共有多少種角色,並為每種角色確定好 Code,然後聲明為枚舉類型。這裡的角色類型可以自定義,根據業務需要設多少都行。
export enum Role { SuperAdmin = 'SuperAdmin', Admin = 'Admin', Normal = 'Normal', Guest = 'Guest', }
聲明自定義註冊(裝飾器)
新建一個 roles.decorator.ts
文件,就可以在 Controller 中使用 @Roles
註解瞭
import { SetMetadata } from '@nestjs/common'; import { Role } from '@constants'; export const ROLES_KEY = 'roles'; export const Roles = (...roles: Role[]) => SetMetadata(ROLES_KEY, roles);
實現角色守衛 RolesGuard
新建 roles.gurad.ts
文件,它的作用是告訴 nest 什麼情況下請求應該被攔截,什麼情況下請求應該被通過。
通過 reflector
可以拿到註解中傳入的角色 code 列表,通過 context.switchToHttp().getRequest()
可以拿到 request 對象。因為我們使用瞭 jwt,在 JwtStrategy�
中往 user 對象中寫入瞭當前登錄用戶的角色信息,所以可以通過從 request 中取 user 的方式得到角色列表。這塊具體的獲取方式根據你的業務而定,業務中把角色信息放在瞭什麼地方,就從哪裡取。
拿到註解中傳入的角色,和用戶已有的角色進行對比,如果用戶角色中包含需要的角色,則返回 true,如果返回 false,則會拋出默認的異常如下:
{ "statusCode": 403, "message": "Forbidden resource", "error": "Forbidden" }
我們需要定制錯誤信息,以使整個系統保持一致,則拋出一個自定義異常,這個異常按照統一規定的格式返回錯誤信息。
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; import { ROLES_KEY } from '../decorators/roles.decorator'; import { Role } from '@constants'; import { InternalErrorException } from '../../exception/InternalErrorException'; import { errorResult } from '@utils'; import { ErrorCodes } from '@constants/errorCode'; @Injectable() export class RolesGuard implements CanActivate { constructor(private reflector: Reflector) {} canActivate(context: ExecutionContext): boolean { const requiredRoles = this.reflector.getAllAndOverride<Role[]>(ROLES_KEY, [ context.getHandler(), context.getClass(), ]); if (!requiredRoles) { return true; } const { user } = context.switchToHttp().getRequest(); const roleCodes = user.roles?.map((item) => item.code); const flag = requiredRoles.some((role) => roleCodes?.includes(role)); if (!flag) { throw new InternalErrorException(errorResult(ErrorCodes.NoAuth)); } return flag; } }
在 providers 中引入 RolesGuard
如果想在全局使用自定義註解,就在 app.module.ts
中全局引入。如果僅想在某個 controller 中使用,則在這個 controller 層級的 module 中聲明。
providers: [ { provide: APP_GUARD, useClass: RolesGuard, }, ],
使用註解
在接口上使用自定義註解實現權限校驗。
括號裡可以寫一個權限,也可以寫多個,因為我們 roles.decorator.ts
中寫的參數類型為 Role[]
@Get() @Roles(Role.Admin, Role.SuperAdmin) async findAll() { const users = await this.userService.findAll(); return successResult(users); }
至此,使用自定義註冊實現接口權限控制就完成啦。
以上就是Nestjs自定義註解實現接口權限控制詳解的詳細內容,更多關於Nestjs註解接口權限的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- Nest.js 授權驗證的方法示例
- NestJs使用Mongoose對MongoDB操作的方法
- NestJS+Redis實現緩存步驟詳解
- Nest.js參數校驗和自定義返回數據格式詳解
- Nest框架中集成使用Swagger示例說明