NestJS参数装饰器能否获取参数原值 或用方法装饰器实现角色校验
方案1 最小改动解决参数装饰器覆盖问题
Nest 原生 createParamDecorator 的回调函数未暴露前序装饰器返回的参数原有值,因此无法直接获取原有值返回。但你可以直接调整现有参数装饰器的返回值即可实现透明效果:
你在 MinimumRole 装饰器内已经通过 getCurrentUserFromContext 拿到了完整的用户对象,把返回值从 undefined 改成该用户对象即可,无论装饰器书写顺序如何,都不会出现覆盖为 undefined 的问题:
export const MinimumRole = createParamDecorator( (minimumRole: Role, executionContext: ExecutionContext) => { const user = getCurrentUserFromContext(executionContext); assertHasMinimumRole(user.role, minimumRole); // 不满足条件则抛出异常 return user; // 直接返回用户对象,不会覆盖原有值 });
方案2 改为方法级角色校验
普通方法装饰器是在应用初始化阶段执行的,无法直接获取请求运行时的上下文。Nest 原生的守卫(Guard)机制是方法级权限校验的最佳实践,守卫可以在请求生命周期内拿到完整的 ExecutionContext 上下文,实现如下:
- 先定义守卫实现校验逻辑
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; @Injectable() export class MinimumRoleGuard implements CanActivate { constructor(private reflector: Reflector) {} canActivate(context: ExecutionContext): boolean { // 读取方法上挂载的最低角色要求元数据 const minimumRole = this.reflector.get<Role>('minimumRole', context.getHandler()); // 没有配置最低角色要求直接放行 if (!minimumRole) return true; const user = getCurrentUserFromContext(context); assertHasMinimumRole(user.role, minimumRole); return true; } }
- 定义方法级装饰器绑定守卫
import { applyDecorators, SetMetadata, UseGuards } from '@nestjs/common'; export const MinimumRole = (role: Role) => { return applyDecorators( SetMetadata('minimumRole', role), UseGuards(MinimumRoleGuard) ); };
- 使用方式
@Get('/list') @MinimumRole(Role.manager) // 作用在方法上,不需要和参数装饰器绑定顺序 getUserList(@CurrentUser() user: User) { // 业务逻辑 }
方法级装饰器的优势是可以直接作用在整个控制器上,对控制器下所有接口统一做角色校验,不需要每个参数单独加装饰器。
内容的提问来源于stack exchange,提问作者Flavien Volken
相关产品推荐
相关产品推荐

