升级express-jwt@7.7.5后合法JWT Token校验失效问题
问题根因
升级express-jwt到7.x版本后存在多个不兼容旧版的破坏性变更,现有代码未适配这些变更、且缺少必要的错误捕获逻辑,是合法Token校验直接返回500的核心原因:
- 配置项更名:v6版本用于指定JWT解析结果挂载到
req对象属性名的配置项userProperty,在v7版本中已被废弃,替换为requestProperty,原有配置不会生效。 - 错误抛出逻辑变更:v7版本的鉴权中间件校验失败时返回Promise类型的异步异常,Express默认错误处理器无法捕获这类异常,若未自定义错误处理中间件接管,所有鉴权阶段的报错都会直接触发500响应,也看不到具体错误信息。
- 额外注意:你贴出的示例Token
exp字段值为1662515841,对应时间为2022年9月7日,属于已过期Token,测试时会直接触发过期校验失败。
排查步骤
首先定位具体报错,不要盲改代码:
在所有路由注册的最末尾,添加Express标准的四参数错误处理中间件,该中间件可以捕获包括鉴权异常在内的所有全局错误:
// 注意:该中间件必须放在所有路由、其他中间件注册之后 app.use((err, req, res, next) => { // 打印错误详情定位具体问题 console.error('服务错误详情:', err); if (err.name === 'UnauthorizedError') { return res.status(401).json({ msg: '访问凭证无效' }); } res.status(500).json({ msg: '服务内部错误' }); });
添加后重新发起请求,即可从控制台看到具体的报错原因,针对性修复即可。
修复方案
针对现有代码做3处调整即可恢复正常鉴权:
- 替换废弃配置项
将鉴权配置中的userProperty: 'payload'替换为新版本要求的requestProperty: 'payload',保持原有解析结果挂载到req.payload的逻辑:const auth = { required: jwt({ secret: 'secret', algorithms: ["HS256"], requestProperty: 'payload', // 替换废弃的userProperty配置 getToken: getTokenFromHeaders }), optional: jwt({ secret: 'secret', algorithms: ["HS256"], requestProperty: 'payload', // 替换废弃的userProperty配置 getToken: getTokenFromHeaders, credentialsRequired: false, }), }; - (可选)兼容标准Authorization头格式
现有Token提取逻辑仅识别Authorization: Token <token值>格式的请求头,如果前端使用标准JWT约定的Bearer前缀传参会识别失败,可以修改提取逻辑同时兼容两种前缀:const getTokenFromHeaders = (req) => { const { authorization } = req.headers; if (!authorization) return null; const [authType, token] = authorization.split(' '); if (['Token', 'Bearer'].includes(authType)) { return token; } return null; }; - 保留前面添加的全局错误处理中间件,后续所有Token过期、签名不匹配、Token缺失等鉴权异常,都会被该中间件捕获并返回标准401响应,不会再直接抛500错误。
测试时注意重新生成有效期内的Token,不要用已经过期的示例Token测试。
内容的提问来源于stack exchange,提问作者Caldera500
相关产品推荐
相关产品推荐

