返回
创建于
状态
公开

在 Web 开发和 API 认证中,Access TokenRefresh Token 的组合(通常被称为“双 Token 机制”)是目前平衡安全性用户体验的主流方案。


1. 基本概念与区别

简单来说,Access Token 是“入场券”,而 Refresh Token 是“换票证”。

特性Access Token (访问令牌)Refresh Token (刷新令牌)
主要作用用于身份验证,携带它请求受保护的资源。用于获取新的 Access Token。
有效期(如 15 分钟 - 2 小时)。(如 7 天 - 30 天)。
存储位置通常存放在客户端内存或 localStorage通常存放在安全性更高的 HttpOnly Cookie 中。
发送频率(每次 API 请求都要携带)。(仅在 Access Token 过期时使用)。
暴露风险风险较高,因为频繁传输。风险较低,传输频率极低。

2. 为什么需要“双 Token”?

如果只使用一个长期的 Access Token,一旦该 Token 被窃取,攻击者将在很长一段时间内拥有该账户的完全访问权,且服务端很难主动使其失效。

双 Token 机制的核心逻辑:

  1. 安全性: Access Token 设为短期,即使泄露,攻击者的攻击窗口也非常窄。
  2. 体验感: Refresh Token 设为长期,用户不需要在 Access Token 过期后反复输入账号密码登录,系统会自动静默刷新。

3. 运行流程(双 Token 工作流)

  1. 登录阶段:
    • 用户输入账号密码。
    • 服务器验证成功,返回两个 Token:access_tokenrefresh_token
  2. 正常访问阶段:
    • 客户端将 access_token 放入 HTTP Header 中(通常是 Authorization: Bearer <token>)请求数据。
    • 服务器校验 Token 有效,返回数据。
  3. Token 过期阶段:
    • access_token 过期,服务器返回 401 Unauthorized 错误。
  4. 刷新阶段(自动):
    • 客户端拦截到 401 错误,自动将 refresh_token 发送到专门的刷新接口(如 /auth/refresh)。
    • 服务器校验 refresh_token
      • 有效: 返回一个新的 access_token
      • 无效/过期: 说明用户长久未操作,返回强制登录错误,清理本地缓存。

4. 进阶安全策略:Refresh Token Rotation(刷新令牌轮转)

为了进一步增强安全性,现在常用 Token Rotation 技术:

  • 每次使用 Refresh Token 换取新的 Access Token 时,服务器会同时返回一个新的 Refresh Token,并将旧的作废。
  • 好处: 如果攻击者窃取了 Refresh Token 并抢先刷新,当合法用户再次刷新时,服务器会发现“旧令牌已被使用”,从而识别出安全威胁,并立即作废该用户所有的 Token 强制重新登录。

5. 开发建议 (前端视角)

  • 无感刷新: 在 Axios 等请求库中使用 interceptors(拦截器)。在 Response 拦截器中捕获 401 状态码,挂起当前请求,执行刷新逻辑后再重试。
  • 防止并发: 如果页面同时发出多个请求且 Token 过期,需要确保只调用一次刷新接口(利用一个 isRefreshing 标志位或 Promise 队列)。

从**计算资源(CPU/内存/数据库)**的角度来看,Refresh Token 的处理过程通常比 Access Token 更消耗资源

我们可以从以下两个维度来拆解它们的开销:


1. 验证频率 vs 单次消耗

虽然单个 Refresh Token 的处理更重,但因为 Access Token 的调用频率极高,总体的系统负载往往集中在 Access Token 的验证上

维度Access Token (验证)Refresh Token (执行刷新)
触发频率极高(几乎每一次 API 调用)。(仅在 Access Token 过期时,如每小时 1 次)。
计算复杂度(通常仅需 CPU 进行解密和签名校验)。(涉及数据库 I/O、哈希计算、新 Token 生成)。
资源压力点CPU 密集型I/O 密集型(数据库/Redis)。

2. 为什么 Refresh Token 更“重”?

在标准的生产环境实现中,Refresh Token 的处理通常包含以下重资源操作:

  • 数据库/缓存查询: 为了安全性,Refresh Token 通常不是纯无状态的。服务端需要去数据库(或 Redis)中检查该 Token 是否被加入黑名单、是否已被撤销(Revoked),或者是否匹配用户当前的设备 ID。
  • 数据库写入(Token 轮转): 如果开启了 Refresh Token Rotation,每次刷新都要删除旧 Token 并插入新 Token,涉及一次数据库写操作。
  • 密码学开销: 需要重新生成两段复杂的随机字符串或 JWT 签名,并可能涉及对数据库中的 Token 进行加盐哈希比对。

3. Access Token 的“轻量”优势

相比之下,Access Token 通常设计为 自包含的 JWT (JSON Web Token)

  • 无需查库: 服务器只需要利用内存中的 Secret Key 对 Token 签名进行数学运算(HMAC 或 RSA 校验)。
  • 计算极快: 这种校验是在内存中完成的,耗时通常在微秒级别。

总结与优化策略

  • 性能瓶颈: 如果你的应用有数百万并发,Access Token 的签名校验(CPU 消耗)会成为主要瓶颈。此时通常会使用分布式网关(如 Kong 或 Nginx 插件)在入口处分担校验压力。
  • 数据库压力: 如果用户频繁掉线触发刷新,Refresh Token 的数据库读写会成为瓶颈。这也是为什么开发者通常将 Refresh Token 存储在 Redis 而不是 PostgreSQL/MySQL 中的原因。

简单结论:

  • 单次处理: Refresh Token 消耗大(因为要读写数据库)。
  • 整体系统负载: Access Token 消耗大(因为验证次数太多)。

Access Token(通常是 JWT)的校验中,选择 HMAC 还是 RSA 直接决定了系统的性能消耗安全性以及架构复杂度

由于 Access Token 的校验频率极高,理解这两者的计算开销差异至关重要。


1. 核心区别:对称 vs 非对称

特性HMAC (如 HS256)RSA (如 RS256)
算法类型对称加密(同一密钥)。非对称加密(私钥签发,公钥校验)。
密钥管理签发者和校验者必须共享同一个 Secret签发者持有 Private Key,校验者只需 Public Key
计算开销极低(仅需一次哈希运算)。较高(涉及大数模幂运算)。
安全性密钥一旦泄露,攻击者可伪造 Token。公钥泄露无妨,只有持有私钥的中心服务器能签发。

2. 计算资源消耗对比

从 CPU 消耗的角度来看,两者存在量级上的差异:

HMAC (对称加密 - 速度王者)

HMAC 校验本质上是执行两次哈希函数(如 SHA-256)。对于现代 CPU 来说,哈希运算有硬件加速,耗时通常在 纳秒 (ns)极低微秒 (μs) 级别。

  • 适用场景: 单体架构,或者内部微服务之间高度信任、统一配置中心分发密钥的场景。

RSA (非对称加密 - 安全卫士)

RSA 校验涉及复杂的数学运算(大数模幂)。虽然校验(使用公钥)比签名(使用私钥)快得多,但相比 HMAC,它仍然要慢 10 到 100 倍

  • 适用场景: 跨机构 API(如 Google Auth)、大型微服务架构(各服务只需公钥即可自主校验,无需联系认证中心)。

3. 为什么 RSA 在现代架构中更流行?

尽管 RSA 消耗更多 CPU 资源,但在分布式系统中,它的优势弥补了性能损失:

  1. 解耦与横向扩展: 认证中心(Auth Service)生成 Token 后,下游的几十个业务服务(Order, User, Payment)只需要持有公钥。即使某个业务服务被黑,黑客也拿不到私钥,无法伪造 Token。
  2. 安全性提升: 如果使用 HMAC,你必须把唯一的 Secret 分发到所有服务器。泄露风险随着服务器数量线性增长。

4. 性能折中方案:ECDSA

如果你既想要 RSA 的安全性(非对称),又想要 HMAC 的高性能(低消耗),现代开发通常会选择 ECDSA (椭圆曲线数字签名算法),如 ES256

  • 计算开销: 远小于 RSA,接近 HMAC。
  • 安全性: 非对称加密。
  • 长度: 生成的 Token 比 RSA 更短,节省网络带宽。

总结建议

如果你正在设计系统,可以参考以下逻辑:

  • 追求极致性能 / 小型项目:HMAC (HS256)。简单、快,注意保护好 Secret 即可。
  • 中大型微服务 / 对安全性敏感:RSA (RS256)。虽然 CPU 消耗稍高,但对于现代服务器来说,这点校验压力通常不是瓶颈。
  • 高性能分布式系统: 强烈建议使用 ECDSA (ES256),它是目前性能与安全的最佳平衡点。