如何在控制器中添加多个 Nestjs RoleGuard
How to add multiple Nestjs RoleGuards in controllers
我有 ADMIN、SUPERADMIN、USER、MODERATORS 的角色保护,
这是其中一名守卫的例子。案件中的一名管理员警卫。他们按我的预期工作,但我无法在控制器中添加多个守卫
import { Injectable, CanActivate, ExecutionContext, HttpException, HttpStatus } from '@nestjs/common';
@/Injectable()
export class AdminGuard implements CanActivate {
constructor() { }
canActivate(context: ExecutionContext) {
const request = context.switchToHttp().getRequest();
const user = request.user;
if (user.usertype == 'Admin') {
return true;
}
throw new HttpException('Unauthorized access', HttpStatus.BAD_REQUEST);
}
}
在我的控制器中,我有这个装饰器
@UseGuards(AuthGuard('jwt'), AdminGuard)
我希望能够做这样的事情
@UseGuards(AuthGuard('jwt'), AdminGuard, SuperAdminGuard)
或
@UseGuards(AuthGuard('jwt'), [AdminGuard, SuperAdminGuard, UserGuard])
或
@UseGuards(AuthGuard('jwt'), AdminGuard || SuperAdminGuard || UserGuard])
None 以上实现有效。有更好的方法吗?也许我做的不对。我已经检查了文档,但似乎无法正常工作
我建议创建一个通用的 RolesGuard
并使用自定义元数据为每个控制器或路由处理程序定义所需的角色:
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private readonly reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const roles = this.reflector.get<string[]>('roles', context.getHandler());
if (!roles) {
return true;
}
const request = context.switchToHttp().getRequest();
const userType = request.user.userType;
return roles.some(r => r === userType);
}
}
用于设置所需角色的自定义装饰器:
export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
如何使用?
现在您可以按如下方式定义所需的角色:
// For this route you need either Superadmin or Admin privileges
@Roles('Superadmin', 'Admin')
@UseGuards(AuthGuard('jwt'), RolesGuard)
Kim 没有回答的另一种方法是使用 Mixin
。 mixin 概念由 AuthGuard
本身使用。
export const UserTypeGuard: (...types: string[]) => CanActivate = createUserTypeGuard;
function createUserTypeGuard(...types: string[]) {
class MixinUserTypeGuard implements CanActivate {
canActivate(context: ExecutionContext) {
const user = context.switchToHttp().getRequest().user;
return types.some(type => user.userType === type);
}
}
}
用法:
@UseGuards(AuthGuard('jwt'), UserTypeGuard('SuperAdmin', 'Admin'))
我有 ADMIN、SUPERADMIN、USER、MODERATORS 的角色保护,
这是其中一名守卫的例子。案件中的一名管理员警卫。他们按我的预期工作,但我无法在控制器中添加多个守卫
import { Injectable, CanActivate, ExecutionContext, HttpException, HttpStatus } from '@nestjs/common';
@/Injectable()
export class AdminGuard implements CanActivate {
constructor() { }
canActivate(context: ExecutionContext) {
const request = context.switchToHttp().getRequest();
const user = request.user;
if (user.usertype == 'Admin') {
return true;
}
throw new HttpException('Unauthorized access', HttpStatus.BAD_REQUEST);
}
}
在我的控制器中,我有这个装饰器
@UseGuards(AuthGuard('jwt'), AdminGuard)
我希望能够做这样的事情
@UseGuards(AuthGuard('jwt'), AdminGuard, SuperAdminGuard)
或
@UseGuards(AuthGuard('jwt'), [AdminGuard, SuperAdminGuard, UserGuard])
或
@UseGuards(AuthGuard('jwt'), AdminGuard || SuperAdminGuard || UserGuard])
None 以上实现有效。有更好的方法吗?也许我做的不对。我已经检查了文档,但似乎无法正常工作
我建议创建一个通用的 RolesGuard
并使用自定义元数据为每个控制器或路由处理程序定义所需的角色:
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private readonly reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const roles = this.reflector.get<string[]>('roles', context.getHandler());
if (!roles) {
return true;
}
const request = context.switchToHttp().getRequest();
const userType = request.user.userType;
return roles.some(r => r === userType);
}
}
用于设置所需角色的自定义装饰器:
export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
如何使用?
现在您可以按如下方式定义所需的角色:
// For this route you need either Superadmin or Admin privileges
@Roles('Superadmin', 'Admin')
@UseGuards(AuthGuard('jwt'), RolesGuard)
Kim 没有回答的另一种方法是使用 Mixin
。 mixin 概念由 AuthGuard
本身使用。
export const UserTypeGuard: (...types: string[]) => CanActivate = createUserTypeGuard;
function createUserTypeGuard(...types: string[]) {
class MixinUserTypeGuard implements CanActivate {
canActivate(context: ExecutionContext) {
const user = context.switchToHttp().getRequest().user;
return types.some(type => user.userType === type);
}
}
}
用法:
@UseGuards(AuthGuard('jwt'), UserTypeGuard('SuperAdmin', 'Admin'))