停止使用 JWT

争论范围

  • 大多数参与者区分了两种主要用例:
    • 基于浏览器的用户会话。
    • 服务到服务 / 后端令牌。
  • 广泛的温和共识:JWT 往往不适合浏览器会话,但在后端和联合身份场景中可以很好,甚至是理想选择。

用于基于浏览器的会话的 JWT

  • 批评者说,与放在 HttpOnly cookie 中的简单不透明会话 ID 相比,JWT 增加了复杂性;如果同一台服务器既签发又验证它们,就没有实际收益。
  • 提出的主要痛点:
    • 很难/很别扭地撤销和退出登录,尤其是按设备退出登录。
    • 可重放性和长寿命令牌。
    • 倾向于把敏感或可变数据塞进令牌里,从而带来缓存失效和安全问题。
  • 有人认为:如果你本来就需要一个数据存储(用于用户、权限),那就直接把会话状态存在那里,避免为会话使用密码学。

安全属性与实现陷阱

  • 历史问题:alg=none、算法降级/混淆、库把公钥当作 HMAC 密钥接受、默认值不佳。
  • 有人认为这些是库的 bug,而且大多已经修复;其他人则说,这些问题源于一个鼓励踩坑和复杂性的规范。
  • 对如今 JWT 到底有多“不安全”存在分歧:
    • 一派:“如果你限制算法并使用好库,JWT 是没问题的。”
    • 另一派:“规范鼓励误用;CVE 仍在不断出现;更安全的设计已经存在。”

撤销、“无状态”认证与退出登录

  • 核心张力:JWT 被宣传为“无状态”,但安全的退出登录和被攻破后的处理需要状态:
    • 撤销列表 / 黑名单。
    • 按用户的“早于某时间均无效”时间戳。
    • 密钥轮换方案。
  • 有人认为,一旦你加入这些状态,你就失去了相对于传统会话的主要优势。
  • 也有人反驳说,撤销列表比完整会话存储小得多,而且更容易在全局复制。

Cookie、存储,以及 XSS/CSRF

  • 强烈支持在浏览器会话中使用 HttpOnly、Secure、SameSite cookie。
  • 许多人警告不要把 JWT 存在 localStorage 中,因为会被 XSS 窃取;有些人认为如果你“根本不允许不可信 JS”那问题不大,另一些人则认为这不现实。
  • 有观点指出,HttpOnly 可以防止令牌被盗,但不能阻止由 XSS 驱动的滥用。

替代方案与更广泛的生态

  • 提到的替代方案包括:不透明随机令牌、签名 cookie、PASETO、macaroons、SAML/OIDC 模式、自定义方案。
  • 有人称赞 PASETO/macaroons 的设计更能抵抗误用,但指出生态和采用度有限。
  • 还有几位认为“停止使用 JWT”这一说法过于夸张或像标题党;他们更倾向于“有针对性且谨慎地使用 JWT”。