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

NestJS中Guards与Passport Strategies底层工作原理解析

NestJS Passport Guard 与 Strategy 协作原理解答

核心绑定规则

你自定义的RtGuard继承AuthGuard('jwt-refresh')后,会自动通过字符串标识jwt-refresh匹配到你用PassportStrategy(Strategy, 'jwt-refresh')注册的刷新令牌策略,不需要手动调用策略方法。

完整认证执行流程

整个校验过程分4个固定阶段执行,你观察到的「错误token不进入Strategy逻辑」是阶段3的内置拦截机制导致的:

  1. 守卫触发阶段:请求命中被@UseGuards(RtGuard)装饰的GraphQL Mutation时,Nest会执行RtGuard从父类AuthGuard继承的canActivate核心逻辑。
  2. 请求适配阶段:canActivate首先调用你重写的getRequest方法,将GraphQL专属执行上下文转换为通用的Express Request对象,这一步无论token是否合法都会执行——也就是你写的console.log('REFRESH')每次请求都会打印的原因。
  3. Passport内置JWT校验阶段:拿到Request对象后,AuthGuard会将请求交给Passport框架调度对应策略,首先执行passport-jwt包内置的基础校验逻辑,这部分逻辑早于你自定义的validate方法执行:
    • 按照配置的ExtractJwt.fromAuthHeaderAsBearerToken()规则从Authorization头提取Bearer格式的token,提取失败直接返回401
    • 用配置的REFRESH_TOKEN_SECRET校验JWT签名合法性,签名伪造、token结构损坏直接返回401
    • 因为你配置了ignoreExpiration: false,会同步校验token是否在有效期内,过期直接返回401
      以上任意一步失败,请求都会被直接拦截,根本不会进入你写的Strategy类的validate方法,这和你测试的现象完全一致。
  4. 自定义业务校验阶段:只有内置JWT校验全部通过,Passport才会把解析完成的JWT payload传入你写的validate方法,执行自定义逻辑:
    • 你当前的逻辑是二次提取请求头中的refreshToken字符串,拼到payload上返回
    • 如果这一步抛出异常,会按异常类型返回对应状态码(比如你写的token格式错误抛403)
    • validate方法的返回值会被AuthGuard自动挂载到req.user属性上,后续Resolver、Service中可以直接取到登录用户信息。

代码优化提示

你在validate中提取refreshToken的逻辑存在兼容问题:

// 原逻辑只能精确匹配大写Bearer+单空格的格式,遇到多空格、小写bearer会残留多余字符
const refreshToken = req.get('authorization')?.replace('Bearer', '').trim();

建议替换为不区分大小写、匹配任意前缀空白的正则写法:

const refreshToken = req.get('authorization')?.replace(/^Bearer\s+/i, '').trim();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 10:03:22