NestJS技术求助:自定义RolesGuard中无法获取JWT认证用户信息
这个问题的核心是守卫的执行顺序以及当前路由缺少JWT认证守卫的应用——用户信息还没被挂载到请求对象上,RolesGuard自然拿不到request.user。
问题分析
你提到getProfile接口能正常获取req.user,说明这个接口肯定应用了负责JWT解析的AuthGuard('jwt')(要么是局部配置,要么是全局注册)。但你的findAll接口只添加了RolesGuard,没有让请求先经过JWT认证步骤:没有认证流程,NestJS就不会把用户信息注入到request对象里,所以console.log(request.user)才会输出undefined。
解决方案
你需要确保AuthGuard('jwt')在RolesGuard之前执行,有两种可行方式:
1. 局部在路由上同时应用两个守卫(更灵活)
修改findAll接口的守卫配置,把AuthGuard('jwt')放在RolesGuard前面——NestJS会按照@UseGuards()的参数顺序依次执行守卫,只有前面的守卫通过后,才会执行后续守卫:
@Get() @UseGuards(AuthGuard('jwt'), RolesGuard) // 先完成JWT认证,再执行角色鉴权 @Roles('admin') findAll() { return this.usersService.findAll(); }
2. 全局注册JWT认证守卫
如果你的大部分接口都需要JWT认证,可以在AppModule里全局注册AuthGuard('jwt'),这样所有路由都会自动经过JWT认证,之后只需要在需要角色鉴权的接口上单独添加RolesGuard即可:
// src/app.module.ts import { Module } from '@nestjs/common'; import { APP_GUARD } from '@nestjs/core'; import { AuthGuard } from '@nestjs/passport'; @Module({ imports: [/* 你的其他模块 */], providers: [ { provide: APP_GUARD, useClass: AuthGuard('jwt'), }, ], }) export class AppModule {}
之后findAll接口可以保持原有写法,全局守卫已经完成了JWT认证并挂载了request.user:
@Get() @UseGuards(RolesGuard) @Roles('admin') findAll() { return this.usersService.findAll(); }
验证逻辑
修改后,你可以在RolesGuard里再次打印request.user,就能看到正常的用户信息了。之后你就可以基于request.user的角色信息和reflector获取到的roles元数据,完成角色鉴权逻辑。
内容的提问来源于stack exchange,提问作者Toby Boulton

