文章

Access Token 与 Refresh Token 如何配合

语之溪

·

Java

·

⚠️ 本文最后更新于2026年01月31日,已经过了205天没有更新,若内容或图片失效,请留言反馈

用户登录成功后,系统需要在后续请求中识别身份。如果只发一个长期有效的 Token,使用方便,但令牌泄露后的风险时间也会变长;如果 Token 有效期很短,用户又会频繁重新登录。

Access Token 与 Refresh Token 的组合,是在访问便利性和风险控制之间做分工:Access Token 用于访问业务接口,生命周期较短;Refresh Token 用于获取新的访问凭证,生命周期较长但使用范围更窄。

两种 Token 各自负责什么

Access Token
- 携带或关联用户身份
- 随业务请求发送
- 有效期较短
- 被网关或服务校验

Refresh Token
- 只用于刷新凭证
- 不应访问普通业务接口
- 有效期较长
- 需要更严格地存储与撤销

两个 Token 不能只是在过期时间上不同。服务端还需要能够区分它们的用途,避免 Refresh Token 被当作 Access Token 使用。

基本登录与刷新流程

用户提交登录凭据
    -> 认证服务校验
    -> 签发 Access Token
    -> 签发 Refresh Token
    -> 客户端访问业务接口
    -> Access Token 到期
    -> 客户端提交 Refresh Token
    -> 认证服务验证并签发新凭证

刷新过程中不需要再次提交密码,但这不代表 Refresh Token 可以无限使用。账号状态、令牌状态和安全策略仍然要重新检查。

Access Token 为什么要短一些

Access Token 会频繁出现在请求中,接触面较大。缩短有效期可以减少泄露后的可用时间。

有效期不能只复制固定数字,需要结合:

  • 系统风险等级;
  • 用户操作频率;
  • 客户端类型;
  • 是否有敏感操作;
  • 是否支持撤销;
  • 异常登录检测能力。

过短会导致频繁刷新,增加认证服务压力;过长则扩大泄露风险。具体时长需要通过实际使用和安全要求调整。

Refresh Token 需要服务端状态

JWT 常被描述为“无状态”,但 Refresh Token 如果完全无法撤销,用户退出、修改密码或账号被禁用后,旧令牌可能仍然可以换取新凭证。

因此我更关注服务端是否能够记录或判断:

  • Refresh Token 是否已签发;
  • 对应用户和客户端;
  • 是否过期;
  • 是否已撤销;
  • 是否已被替换;
  • 最后一次使用时间;
  • 账号当前是否允许登录。

可以存储令牌标识或哈希,而不是直接保存完整明文 Token。

刷新时进行轮换

每次刷新只返回新的 Access Token,而继续使用同一个 Refresh Token,能够实现基本续期,但旧刷新凭证长期有效。

更严格的方式是 Refresh Token Rotation:

提交 Refresh Token A
    -> 验证 A 有效
    -> 将 A 标记为已使用或撤销
    -> 签发 Access Token B
    -> 签发 Refresh Token B

之后再次使用 A,应被拒绝。若 A 在已经使用后又出现,可能意味着令牌被复制,需要根据策略撤销相关会话。

轮换会增加状态管理和并发处理难度。例如客户端同时发起两个刷新请求时,第二个请求可能使用已经失效的旧令牌,因此客户端也要避免并发刷新。

客户端如何避免重复刷新

多个请求同时发现 Access Token 过期时,不应该各自发起刷新。

第一个失败请求
    -> 创建刷新任务
其他失败请求
    -> 等待同一个刷新任务
刷新成功
    -> 更新凭证
    -> 重放允许重试的请求

重放请求要谨慎。查询请求通常更容易重试,创建、支付或状态变更类请求可能产生重复副作用,需要依赖幂等设计和业务规则。

Token 放在哪里

客户端存储方式需要根据 Web、移动端和威胁模型决定。

Web 场景常见选择包括内存、受保护 Cookie 和浏览器存储。它们各有风险:

  • JavaScript 可读存储更容易受到 XSS 影响;
  • Cookie 需要正确设置 HttpOnlySecureSameSite
  • 自动携带 Cookie 时需要考虑 CSRF;
  • 内存存储在页面刷新后需要恢复会话。

不能只说某一种方式绝对安全。重点是明确攻击面,并配合 HTTPS、内容安全策略、CSRF 防护和最小有效期。

移动端应使用系统提供的安全存储能力,不把令牌写进普通日志、明文配置或可公开备份区域。

刷新接口要做哪些检查

收到 Refresh Token 后,认证服务至少需要确认:

  • 签名或随机令牌是否合法;
  • 类型是否为刷新凭证;
  • 是否在有效期内;
  • 服务端状态是否允许使用;
  • 用户是否存在且未被禁用;
  • 客户端或会话是否匹配;
  • 是否触发轮换或重复使用规则。

验证失败时,不应返回详细到可以帮助攻击者枚举账号或令牌状态的内部信息。

退出登录和修改密码

退出登录不能只删除客户端 Token。如果服务端允许 Refresh Token 继续换取新凭证,旧会话仍可能恢复。

可以在这些场景撤销刷新凭证:

  • 用户主动退出;
  • 修改密码;
  • 账号被禁用;
  • 管理员强制下线;
  • 检测到令牌重复使用;
  • 用户选择退出所有设备。

Access Token 在短有效期内可能仍然有效。若业务要求立即失效,需要增加黑名单、令牌版本或其他服务端校验,但这也会增加每次请求的状态查询成本。

一个脱敏的响应结构

{
  "accessToken": "<short-lived-token>",
  "refreshToken": "<long-lived-token>",
  "tokenType": "Bearer",
  "expiresIn": 900
}

这只是结构示例,不包含 HAOVP 的真实 Token、有效期和接口响应。公开日志和截图中也不能展示真实令牌。

网关和认证服务如何分工

在微服务架构中,可以让认证服务负责登录、签发、刷新和撤销;网关负责对普通业务请求进行基础 Access Token 校验和身份传递。

认证服务:
登录与凭据校验
Token 签发与刷新
Refresh Token 状态
退出与撤销

网关:
识别受保护路由
校验 Access Token
清理伪造身份头
向下游传递可信身份

业务服务:
校验具体数据和操作权限

刷新接口应由认证服务处理,不能让普通业务服务接受 Refresh Token。

Access Token 与 Refresh Token 配合的核心,不是简单准备两个字符串,而是让短期访问、长期续期、轮换、撤销和客户端存储形成完整闭环。Access Token 降低长期暴露风险,Refresh Token 保持会话连续性;真正的安全性来自用途隔离、服务端状态和异常场景处理。

现在已有 8 次阅读,0 条评论,0 人点赞
评论:共0条
发表
搜索 消息 足迹 排行
你还不曾留言过..
你还不曾留下足迹..
博主 不再显示
博主
未知作品 歌曲封面
立即安装