撤销与强制下线

可撤销优先

设计认证系统时,先想「怎么撤销」,再想「怎么签发」。Access Token 可能被盗、Refresh Token 可能泄露、设备可能丢失,如果凭证签发了就收不回来,安全就无从谈起。

什么时候要撤销

  • 用户主动退出登录。
  • 修改密码后,撤销其他设备的会话。
  • 管理员冻结账号。
  • 风控检测到异常登录。
  • Refresh Token 被重放(检测到泄露)。

撤销要动哪些东西

一次撤销不是「删一个标记」那么简单,要联动:

撤销会话
  ├─> 会话记录标记 revoked_at
  ├─> 挂在该会话下的 Refresh Token 立即失效
  ├─> Access Token 靠短有效期快速失效(或进黑名单)
  └─> 写入审计日志(谁、何时、哪台设备)

JWT 的撤销延迟怎么处理

JWT 无状态,撤销不立即生效。两种处理:

  • 短有效期为主:Access Token 只活几分钟,撤销延迟窗口可控。
  • 黑名单 / 版本号兜底:把被撤销的 jti 放进 Redis 黑名单,或给用户加 token_version,JWT 里带上版本号,验签时比对。版本号一变,所有旧 Token 一起失效——这招特别适合「改密后全部下线」。

强制下线的两种用法

「强制下线」不只是登出,还分精确和全局两种:

  • 精确下线:用户只撤销某一台异常设备,其它设备不受影响(设备管理页的「退出此设备」)。
  • 全局下线:改密、冻结、账号被盗时,让该用户所有会话失效。

实现全局下线,用版本号方案最顺手:user_account.token_version 加一,所有旧 JWT 验签失败;同时把所有未撤销的会话标记为 revoked。

撤销链的完整流程

一次改密后的撤销流程

用户修改密码

先验证当前身份

步骤 1 · 动作输入旧密码 / 触发 MFA,防止会话被利用

更新 password_hash

步骤 2 · 动作用新密码重新慢哈希

token_version + 1

步骤 3 · 动作所有旧 JWT 立即失效

撤销除当前设备外的会话

步骤 4 · 判断保留当前登录态,其它设备强制下线

通知用户

步骤 5 · 动作告知密码已修改,非本人操作请立即处理

写入审计日志

步骤 6 · 结果记录改密来源与撤销范围
风险窗口被迅速关闭

小结

  • 撤销是认证系统的必备能力,不是加分项。
  • 撤销要联动会话、Refresh Token、Access Token 和审计。
  • JWT 的撤销延迟,用短有效期 + 黑名单 / 版本号控制。
  • 「改密后强制全部下线」用版本号方案最干净。

下一节看会话的另一面:多设备管理与会话风控。