Nestjs自定義注解實現(xiàn)接口權限控制詳解
正文
當業(yè)務接口開發(fā)完成之后,正式上線之前還需要對每個接口進行權限控制。比如刪除用戶只能管理員角色操作,查詢?nèi)坑脩糁挥泄芾韱T有權限等。
對接口實現(xiàn)權限控制有很多種方案,最簡單的實現(xiàn)是在每個接口的 controller 層進行判斷,但這樣不優(yōu)雅,冗余代碼多,且對業(yè)務侵入比較強。合理的權限控制方案應該是跟業(yè)務邏輯松耦合。
Nest 官方文檔為我們提供了幾種權限控制方式,我們來實現(xiàn)最基礎的基于角色的 RBAC(Role-based access control) 控制方案。
實現(xiàn) RBAC 權限控制一共需要五步:
- 定義角色的枚舉類 Role
- 聲明自定義注解(裝飾器)roles.decorators.ts
- 實現(xiàn)角色守衛(wèi) RolesGuard
- 在 app.module.ts 的 providers 中引入 RolesGuard
- 在需要的接口上添加注解:
@Roles(Role.Admin, Role.SuperAdmin)?
定義角色枚舉
梳理好系統(tǒng)中一共有多少種角色,并為每種角色確定好 Code,然后聲明為枚舉類型。這里的角色類型可以自定義,根據(jù)業(yè)務需要設多少都行。
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);
實現(xiàn)角色守衛(wèi) RolesGuard
新建 roles.gurad.ts文件,它的作用是告訴 nest 什么情況下請求應該被攔截,什么情況下請求應該被通過。
通過 reflector可以拿到注解中傳入的角色 code 列表,通過 context.switchToHttp().getRequest()可以拿到 request 對象。因為我們使用了 jwt,在 JwtStrategy?中往 user 對象中寫入了當前登錄用戶的角色信息,所以可以通過從 request 中取 user 的方式得到角色列表。這塊具體的獲取方式根據(jù)你的業(yè)務而定,業(yè)務中把角色信息放在了什么地方,就從哪里取。
拿到注解中傳入的角色,和用戶已有的角色進行對比,如果用戶角色中包含需要的角色,則返回 true,如果返回 false,則會拋出默認的異常如下:
{
"statusCode": 403,
"message": "Forbidden resource",
"error": "Forbidden"
}
我們需要定制錯誤信息,以使整個系統(tǒng)保持一致,則拋出一個自定義異常,這個異常按照統(tǒng)一規(guī)定的格式返回錯誤信息。
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,
},
],
使用注解
在接口上使用自定義注解實現(xiàn)權限校驗。
括號里可以寫一個權限,也可以寫多個,因為我們 roles.decorator.ts中寫的參數(shù)類型為 Role[]
@Get()
@Roles(Role.Admin, Role.SuperAdmin)
async findAll() {
const users = await this.userService.findAll();
return successResult(users);
}
至此,使用自定義注冊實現(xiàn)接口權限控制就完成啦。
以上就是Nestjs自定義注解實現(xiàn)接口權限控制詳解的詳細內(nèi)容,更多關于Nestjs注解接口權限的資料請關注腳本之家其它相關文章!
相關文章
用Nodejs實現(xiàn)在終端中炒股的實現(xiàn)
這篇文章主要介紹了用Nodejs實現(xiàn)在終端中炒股的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-10-10
Node.js readline 逐行讀取、寫入文件內(nèi)容的示例
本篇文章主要介紹了Node.js readline逐行讀取、寫入文件內(nèi)容的示例,運用readline逐行讀取的兩種實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-03-03
Nodejs + sequelize 實現(xiàn)增刪改查操作
這篇文章主要介紹了Nodejs + sequelize 實現(xiàn)增刪改查操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11

