JWT 续签方案详解
大约 12 分钟
JWT 续签方案详解
在前后端分离架构下,JWT(JSON Web Token)认证方案广泛应用。
然而,JWT的无状态性使得其续签功能的实现变得棘手。
本次分享将结合实际经验,介绍如何在不同场景下实现JWT的续签功能。
为什么需要JWT续签
JWT的基本流程
- 用户登录后,认证中心颁发JWT,并返回给客户端。
- JWT包含用户基本信息和过期时间(Exp)。
- 客户端保存JWT,并在访问后台核心接口时附加在请求头或Cookie中。
JWT过期问题
- JWT设置了过期时间(如30分钟)。
- 超过有效期后,后端校验JWT时会抛出403异常。
- 客户端接收到异常后,会将用户踢回登录页。
不设置过期时间的风险
- 长期/永久有效的JWT可能被恶意使用。
- 未设置过期时间的JWT会成为“太空垃圾”,带来安全隐患。
续签的必要性
- 避免用户操作过程中被强制退出。
- 延长JWT的有效时间,提升用户体验。
续签的限制
- JWT续签必须有退出机制,避免无限续签导致的安全问题。
场景一:前台不允许改变 JWT 令牌
解决方案:利用后台的Redis
用户登录:
- 认证中心颁发JWT,并向Redis中写入一个键值对。
- 键(Key)通过用户数据和客户端特征数据生成的MD5摘要。
- 值(Value)不重要,主要是设置Redis的过期时间(如2小时)。
客户端请求:
- 客户端向后端服务发起请求,附带JWT。
- 后端服务校验JWT并提取用户ID和客户端特征数据,生成MD5摘要。
- 在Redis中查询该Key是否存在。
Redis校验:
- 如果Key不存在,JWT无效,拒绝服务。
- 如果Key存在,查询剩余有效时间:
- 超过1小时:正常响应。
- 少于1小时:续签1小时。
退出机制:
- 用户离开超过2小时,Redis中的Key过期被删除。
- 用户重新操作时,JWT无效,要求重新登录。
为什么数据库使用 md5 作为 key?
- 通过用户数据和客户端特征数据生成MD5摘要,提高安全性。
- 防止 JWT 被盗取后在不同环境下使用。
改进方案:使用 JWT + 环境参数作为 key。
优缺点
- 优点:利用Redis特性控制JWT有效时间,实现续签。
- 缺点:JWT变为有状态,增加了系统复杂性。而不是那种随处可用的无状态。
3. 场景二:前台允许改变JWT令牌
解决方案:使用两个JWT(Access Token 和 Refresh Token)
用户登录:
- 认证中心返回两个JWT:Access Token和Refresh Token。
- Access Token(如30分钟有效),主要用于业务交互。
- Refresh Token(如60分钟有效),用于续签。
客户端请求:
- 在请求头或Cookie中附带两个Token。
- 后端服务校验Access Token:
- 有效:正常响应。
- 过期:校验Refresh Token。
续签逻辑:
- Refresh Token有效:通过认证中心刷新生成新的Access Token和Refresh Token。
- 将新Token返回给客户端,替换旧Token。
退出机制:
- 超过Refresh Token有效期(如1小时),要求重新登录。
安全性考虑
- Refresh Token用于续签,解决Access Token失效后的续签问题。
- 防止无限续签,设置合理的过期时间。
优缺点
- 优点:轻量级实现,前端Token可变。
- 缺点:客户端需要较大的改造工作,处理多个Token。
4. 解决重发JWT的问题
问题描述
- 多线程客户端可能同时发出多个请求,导致生成多个JWT。
- 可能出现Token覆盖或交叉写入问题。
解决方案:计时Map数据结构
认证中心设置计时Map:
- 记录几秒内生成的JWT数据。
- 同样的JWT请求在短时间内返回相同的Token。
实现效果:
- 避免多线程请求导致的Token覆盖或交叉写入问题。
- 提高系统的一致性和稳定性。
5. 总结
- JWT续签可以提高用户体验,避免频繁登录。
- 不同场景下有不同的实现方案:
- 前台不允许改变JWT:利用Redis控制有效时间。
- 前台允许改变JWT:使用Access Token和Refresh Token。
- 续签方案需要考虑安全性和系统复杂性。
- 解决重发JWT的问题,确保系统的一致性。
通过以上方案,可以在不同场景下实现JWT的续签功能,提高系统的安全性和用户体验。如果你有更好的方案,欢迎在评论区分享,大家一起拓宽思路。
感谢大家的支持,记得点赞哦!