跳至主要內容

JWT 续签方案详解

Hirsuntech大约 12 分钟

JWT 续签方案详解

在前后端分离架构下,JWT(JSON Web Token)认证方案广泛应用。

然而,JWT的无状态性使得其续签功能的实现变得棘手。

本次分享将结合实际经验,介绍如何在不同场景下实现JWT的续签功能。

为什么需要JWT续签

JWT的基本流程

  1. 用户登录后,认证中心颁发JWT,并返回给客户端。
  2. JWT包含用户基本信息和过期时间(Exp)。
  3. 客户端保存JWT,并在访问后台核心接口时附加在请求头或Cookie中。

JWT过期问题

  • JWT设置了过期时间(如30分钟)。
  • 超过有效期后,后端校验JWT时会抛出403异常。
  • 客户端接收到异常后,会将用户踢回登录页。
1735305754022.png

不设置过期时间的风险

  • 长期/永久有效的JWT可能被恶意使用。
  • 未设置过期时间的JWT会成为“太空垃圾”,带来安全隐患。

续签的必要性

  • 避免用户操作过程中被强制退出。
  • 延长JWT的有效时间,提升用户体验。

续签的限制

  • JWT续签必须有退出机制,避免无限续签导致的安全问题。

场景一:前台不允许改变 JWT 令牌

解决方案:利用后台的Redis

1735306265887.png
1735306265887.png
  1. 用户登录

    • 认证中心颁发JWT,并向Redis中写入一个键值对。
    • 键(Key)通过用户数据和客户端特征数据生成的MD5摘要。
    • 值(Value)不重要,主要是设置Redis的过期时间(如2小时)。
  2. 客户端请求

    • 客户端向后端服务发起请求,附带JWT。
    • 后端服务校验JWT并提取用户ID和客户端特征数据,生成MD5摘要。
    • 在Redis中查询该Key是否存在。
  3. Redis校验

    • 如果Key不存在,JWT无效,拒绝服务。
    • 如果Key存在,查询剩余有效时间:
      • 超过1小时:正常响应。
      • 少于1小时:续签1小时。
  4. 退出机制

    • 用户离开超过2小时,Redis中的Key过期被删除。
    • 用户重新操作时,JWT无效,要求重新登录。

为什么数据库使用 md5 作为 key?

  • 通过用户数据和客户端特征数据生成MD5摘要,提高安全性。
  • 防止 JWT 被盗取后在不同环境下使用。

改进方案:使用 JWT + 环境参数作为 key。

优缺点

  • 优点:利用Redis特性控制JWT有效时间,实现续签。
  • 缺点:JWT变为有状态,增加了系统复杂性。而不是那种随处可用的无状态。

3. 场景二:前台允许改变JWT令牌

解决方案:使用两个JWT(Access Token 和 Refresh Token)

  1. 用户登录

    • 认证中心返回两个JWT:Access Token和Refresh Token。
    • Access Token(如30分钟有效),主要用于业务交互。
    • Refresh Token(如60分钟有效),用于续签。
  2. 客户端请求

    • 在请求头或Cookie中附带两个Token。
    • 后端服务校验Access Token:
      • 有效:正常响应。
      • 过期:校验Refresh Token。
  3. 续签逻辑

    • Refresh Token有效:通过认证中心刷新生成新的Access Token和Refresh Token。
    • 将新Token返回给客户端,替换旧Token。
  4. 退出机制

    • 超过Refresh Token有效期(如1小时),要求重新登录。

安全性考虑

  • Refresh Token用于续签,解决Access Token失效后的续签问题。
  • 防止无限续签,设置合理的过期时间。

优缺点

  • 优点:轻量级实现,前端Token可变。
  • 缺点:客户端需要较大的改造工作,处理多个Token。

4. 解决重发JWT的问题

问题描述

  • 多线程客户端可能同时发出多个请求,导致生成多个JWT。
  • 可能出现Token覆盖或交叉写入问题。

解决方案:计时Map数据结构

  1. 认证中心设置计时Map

    • 记录几秒内生成的JWT数据。
    • 同样的JWT请求在短时间内返回相同的Token。
  2. 实现效果

    • 避免多线程请求导致的Token覆盖或交叉写入问题。
    • 提高系统的一致性和稳定性。

5. 总结

  • JWT续签可以提高用户体验,避免频繁登录。
  • 不同场景下有不同的实现方案:
    • 前台不允许改变JWT:利用Redis控制有效时间。
    • 前台允许改变JWT:使用Access Token和Refresh Token。
  • 续签方案需要考虑安全性和系统复杂性。
  • 解决重发JWT的问题,确保系统的一致性。

通过以上方案,可以在不同场景下实现JWT的续签功能,提高系统的安全性和用户体验。如果你有更好的方案,欢迎在评论区分享,大家一起拓宽思路。

感谢大家的支持,记得点赞哦!