找回密码
 立即注册
首页 业界区 业界 Token续期的5种方案

Token续期的5种方案

痨砖 前天 13:28
前言

今天我们来聊聊一个看似简单却让无数开发者栽跟头的问题——Token续期
你以为Token续期只是重置时间?90%的系统安全漏洞由此而生!
当用户正在提交重要表单时突然跳转到登录页面,或者系统在高峰期因Token并发刷新而崩溃,这些问题的根源往往在于Token续期策略设计不当
一、Token续期的本质

Token续期不是简单的时间重置,而是安全、用户体验和系统性能的三方博弈
我们先看一个典型事故:
  1. // 错误案例:简单过期的Token检查
  2. public boolean validateToken(String token) {
  3.     return JwtUtil.getExpiration(token).after(new Date());
  4. }
复制代码
这种实现会导致:

  • 用户操作中断(Token突然过期)
  • 安全风险(旧Token继续有效)
  • 并发问题(多个请求同时触发刷新)
Token续期的三大核心问题


  • 何时续期:提前多久刷新最合理?
  • 如何续期:单Token还是双Token?有状态还是无状态?
  • 安全防控:如何防止令牌劫持和并发风暴?
下面我跟大家一起聊聊工作中最常用的5种主流方案,希望对你会有所帮助。
二、单Token方案

2.1 基础实现与致命缺陷
  1. public String refreshToken(String oldToken) {
  2.     String username = JwtUtil.parseUsername(oldToken);
  3.     return JwtUtil.generateToken(username, 30 * 60); // 直接生成新Token
  4. }
复制代码
三大致命缺陷

  • 旧Token在有效期内依然可用(安全黑洞)
  • 多个请求同时触发刷新会导致多个有效Token并存(并发灾难)
  • 无法强制下线用户(状态失控)
2.2 黑名单优化方案

1.webp

代码实现
  1. public String safeRefresh(String oldToken) {
  2.     // 旧Token加入黑名单(有效期比Token长5分钟)
  3.     redis.setex("blacklist:"+oldToken, "1", 35 * 60);
  4.    
  5.     String username = JwtUtil.parseUsername(oldToken);
  6.     String newToken = JwtUtil.generateToken(username, 30 * 60);
  7.     return newToken;
  8. }
复制代码
适用场景

  • 内部低安全系统
  • 短期活动页面
  • 快速原型开发
三、双Token方案

3.1 核心架构设计

2.webp

3.2 安全增强:三验证机制
  1. public TokenPair refreshTokens(String refreshToken) {
  2.     // 1. JWT签名验证
  3.     if (!JwtUtil.verifySignature(refreshToken)) {
  4.         throw new SecurityException("非法令牌");
  5.     }
  6.    
  7.     // 2. 状态令牌验证
  8.     String stateToken = extractStateToken(refreshToken);
  9.     if (!redis.exists("state_token:" + stateToken)) {
  10.         throw new SecurityException("令牌已失效");
  11.     }
  12.    
  13.     // 3. 设备绑定验证
  14.     String deviceId = getDeviceIdFromRequest();
  15.     if (!deviceId.equals(redis.get("bind_device:" + stateToken))) {
  16.         throw new SecurityException("设备变更需重新登录");
  17.     }
  18.    
  19.     return generateNewTokenPair(refreshToken);
  20. }
复制代码
3.3 并发控制:分布式锁方案
  1. public TokenPair safeRefresh(String refreshToken) {
  2.     String lockKey = "refresh_lock:" + refreshToken;
  3.     RLock lock = redissonClient.getLock(lockKey);
  4.    
  5.     try {
  6.         if (lock.tryLock(2, 5, TimeUnit.SECONDS)) {
  7.             return doRefresh(refreshToken);
  8.         }
  9.         throw new BusyException("系统繁忙,请重试");
  10.     } finally {
  11.         lock.unlock();
  12.     }
  13. }
复制代码
适用场景

  • 金融系统
  • 电商平台
  • 企业级应用
四、自动续期方案

4.1 拦截器+滑动窗口

3.webp

智能阈值计算
  1. public boolean shouldRenew(Token token) {
  2.     long remainTime = token.getExpireTime() - System.currentTimeMillis();
  3.     long totalTime = token.getTotalValidTime();
  4.    
  5.     // 双阈值策略:绝对时间(5分钟)和相对时间(30%有效期)
  6.     return remainTime <= Math.min(5 * 60 * 1000, 0.3 * totalTime);
  7. }
复制代码
8.3 十大避坑指南


  • 永远不要用长有效期的Access Token
  • Refresh Token必须是一次性使用的
  • 客户端必须实现静默更新机制
  • 分布式环境下必须用RedLock处理并发刷新
  • 敏感操作必须二次认证
  • 黑名单有效期需长于Token有效期
  • 设备变更必须重新认证
  • 监控Refresh Token的使用频率
  • 定期轮换签名密钥
  • 实现令牌撤销接口
好的Token管理系统应该像人体的自主神经系统——平时感受不到它的存在,但在需要时总能及时响应。
最后说一句(求关注,别白嫖我)

如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下我的同名公众号:苏三说技术,您的支持是我坚持写作最大的动力。
求一键三连:点赞、转发、在看。
关注公众号:【苏三说技术】,在公众号中回复:进大厂,可以免费获取我最近整理的10万字的面试宝典,好多小伙伴靠这个宝典拿到了多家大厂的offer。
本文收录于我的技术网站:http://www.susan.net.cn

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册