先记住这个答案
Refresh Token Rotation 是令牌刷新策略:每次用 Refresh Token 换取新 Access Token 时,服务端同时签发一个新的 Refresh Token,并使旧 Refresh Token 失效。若检测到已作旧的 Refresh Token 被重放,通常视为攻击,服务端应撤销该用户会话关联的整个令牌族,强制重新登录;但需先排除客户端并发请求导致的误判,可设置短期宽限或要求客户端互斥。这能限制令牌泄露后的横向移动窗口。
- 刷新时作废旧令牌、签发新令牌,可限制泄露影响。
- 检测到旧令牌复用通常视为重放,应撤销整个令牌族(排除并发场景)。
- 处理并发刷新需允许短暂宽限期并记录异常。
轮换与重放检测的信号机制
Refresh Token Rotation 的核心是服务端为每个会话维护一个令牌族。当客户端用 Refresh Token RT1 换取新 Access Token 时,服务端验证 RT1 有效后,生成新的 RT2 并返回,同时将 RT1 标记为已使用。此后只有 RT2 能继续刷新。这样攻击者即使拿到 RT1,也无法用它获取新令牌。
重放检测依赖一个状态存储:服务端保存每个 Refresh Token 的状态(有效、已使用、已撤销)。当收到一个标记为已使用的 Refresh Token 时,通常可判定为重放,此时服务端应撤销该令牌族中所有有效令牌并通知客户端重新认证,但需先确认非客户端并发所致;可设置短期宽限窗口以容忍并发误判。检测时机是校验令牌存在且有效后,再检查其状态标志。
移动端并发刷新导致误判的工程场景
假设一个 App 在启动时同时发起了两个并发 API 请求,两个请求都因 Access Token 过期而触发了刷新逻辑。两个线程几乎同时使用同一个 Refresh Token RT1 调用刷新端点。服务端处理第一个请求成功,生成 RT2,并标记 RT1 已使用;接着处理第二个请求时发现 RT1 已使用,按重放处理,撤销整个令牌族,导致用户被强制登出。
解决方式是引入短期并发容忍:服务端为刚被使用的旧令牌保留一个短期宽限窗口(如30秒),在这个窗口内重复使用只返回新的 RT2(或提示客户端重试),但不立即撤销整族。更可靠的是客户端做刷新互斥:在同一时间只允许一个刷新请求进行,其他请求等待或共享结果。服务端可同时记录异常,若超过宽限仍重放则触发撤销。
失效边界与安全策略权衡
严格的撤销整族策略在大多数场景有效,但在用户多设备登录时会有问题:每台设备各有独立 Refresh Token,但它们属于同一用户会话族吗?通常设计为每个设备独立令牌族,这样撤销某设备令牌不影响其他设备。若将同一账号所有登录视为一整个族,用户在一台设备重放会导致全家桶登出,体验糟糕。因此族粒度应按会话而非账号。
另一个边界是:若攻击者已在宽限期内使用了旧令牌并获得了新令牌,服务端无法察觉。为了增强检测,可绑定令牌指纹(如设备信息、IP),异常变更时触发告警。但过分严格的 IP 检测会导致移动网络切换频繁触发重放,所以应结合风险评分,而不是一有变化就撤销。实现时需权衡安全性和可用性。
容易答错的地方
- 轮换等于每次刷新都完全改动令牌串
- 轮换关键是状态作废,而不只是随机生成新令牌。若仅生成新令牌却不使旧令牌失效,攻击者仍可重放旧令牌。真正的轮换必须将旧令牌标记为已使用,并在检测到重放时撤销整个族。
- 重放检测发现后只撤销当前被重放的那一个令牌
- 攻击者重放旧令牌通常意味着已获取该令牌,可能已经用过或即将用其他令牌。只撤销一个令牌无法阻止攻击者使用同族中其他有效令牌。安全做法是撤销整个令牌族,即该会话下的所有 Refresh Token 和 Access Token。
面试官还会怎么问?
Refresh Token 轮换时如何预防并发请求导致误杀?
客户端应做刷新互斥,只允许一个刷新请求在途,其他请求等待新 Access Token。服务端可提供短期宽限:旧令牌在短时间内重用仅返回最新令牌,不触发撤销,但记录异常。宽限时长需低于攻击者利用时间窗口(通常30秒~1分钟)。
撤销整个令牌族时,已经发出的 Access Token 如何立即失效?
Access Token 若为 JWT 无状态,本身无法立即撤销。可依赖短期过期(如5分钟),或服务端维护可撤销的访问令牌列表(黑名单),每次请求校验。也可用结合 Refresh Token 族状态:当检测到重放时,将族内所有令牌标记为撤销,并拒绝后续请求。
Refresh Token 轮换与使用唯一 refresh token ID 有什么区别?
轮换是每次刷新都生成新令牌,并作废旧令牌;而固定 refresh token ID 是令牌不变,仅更新最后使用时间。轮换能主动限制泄露窗口,配合重放检测可形成家族撤销机制,安全性更高。固定 ID 若泄露,攻击者可长期使用,除非另设设备指纹。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。