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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 13:45:08