JWT令牌默认过期时间及严格登出功能实现咨询
JWT默认过期时间与严格登出实现方案
一、JWT默认过期时间说明
当调用jwt.sign()时不指定expiresIn参数,生成的JWT没有过期时间限制,令牌会永久有效——除非你主动通过其他机制使其失效,或者签名密钥泄露导致令牌被伪造。
对比你提供的两段代码:
- 第一段明确设置
expiresIn: "1h",令牌会在1小时后自动过期:
function generateToken(payload) { return jwt.sign(payload, JWT_SECRET, { expiresIn: "1h" }); }
- 第二段未指定
expiresIn,生成的令牌永久有效:
function generateToken(payload) { return jwt.sign(payload, JWT_SECRET); }
二、严格登出功能实现(手动登出+版本更新触发登出)
JWT本身是无状态的,无法直接主动作废令牌,要实现你需要的严格登出逻辑,可结合令牌黑名单和版本号校验两种机制:
1. 令牌黑名单:处理手动登出
- 维护一个存储(比如Redis、内存数据库),用户手动登出时,将其当前使用的JWT令牌加入黑名单;
- 每次接口请求验证令牌时,先检查该令牌是否在黑名单中,若在则拒绝请求。
2. 版本号校验:处理应用版本更新触发登出
- 在JWT的payload中加入应用版本号字段;
- 后端维护当前有效的应用版本号,发布新版本时更新这个值;
- 验证令牌时,检查payload中的版本号是否与后端当前有效版本一致,不一致则拒绝请求,强制用户重新登录。
综合实现代码示例
生成带版本号的令牌
function generateToken(payload) { // 把应用版本号加入payload,版本号可从环境变量配置 const tokenPayload = { ...payload, appVersion: process.env.APP_VERSION }; // 可设置一个较长的过期时间(比如30天),结合黑名单处理手动登出 return jwt.sign(tokenPayload, JWT_SECRET, { expiresIn: "30d" }); }
令牌验证与登出逻辑
const jwt = require('jsonwebtoken'); const redis = require('redis'); const redisClient = redis.createClient(); // 验证令牌 async function verifyToken(token) { try { // 先检查令牌是否在黑名单 const isBlacklisted = await redisClient.get(`blacklist:${token}`); if (isBlacklisted) { throw new Error('令牌已失效,请重新登录'); } const decoded = jwt.verify(token, JWT_SECRET); // 校验应用版本 if (decoded.appVersion !== process.env.APP_VERSION) { throw new Error('应用已更新,请重新登录'); } return decoded; } catch (err) { throw err; } } // 手动登出 async function logout(token) { const decoded = jwt.decode(token); if (decoded.exp) { // 计算令牌剩余有效期,黑名单有效期设为剩余时间 const remainingTime = decoded.exp - Math.floor(Date.now() / 1000); await redisClient.setEx(`blacklist:${token}`, remainingTime, 'true'); } else { // 永久令牌则永久加入黑名单 await redisClient.set(`blacklist:${token}`, 'true'); } }
内容的提问来源于stack exchange,提问作者Shruti Patil
相关产品推荐
相关产品推荐

