NestJS集成JWT+Passport时角色守卫中req.user未定义问题求助
问题解决:NestJS RolesGuard 中 req.user 为 undefined 的原因及修复方案
核心问题根源
你在路由上多次单独使用 @UseGuards 装饰器,导致 NestJS 仅执行最后一个守卫(RolesGuard),而负责认证的 JwtAuthGuard 并未被触发。由于认证守卫没运行,req.user 自然不会被挂载,所以在 RolesGuard 中获取到的是 undefined。
NestJS 中,每个 @UseGuards 装饰器会替换当前路由的守卫列表,而非追加。分开写两个 @UseGuards 等同于只启用了最后一个守卫。
修复步骤
1. 合并守卫到同一个 @UseGuards 装饰器
将认证守卫与角色守卫放在同一个 @UseGuards 中,且保证认证守卫在前(守卫按顺序执行,需先完成认证挂载用户信息)。
修改 user.controller.ts:
@Controller('users') export class UserController { constructor(private userService: UserService) {} @Get('/') // 合并两个守卫,JwtAuthGuard 先执行完成认证 @UseGuards(JwtAuthGuard, RolesGuard) getAllUsers(): any { return this.userService.getAll(); } }
如果你更倾向于直接使用 AuthGuard('jwt') 而非自定义的 JwtAuthGuard,也可以写成:
@UseGuards(AuthGuard('jwt'), RolesGuard)
2. 验证基础逻辑(已正确实现,无需修改)
你的 JwtStrategy 中 validate 方法已经正确返回用户对象,Passport 会自动将该返回值挂载到 req.user 上,这部分逻辑没问题:
async validate(payload: any) { const user = await this.userService.getOne(payload._id); console.log('user', user); return user; // Passport 会将此对象挂载到 req.user }
扩展:实现角色权限校验(可选)
如果需要进一步基于角色限制访问,可以添加一个自定义的 @Roles 装饰器配合 RolesGuard 使用:
- 定义
@Roles装饰器
// roles.decorator.ts import { SetMetadata } from '@nestjs/common'; export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
- 修改
RolesGuard校验角色
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; @Injectable() export class RolesGuard implements CanActivate { constructor(private reflector: Reflector) {} canActivate(context: ExecutionContext): boolean | Promise<boolean> { // 获取路由上配置的必填角色 const requiredRoles = this.reflector.get<string[]>('roles', context.getHandler()); if (!requiredRoles) { return true; // 未配置角色则直接放行 } const req = context.switchToHttp().getRequest(); // 假设用户对象包含 roles 属性,根据你的数据库结构调整 return req.user?.roles?.some(role => requiredRoles.includes(role)); } }
- 在路由上指定允许的角色
@Get('/') @UseGuards(JwtAuthGuard, RolesGuard) @Roles('admin') // 仅允许 admin 角色访问 getAllUsers(): any { return this.userService.getAll(); }
内容的提问来源于stack exchange,提问作者UAhmadSoft
相关产品推荐
相关产品推荐

