JWT令牌设置60秒过期却永不失效问题排查求助
问题根源及修复方案
1. JWT的iat字段使用毫秒级时间戳(核心错误)
在tokenManager.js的issueJWT和issueRefreshToken函数中,你手动设置了iat: Date.now(),但JWT标准里的iat(签发时间)要求是Unix时间戳(秒级),而Date.now()返回的是毫秒级时间戳。
这会导致JWT库计算过期时间时,把毫秒数当成秒数处理——比如当前毫秒时间是1718000000000,当成秒的话就是1718000000,相当于50多年后的时间,再加上60秒的有效期,令牌自然永远不会过期。
修复代码:
修改tokenManager.js中的payload部分,将iat改为秒级时间戳:
const issueJWT = (user) => { const expiresIn = 60; const payload = { sub: user.id, iat: Math.floor(Date.now() / 1000), // 替换Date.now()为秒级时间戳 }; const signedToken = jwt.sign(payload, PRIV_KEY, { expiresIn: expiresIn, algorithm: 'RS256' }); return { token: "Bearer " + signedToken, expires: expiresIn }; }; const issueRefreshToken = (user) => { const expiresIn = '7d'; const payload = { sub: user.id, iat: Math.floor(Date.now() / 1000), // 同样修改这里 }; const refreshToken = jwt.sign(payload, PRIV_KEY, { expiresIn: expiresIn, algorithm: 'RS256' }); return refreshToken; };
2. 优化中间件的错误处理(可选但推荐)
当前authMiddleware.js中,所有JWT验证错误都返回403,无法区分令牌过期、签名无效等不同情况,不利于调试和前端处理。可以修改为:
const authenticateJWT = (req, res, next) => { const authHeader = req.headers.authorization; if (authHeader) { const token = authHeader.split(' ')[1]; jwt.verify(token, PUB_KEY, { algorithms: ['RS256'] }, (err, user) => { if (err) { // 根据错误类型返回对应状态码 if (err.name === 'TokenExpiredError') { return res.status(401).json({ message: '令牌已过期' }); } return res.sendStatus(403); // 其他验证错误(如签名无效)返回403 } req.user = user; next(); }); } else { res.sendStatus(401); } };
3. 验证修复效果
- 重启服务器,重新获取JWT令牌
- 等待60秒后,用该令牌请求
/info/getInfo接口,此时应该返回对应过期提示或状态码,证明过期逻辑生效。
内容的提问来源于stack exchange,提问作者joisberg
相关产品推荐
相关产品推荐

