Nestjs Roles装饰器从JWT载荷获取用户时的异常行为排查
问题根因
你的问题本质是Guard的执行顺序不符合预期:
你大概率在AppModule中通过APP_GUARD将RolesGuard注册为了全局守卫,全局守卫的执行优先级永远高于控制器/路由层面声明的守卫。
- 当你开启角色校验时:全局
RolesGuard先执行,此时JwtAuthGuard还未运行,request.user未被赋值,校验失败直接返回false,JwtAuthGuard根本没有执行机会,自然日志里user是undefined。 - 当你关闭角色校验直接返回
true时:全局RolesGuard执行通过后,才会运行控制器层面的JwtAuthGuard,将JWT解析出的用户信息挂载到request.user上,后续再次执行RolesGuard时就能拿到用户信息,所以日志输出正常。
解决方案
方案1:调整全局守卫顺序(推荐)
如果你需要全局生效JWT校验和角色校验,直接在AppModule的providers中按顺序注册两个守卫,控制器层面无需再额外加@UseGuards:
// app.module.ts @Module({ providers: [ // 先执行JWT校验,挂载用户信息 { provide: APP_GUARD, useClass: JwtAuthGuard }, // 再执行角色校验 { provide: APP_GUARD, useClass: RolesGuard } ] }) export class AppModule {}
方案2:取消RolesGuard的全局注册
如果你不需要全局生效角色校验,直接删掉AppModule中RolesGuard的全局注册配置,仅保留控制器层面的@UseGuards(JwtAuthGuard, RolesGuard)即可,此时守卫会按照你声明的顺序执行,request.user会先被JwtAuthGuard赋值再传入RolesGuard。
优化建议
在RolesGuard中补充用户存在性校验,避免运行时报错:
const request = context.switchToHttp().getRequest(); const user = request.user; if (!user) { return false; } const userRole = user.roles;
内容的提问来源于stack exchange,提问作者fschober
相关产品推荐
相关产品推荐

