首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Token续期的5种方案

Token续期的5种方案

作者头像
苏三说技术
发布2025-08-24 11:22:29
发布2025-08-24 11:22:29
30400
代码可运行
举报
文章被收录于专栏:苏三说技术苏三说技术
运行总次数:0
代码可运行

前言

今天我们来聊聊一个看似简单却让无数开发者栽跟头的问题——Token续期

你以为Token续期只是重置时间?90%的系统安全漏洞由此而生!

当用户正在提交重要表单时突然跳转到登录页面,或者系统在高峰期因Token并发刷新而崩溃,这些问题的根源往往在于Token续期策略设计不当

欢迎加入苏三的星球,你将获得:100万QPS短链系统、复杂的商城微服务系统、苏三AI项目、刷题吧小程序、秒杀系统、商城系统、秒杀系统、代码生成工具等8个项目的源代码开发教程技术答疑

一、Token续期的本质

Token续期不是简单的时间重置,而是安全、用户体验和系统性能的三方博弈

我们先看一个典型事故:

代码语言:javascript
代码运行次数:0
运行
复制
// 错误案例:简单过期的Token检查
public boolean validateToken(String token) {
    return JwtUtil.getExpiration(token).after(new Date());
}

这种实现会导致:

  1. 用户操作中断(Token突然过期)
  2. 安全风险(旧Token继续有效)
  3. 并发问题(多个请求同时触发刷新)

Token续期的三大核心问题

  1. 何时续期:提前多久刷新最合理?
  2. 如何续期:单Token还是双Token?有状态还是无状态?
  3. 安全防控:如何防止令牌劫持和并发风暴?

下面我跟大家一起聊聊工作中最常用的5种主流方案,希望对你会有所帮助。

二、单Token方案

2.1 基础实现与致命缺陷

代码语言:javascript
代码运行次数:0
运行
复制
public String refreshToken(String oldToken) {
    String username = JwtUtil.parseUsername(oldToken);
    return JwtUtil.generateToken(username, 30 * 60); // 直接生成新Token
}

三大致命缺陷

  1. 旧Token在有效期内依然可用(安全黑洞)
  2. 多个请求同时触发刷新会导致多个有效Token并存(并发灾难)
  3. 无法强制下线用户(状态失控)

2.2 黑名单优化方案

代码实现

代码语言:javascript
代码运行次数:0
运行
复制
public String safeRefresh(String oldToken) {
    // 旧Token加入黑名单(有效期比Token长5分钟)
    redis.setex("blacklist:"+oldToken, "1", 35 * 60); 
    
    String username = JwtUtil.parseUsername(oldToken);
    String newToken = JwtUtil.generateToken(username, 30 * 60);
    return newToken;
}

适用场景

  • 内部低安全系统
  • 短期活动页面
  • 快速原型开发

三、双Token方案

3.1 核心架构设计

3.2 安全增强:三验证机制

代码语言:javascript
代码运行次数:0
运行
复制
public TokenPair refreshTokens(String refreshToken) {
    // 1. JWT签名验证
    if (!JwtUtil.verifySignature(refreshToken)) {
        thrownew SecurityException("非法令牌");
    }
    
    // 2. 状态令牌验证
    String stateToken = extractStateToken(refreshToken);
    if (!redis.exists("state_token:" + stateToken)) {
        thrownew SecurityException("令牌已失效");
    }
    
    // 3. 设备绑定验证
    String deviceId = getDeviceIdFromRequest();
    if (!deviceId.equals(redis.get("bind_device:" + stateToken))) {
        thrownew SecurityException("设备变更需重新登录");
    }
    
    return generateNewTokenPair(refreshToken);
}

3.3 并发控制:分布式锁方案

代码语言:javascript
代码运行次数:0
运行
复制
public TokenPair safeRefresh(String refreshToken) {
    String lockKey = "refresh_lock:" + refreshToken;
    RLock lock = redissonClient.getLock(lockKey);
    
    try {
        if (lock.tryLock(2, 5, TimeUnit.SECONDS)) {
            return doRefresh(refreshToken);
        }
        throw new BusyException("系统繁忙,请重试");
    } finally {
        lock.unlock();
    }
}

适用场景

  • 金融系统
  • 电商平台
  • 企业级应用

四、自动续期方案

4.1 拦截器+滑动窗口

智能阈值计算

代码语言:javascript
代码运行次数:0
运行
复制
public boolean shouldRenew(Token token) {
    long remainTime = token.getExpireTime() - System.currentTimeMillis();
    long totalTime = token.getTotalValidTime();
    
    // 双阈值策略:绝对时间(5分钟)和相对时间(30%有效期)
    return remainTime <= Math.min(5 * 60 * 1000, 0.3 * totalTime);
}

4.2 Redis缓存续期方案

代码语言:javascript
代码运行次数:0
运行
复制
public void autoRenewToken(String headerToken) {
    String cacheKey = "token_cache:" + headerToken;
    String cacheToken = redis.get(cacheKey);
    
    if (cacheToken == null) throw new TokenExpiredException("令牌已完全过期");
    
    if (JwtUtil.isAboutToExpire(cacheToken)) { 
        String newToken = generateNewToken();
        // 关键:Token更新但缓存Key不变
        redis.setex(cacheKey, newToken, 2 * 60 * 60);
        response.setHeader("X-New-Token", newToken);
    }
}

4.3 Gateway全局过滤器方案

代码语言:javascript
代码运行次数:0
运行
复制
@Component
@Order(-100)
publicclass TokenRenewFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, Chain chain) {
        String token = extractToken(exchange.getRequest());
        
        if (renewService.isRenewRequired(token)) {
            String newToken = renewService.renewToken(token);
            exchange.getResponse().getHeaders().set("X-New-Token", newToken);
        }
        
        return chain.filter(exchange);
    }
}

适用场景

  • 微服务架构
  • 前后端分离应用
  • 高并发用户系统

五、分布式环境特殊挑战

5.1 多设备会话管理

设备冲突解决方案

代码语言:javascript
代码运行次数:0
运行
复制
public void handleLogin(User user, String deviceType) {
    String oldSessionKey = "user_devices:" + user.getId() + ":" + deviceType;
    String oldToken = redis.get(oldSessionKey);
    
    if (oldToken != null) {
        redis.del("token_cache:" + oldToken); // 使旧Token失效
    }
    
    String newToken = generateToken();
    redis.set(oldSessionKey, newToken);
}

5.2 跨服务令牌验证

代码语言:javascript
代码运行次数:0
运行
复制
public boolean validateTokenAcrossServices(String token) {
    // 1. 本地快速验证
    if (JwtUtil.verifyWithLocalKey(token)) return true;
    
    // 2. 查询认证中心
    return authCenterClient.validateToken(token);
}

六、五大方案对比

方案

安全性

用户体验

实现复杂度

适用场景

性能影响

典型应用

单Token基础版

★☆☆☆☆

★★☆☆☆

★☆☆☆☆

内部测试系统

原型开发

单Token+黑名单

★★☆☆☆

★★★☆☆

★★☆☆☆

低风险Web应用

企业内网

双Token基础版

★★★☆☆

★★★★☆

★★★☆☆

常规Web/APP

电商平台

双Token+三验证

★★★★★

★★★☆☆

★★★★☆

金融/支付系统

银行APP

自动续期方案

★★★★☆

★★★★★

★★★★☆

高用户体验要求系统

中高

SAAS应用

七、方案如何选型?

八、最佳实践与避坑指南

8.1 安全黄金法则

  1. 令牌时效控制
    • Access Token ≤ 30分钟
    • Refresh Token ≤ 7天(需配合刷新次数限制)
  2. 敏感操作二次认证
代码语言:javascript
代码运行次数:0
运行
复制
public void processSensitiveOperation(String token) {
   if (isSensitiveOperation()) {
       if (!smsVerifyService.verify(getCurrentUser())) {
           throw new SecurityException("需要短信验证");
       }
   }
   // 执行操作
}

8.2 性能优化关键

  1. 异步刷新队列
  1. 本地缓存验证
代码语言:javascript
代码运行次数:0
运行
复制
// 使用Caffeine实现本地缓存
LoadingCache<String, Boolean> tokenCache = Caffeine.newBuilder()
   .maximumSize(10_000)
   .expireAfterWrite(5, TimeUnit.MINUTES)
   .build(key -> redis.exists("valid_token:" + key));

8.3 十大避坑指南

  1. 永远不要用长有效期的Access Token
  2. Refresh Token必须是一次性使用的
  3. 客户端必须实现静默更新机制
  4. 分布式环境下必须用RedLock处理并发刷新
  5. 敏感操作必须二次认证
  6. 黑名单有效期需长于Token有效期
  7. 设备变更必须重新认证
  8. 监控Refresh Token的使用频率
  9. 定期轮换签名密钥
  10. 实现令牌撤销接口

好的Token管理系统应该像人体的自主神经系统——平时感受不到它的存在,但在需要时总能及时响应。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-08-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 苏三说技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 一、Token续期的本质
    • Token续期的三大核心问题
  • 二、单Token方案
    • 2.1 基础实现与致命缺陷
    • 2.2 黑名单优化方案
  • 三、双Token方案
    • 3.1 核心架构设计
    • 3.2 安全增强:三验证机制
    • 3.3 并发控制:分布式锁方案
  • 四、自动续期方案
    • 4.1 拦截器+滑动窗口
    • 4.2 Redis缓存续期方案
    • 4.3 Gateway全局过滤器方案
  • 五、分布式环境特殊挑战
    • 5.1 多设备会话管理
    • 5.2 跨服务令牌验证
  • 六、五大方案对比
  • 七、方案如何选型?
  • 八、最佳实践与避坑指南
    • 8.1 安全黄金法则
    • 8.2 性能优化关键
    • 8.3 十大避坑指南
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档