← 返回信息流
AI 资讯Hacker News·3 小时前

为何建议停止使用 JWT:潜在风险与替代方案

原标题:Stop Using JWTs

速览

JWT 因其无状态特性被广泛采用,但存在密钥管理复杂、撤销困难及潜在的安全漏洞。本文指出盲目使用 JWT 可能带来的风险,并建议根据具体场景评估是否采用更严格的认证机制。

AI 深度解读

背景

在 Web 开发领域,JSON Web Token (JWT) 曾被视为实现无状态身份验证的“银弹”。随着微服务架构和前后端分离模式的普及,许多开发者倾向于将用户凭证存储在 JWT 中,并直接存放在浏览器的 localStoragesessionStorage 中,以简化会话管理。

然而,这种趋势引发了安全社区的强烈反弹。本文源自 Hacker News 上的一篇高赞讨论,其核心观点直指当前 Web 安全实践中的一个普遍误区:JWT 并非为长期用户会话设计,将其用于维持用户登录状态不仅效率低下,更存在严重的安全隐患。文章引用了安全专家 joepie91 的研究以及 Ryan Degg 关于避免使用 localStorage 存储认证凭据的建议,旨在纠正开发者对“无状态”和“JWT”的过度迷信。

核心内容

1. JWT 的设计初衷与局限

JWT 规范本身仅适用于极短生命周期的令牌(通常建议为 5 分钟或更短)。会话(Session)需要维持用户较长时间的登录状态,这与 JWT 的设计初衷背道而驰。试图用 JWT 处理长期会话,本质上是在滥用该规范。

2. “无状态”认证的伪命题

许多开发者推崇 JWT 是因为其“无状态”特性,认为这样可以轻松扩展且无需服务器存储。然而,文章指出,真正的“无状态”认证在安全层面上并不可行。

  • 必须拥有状态:为了安全地处理令牌,系统必须维护某种状态。
  • 数据冗余:如果必须建立数据存储,直接存储所有会话数据(即传统 Session)比存储令牌并额外维护一个令牌黑名单或验证机制更为高效和安全。
  • 效率低下:仅存储简单会话令牌的 JWT 比传统的 Cookie 会话更不灵活,且没有任何性能优势。

3. 规范本身的安全缺陷

JWT 规范并未得到安全专家的广泛信任。原始规范允许创建伪造令牌,且可能存在其他设计缺陷。对于任何涉及安全和身份验证的场景,依赖一个不被信任的规范是高风险行为。

4. 关于 Google 使用 JWT 的误解

有人反驳称“Google 也在用 JWT”,因此 JWT 是安全的。文章澄清了这一误解:

  • 用途不同:Google 在浏览器中用于用户会话的是传统的 Cookie 会话,而非 JWT。
  • SSO 传输:Google 使用 JWT 纯粹作为单点登录(SSO)的传输机制,用于在不同服务器或主机间转移登录会话。这属于 JWT 的合理用例。
  • 资源差异:Google 拥有顶尖的安全专家团队来构建和维护更安全的 JWT 实现,其实际安全性与普通开发者自行实现的 JWT 不可同日而语。

5. 替代方案:PASETO 与传统 Cookie

  • 短期令牌替代者:如果确实需要短期、签名的令牌,推荐使用 PASETO (Platform-Agnostic Security Tokens)。PASETO 被设计为比 JWT 更安全,旨在解决 JWT 的诸多规范缺陷。
  • 会话管理的最佳实践:对于维持用户登录,应使用传统的 Cookie 会话。现代 Web 服务器框架(如 Express、Django、Spring 等)通常都内置了会话支持,配置并不复杂。

6. 避免使用 localStorage 存储认证凭据

文章再次强调,不应将 JWT 令牌或任何认证凭据存储在 localStoragesessionStorage 中。这极易导致跨站脚本攻击(XSS),因为 JavaScript 可以轻易读取这些存储中的数据。相比之下,HttpOnly Cookie 能有效防止 JavaScript 访问,从而抵御 XSS 攻击。

7. 实施建议

对于不熟悉会话设置的开发者,文章指出这并非新技术,不应过度依赖第三方教程。大多数框架(如 Node.js 的 Express)只需启用中间件(如 express-session)并连接适当的存储后端(如 connect-session-knex 配合 PostgreSQL、MySQL 或 SQLite)即可轻松实现。

关键要点

  • JWT 不适用于长期会话:JWT 规范仅适用于短期令牌(<5分钟),用于维持用户登录状态是设计误用。
  • 无状态认证不安全:真正的无状态认证需要巨大的资源支持,普通开发者无法安全实现。必须维护状态,直接存储会话数据比存储 JWT 更优。
  • JWT 规范存在缺陷:原始规范允许伪造令牌,不被安全专家信任,不应将其用于核心安全逻辑。
  • Cookie 会话优于 JWT 会话:传统的 HttpOnly Cookie 会话更安全、更高效,且能更好地防御 XSS 攻击。
  • 警惕 localStorage:严禁在 localStorage 中存储 JWT 或认证凭据,应使用 HttpOnly Cookie。
  • PASETO 是更好的替代方案:若需短期签名令牌,请使用 PASETO 而非 JWT。
  • 不要盲目模仿大厂:Google 等大厂使用 JWT 仅限于特定的 SSO 传输场景,且有顶级安全团队维护,其实现与普通开发者的自建 JWT 完全不同。
  • 回归基础:利用框架内置的会话管理功能(如 express-session)是简单且安全的做法,无需过度复杂化。

意义与影响

这篇文章对 Web 开发实践产生了重要的纠偏意义。长期以来,“JWT 即现代”、“无状态即优雅”的观念在开发者社区中根深蒂固,导致大量应用暴露在潜在的安全风险中。

  1. 安全意识的提升:它促使开发者重新审视身份验证机制的安全性,从盲目追求“无状态”转向关注“实际安全性”。强调 HttpOnly Cookie 和服务器端会话存储,有助于降低 XSS 攻击带来的凭证泄露风险。
  2. 技术选型的理性回归:文章揭示了 JWT 在会话管理上的局限性,引导开发者根据具体场景选择合适工具。对于短期令牌传输,PASETO 等更现代的规范值得考虑;对于长期会话,传统机制依然是经过时间检验的最佳实践。
  3. 对“最佳实践”的批判性思考:通过澄清 Google 等大厂的使用场景,文章提醒开发者不要断章取义地引用大厂案例,而应深入理解技术背后的设计原理和安全边界。
  4. 推动规范演进:对 JWT 规范缺陷的指出,有助于推动安全社区对现有标准的反思,并促进如 PASETO 等更严谨标准的普及。

总之,这篇解读呼吁开发者回归安全本质,摒弃对 JWT 的盲目崇拜,采用更稳健、更安全的传统会话管理方式,并在确需令牌时使用更安全的替代方案。

查看原文 →gist.github.com