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

如何在PassportJS的JwtStrategy中识别Token过期状态

区分Passport JWT校验不同错误状态的实现方案

passport-jwt默认会将所有校验失败场景统一返回401 Unauthorized,要单独识别Token过期等专属状态,核心是通过自定义认证回调捕获JWT解析阶段的特定错误类型,按场景返回对应状态即可。

实现逻辑

JWT校验分为两个阶段,不同阶段的错误可以分别捕获:

  • JWT格式/签名/有效期校验阶段:由底层jsonwebtoken库直接抛出对应类型的错误
    • Token过期:抛出TokenExpiredError,携带过期时间字段
    • Token签名被篡改/无效:抛出JsonWebTokenError
  • 业务校验阶段:即查询用户是否存在的逻辑,这部分可以通过done方法的第三个参数透传自定义错误信息

具体修改步骤

1. 替换默认的Passport认证中间件

不要直接使用passport.authenticate('jwt')的默认处理,改用自定义回调的方式接管错误响应:

// 自定义JWT认证中间件
const jwtAuth = (req, res, next) => {
  passport.authenticate('jwt', { session: false }, (err, user, info) => {
    // 处理JWT本身解析、校验阶段的错误
    if (err) {
      // 识别Token过期场景
      if (err.name === 'TokenExpiredError') {
        return res.status(401).json({
          code: 40101, // 自定义Token过期专属业务码
          message: '登录凭证已过期,请重新登录'
        })
      }
      // 处理其他JWT无效场景,比如签名错误
      return res.status(401).json({
        code: 40102,
        message: '登录凭证无效'
      })
    }

    // 处理无有效用户的场景
    if (!user) {
      // 可以根据info里的信息细分场景:比如未传Token、用户不存在等
      return res.status(401).json({
        code: 40100,
        message: info?.message || '请先登录'
      })
    }

    // 校验通过,将用户信息挂载到请求对象,继续执行后续逻辑
    req.user = user
    next()
  })(req, res, next)
}

后续路由中直接使用这个自定义中间件即可:

router.get('/user/info', jwtAuth, (req, res) => {
  res.json({ data: req.user })
})

2. 原有JwtStrategy的适配调整

现有策略代码基本不需要改动,只需要注意不要把配置项ignoreExpiration设为true(该值默认是false,即默认开启过期校验)即可。如果需要在用户不存在的场景透传自定义提示,可以调整done回调的传参:

const passport = require("passport")
const JwtStrategy = require("passport-jwt").Strategy,
ExtractJwt = require("passport-jwt").ExtractJwt
const opts = {}
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken()
opts.secretOrKey = JWT_SECRET

passport.use(
   new JwtStrategy(opts, function (jwt_payload, done) {
    UserID.findOne({ id: jwt_payload._id }, function (err, id) {
      if (err) {
        return done(err, false)
      }
      if (id) {
        return done(null, id)
      } else {
        // 第三个参数透传自定义错误信息,会被上面中间件的info参数接收
        return done(null, false, { message: '账号不存在或已被注销' })
      }
    })
  })
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.14 16:15:48