如何使用express-jwt返回非401的自定义状态码?
解决express-jwt可选认证场景下令牌过期返回自定义状态码的问题
要实现可选认证(credentialsRequired: false)时,令牌存在但过期返回402状态码的需求,你需要在express-jwt的中间件之后添加一个自定义的错误处理中间件——因为当credentialsRequired: false时,express-jwt不会主动抛出错误,而是将验证失败的信息存储在req.authInfo中。
步骤1:保留原有的express-jwt配置
你的decodeAuthIfExist配置不需要修改,保持原样即可:
const jwt = require('express-jwt'); const jwksRsa = require('jwks-rsa'); // 确保已引入依赖 exports.decodeAuthIfExist = jwt({ secret: jwksRsa.expressJwtSecret({ cache: true, rateLimit: true, jwksRequestsPerMinute: 5, jwksUri: `https://${process.env.AUTH0_DOMAIN}/.well-known/jwks.json` }), credentialsRequired: false, audience: process.env.AUTH0_AUDIENCE, issuer: `https://${process.env.AUTH0_DOMAIN}/`, algorithms: ['RS256'] });
步骤2:添加自定义错误处理中间件
创建一个中间件来检查req.authInfo中的错误信息,针对令牌过期的情况返回402状态码:
exports.handleOptionalAuthError = (req, res, next) => { // 检查是否存在认证错误 if (req.authInfo) { // 判断是否为令牌过期错误 if (req.authInfo.name === 'TokenExpiredError') { return res.status(402).json({ error: 'TokenExpired', message: '你的认证令牌已过期,若需要请重新获取' }); } // 你也可以扩展处理其他令牌错误,比如无效签名 // else if (req.authInfo.name === 'JsonWebTokenError') { // return res.status(400).json({ error: 'InvalidToken', message: '无效的认证令牌' }); // } } // 没有错误则继续执行后续中间件 next(); };
步骤3:在路由中组合使用中间件
将自定义错误处理中间件放在decodeAuthIfExist之后,确保能捕获到认证错误:
app.get('/resource', auth.decodeAuthIfExist, auth.handleOptionalAuthError, resource.get);
原理说明
当credentialsRequired: false时:
- 如果请求中没有令牌,express-jwt不会做任何处理,直接进入下一个中间件
- 如果请求中有令牌但验证失败(比如过期、签名错误),express-jwt会将错误信息存入
req.authInfo,而不会抛出默认的401错误 - 我们的自定义中间件通过检查
req.authInfo,识别令牌过期的错误类型,返回自定义的402状态码,避免应用自动跳转到登录页
内容的提问来源于stack exchange,提问作者kane
相关产品推荐
相关产品推荐

