为什么需要双 Token?
-
单 Token 模型通常存在一个核心矛盾:安全性与用户体验难以兼顾。
-
如果 Token 过期时间很短:安全性高,但用户频繁掉线
-
如果 Token 过期时间很长:用户体验好,但一旦泄露风险极大
-
-
双 Token 的核心思路是:把“短期访问权限”和“长期刷新能力”拆开。
-
Access Token:短期有效(例如 5~30 分钟),用于接口请求
-
Refresh Token:长期有效(例如 7~30 天),用于换取新的 Access Token
-
这样一来,即使 Access Token 被窃取,攻击窗口也被压缩在较短时间内。
双 Token 的核心原理
双 Token 机制包含两个核心令牌:Access Token(访问令牌)和Refresh Token(刷新令牌),二者有效期、用途、存储方式完全不同,可以精准解决单 Token 的所有痛点。
双令牌核心差异对比
| 特性维度 | Access Token(访问令牌) | Refresh Token(刷新令牌) |
|---|---|---|
| 核心用途 | 用于所有业务接口鉴权,证明用户实时身份 | 仅用于刷新 Access Token,不参与任何业务请 |
| 有效期 | 短期有效,建议 15~30 分钟 | 长期有效,建议 7~30 天 |
| 安全级别 | 低风险、高频使用,泄露后仅短期有效 | 高风险、低频使用,是身份续期的唯一凭证 |
| 存储方式 | 前端内存/普通存储,随请求携带 | 优先 HttpOnly Cookie,杜绝 XSS 窃取 |
通俗化理解
可以把双 Token 机制类比为「景区通行体系」:
- Access Token = 一次性入园门票:有效期短,只能用于游玩参观(访问业务接口),过期立即失效,丢了也影响不大
- Refresh Token = 次卡(可以凭次卡换取入园门票):有效期长,不能直接入园游玩,但可以凭此免费兑换新的一次性入园门票(刷新 Access Token)
这套机制的核心逻辑:用短期令牌承担高频业务风险,用长期令牌保障登录连续性,从而达到风险隔离。
双 Token 基本业务流程
完整的双 Token 登录、鉴权、刷新流程,覆盖用户从登录到退出的全生命周期,是实现无感刷新的核心依据。
首次登录流程
- 用户输入账号密码,前端提交登录请求至后端
- 后端校验账号密码无误后,同时生成两个 Token:短期 Access Token、长期 Refresh Token
- 后端返回双 Token 给前端,同时将 Refresh Token 关联用户信息存入 Redis(用于失效管控)
- 前端接收令牌:Access Token 存入内存/本地存储,Refresh Token 写入 HttpOnly Cookie
- 登录成功,跳转首页,后续所有业务请求携带 Access Token 鉴权
正常业务请求流程
- 前端发起接口请求,请求头自动携带 Access Token
- 后端校验 Token 有效性(是否过期、签名是否正确)
- 校验通过,正常返回业务数据;校验失败,返回对应状态码 401
核心:Token 过期无感刷新流程
当 Access Token 过期、Refresh Token 未过期时,触发无感刷新,用户全程无感知,无需重新登录:
- 前端请求接口,后端检测 Access Token 过期,返回 401 Token 过期状态码
- 前端拦截器捕获 401 错误,暂停当前所有业务请求,防止重复报错
- 前端携带 Refresh Token,单独发起刷新 Token 专用请求
- 后端校验 Refresh Token 有效且未过期,生成全新的 Access Token返回前端
- 前端更新本地 Access Token,重新发起之前失败的业务请求
- 请求成功,用户正常操作,全程无弹窗、无跳转
注意点
双 Token 不是万能方案,若存储和使用不当,依然存在安全漏洞。
令牌存储安全区分
- Access Token:推荐存入 localStorage/sessionStorage + 内存,不长期留存,即使被 XSS 窃取,短时间过期风险低
- Refresh Token:禁止存入本地存储,必须存入 HttpOnly + Secure Cookie,杜绝 XSS 攻击窃取,仅允许后端读取
前端逻辑容错优化
- 增加请求锁机制:避免多个接口同时 401,重复发起刷新 Token 请求,造成接口冗余
- 失败请求队列缓存:刷新 Token 期间的所有请求排队等待,刷新成功后批量重试,保证业务不中断
- 主动过期预判:前端可在 Access Token 过期前 5 分钟主动触发刷新,规避用户操作卡顿
If you enjoyed this, leave a comment~