采用“短寿命访问令牌 + 长寿命刷新令牌”的双令牌机制是平衡安全性与用户体验的标准方案。适用于 Web 及移动端应用,风险边界在于刷新令牌的存储安全必须高于访问令牌,且需具备撤销能力。
先说结论:双令牌机制通过分离权限时效,既限制泄露影响范围,又减少用户重复登录频次。
- 先判断:评估业务数据敏感度,决定访问令牌的生命周期级别。
- 优先做:实施访问令牌分钟级过期,配合刷新令牌自动续期。
- 再验证:确认令牌过期后接口拒绝访问,且刷新流程能无感获取新令牌。
快速处理思路
JWT 配置通常在服务端代码或网关层完成,核心是设置 payload 中的 exp claim。
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022,
"exp": 1516242622
}上述示例中 exp 减去 iat 即为过期时间,建议访问令牌设置为分钟级差值。
为什么会这样
JWT 无状态特性导致服务端无法主动撤销令牌,除非等待其自然过期。
一旦令牌泄露,攻击者在过期前均可冒用身份。缩短过期时间能减少泄露窗口,但过短会导致用户频繁登录。双令牌机制将高频验证的访问令牌设为短效,将用于获取新访问令牌的刷新令牌设为长效,从而在安全与体验间取得平衡。
分步处理
第一步:设置访问令牌短时效。
在生成 JWT 的服务端逻辑中,将 exp 字段设置为当前时间加上较短时长,行业常见实践为 15 分钟至 1 小时。
第二步:实现刷新令牌流程。
生成一个长期有效的刷新令牌(通常存储在服务端数据库或加密 Cookie 中),当访问令牌过期时,客户端使用刷新令牌请求新的访问令牌。
第三步:实施刷新令牌轮换。
每次使用刷新令牌获取新访问令牌时,同时颁发新的刷新令牌并使旧刷新令牌失效,防止刷新令牌重放攻击。
怎么验证是否生效
通过解码令牌检查 exp 字段,并模拟过期请求测试接口响应。
使用 jwt.io 或命令行工具解码访问令牌,确认 exp 时间戳符合预期。等待令牌过期后调用受保护接口,应返回 401 Unauthorized。随后调用刷新接口,应能获取新的有效访问令牌。
常见坑
将敏感令牌存储在 localStorage 易受 XSS 攻击,建议使用 HttpOnly Cookie。
服务端与客户端时间不同步可能导致令牌提前失效或验证失败,需确保服务器时间同步。刷新令牌若未做轮换处理,一旦泄露可被长期滥用。
常见问题
JWT 过期后能强制撤销吗?
原生 JWT 不支持主动撤销,需配合服务端黑名单或令牌版本机制实现。
刷新令牌应该存哪里?
建议存储在 HttpOnly 且 Secure 的 Cookie 中,避免 JavaScript 访问。
时钟偏差会导致验证失败吗?
会,验证服务端应允许少量的时钟偏差(Clock Skew),通常设置为几分钟。
参考来源
- RFC 7519: JSON Web Token (JWT) - IETF Standards
- OWASP Authentication Cheat Sheet - OWASP Foundation