You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 使用:

  1. 定义 @Roles 装饰器
// roles.decorator.ts
import { SetMetadata } from '@nestjs/common';

export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
  1. 修改 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));
  }
}
  1. 在路由上指定允许的角色
@Get('/')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin') // 仅允许 admin 角色访问
getAllUsers(): any {
  return this.userService.getAll();
}

内容的提问来源于stack exchange,提问作者UAhmadSoft

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 16:16:12