停止在浏览器会话中使用 JWT:辩论分析
这场辩论的核心结论是,虽然 JSON Web Tokens (JWTs) 对于服务间通信和短寿命的身份验证缓存非常有效,但它们通常不是浏览器端用户会话的正确工具。主要的冲突源于无状态性(statelessness)的感知收益与会话撤销(session revocation)的实际必要性之间的权衡。
不支持在浏览器会话中使用 JWT 的理由
JWTs 经常因其设计上的无状态性而被批评为不适合用户会话。这造成了一个关键的安全漏洞:在不向系统中重新引入状态的情况下,无法在令牌到期之前使其失效。
撤销困境
如果用户注销或会话被劫持,无状态的 JWT 在其生存时间 (TTL) 到期之前仍然有效。为了解决这个问题,开发者通常会实现一个无效令牌的“撤销列表”(或黑名单)。然而,正如社区成员所指出的,如果你为了确保安全而维护一个有状态的撤销令牌列表,你实际上已经重新引入了状态,从而抵消了使用 JWTs 而非传统会话 Cookie 的主要架构优势。
复杂度 vs. 简单性
对于许多应用程序来说,传统的会话 Cookie——即服务器在数据库中存储会话 ID 并对每个请求进行验证——更加简单且更安全。这种方法允许立即终止会话,并并且无需在客户端进行加密签名和验证的开销,从而更轻松地管理用户状态。
支持 JWTs 以及替代实现方案的理由
尽管存在批评,许多工程师认为,在特定的约束和模式下使用 JWTs 是合适的。
服务间通信
业界有一个强烈的共识,即 JWTs 非常适合微服务之间的内部通信。在这些场景下,一个中央身份验证服务可以铸造一个令牌,子服务可以使用公钥 (RS256) 进行验证,而无需为每个请求查询中央数据库。这降低了延迟并防止了子服务需要直接访问身份验证数据库的需求。
短寿命令牌与刷新模式
为了减轻无状态性的风险,一些开发者使用极短寿命的访问令牌(例如 5 分钟)并结合刷新令牌系统。
"I use 5 minutes. Most sessions on my site last 4-10 minutes. Worst case scenario, a malicious user is able to access certain read-only resources for a few minutes."
这种方法在保持避免为每个请求查询数据库带来的性能优势的同时,限制了被劫持令牌的漏洞窗口。
高级撤销策略
有人认为,对于 JWTs 的撤销列表实际上比完整的会话存储更高效。因为只需要跟踪被撤销的令牌(而不是所有活跃的会话),被查询的数据集要小得多。此外,像 minimum_issued_at 这样的模式可以用于使所有在特定时间戳之前颁发的令牌失效(例如,在“从所有设备注销”事件期间),而无需跟踪单个令牌 ID。
替代方案与行业标准
虽然辩论的焦点在于 JWTs 与会话(Sessions)的对比,但一些技术贡献者建议转向更现代的标准:
- PASETO (Platform-Agnostic Security Tokens): 被建议作为 JWTs 的更安全替代方案,因为它避免了 JWT 规范中的一些设计缺陷并降低了实现错误的风险。
- JWE (JSON Web Encryption): 对于必须在令牌内存储敏感数据的场景,建议使用 JWE,因为标准的 JWTs 仅经过签名(编码),而非加密。
使用场景总结
| 使用场景 | 推荐方法 | 原因 | | :--- | :--- | | Browser User Sessions | Session Cookies | 立即撤销,复杂度较低 | | Microservices / API | JWTs | 解耦身份验证,减轻数据库负载 | | High-Security Actions | Re-authentication | 无论令牌状态如何,都需要密码/MFA | | Internal Service Auth | PASETO / JWT | 标准化,经加密验证 |