小心 JWT 炒作

2025-05-25

小心 JWT 炒作

GitHub 上的许多文章、课程和项目“启动器”都建议在面向客户端的 API 上使用 JSON Web Token (JWT) 作为会话令牌。

JWT 作为一项技术被过度炒作,它已经成为所有身份验证令牌的默认设置,而没有在有意义的地方使用。

🔐 什么是 JWT?🔐

JWT 是一种令牌格式,它包含一个 JSON 对象,其中包含一些标准化字段,并以标准化方式进行签名。令牌还包含有关其签名方式的信息,以便客户端可以验证令牌。

然后,这个签名对象可以通过任何机制发送给用户。它通常通过 HTTP 响应主体或类似 Cookie 的 Base64 编码的标头传递。客户端将 JWT 发送到服务器,服务器会检查签名,如果是有效令牌,则会执行相应的操作。

在前端客户端应用程序中,您可以将 JWT 存储在本地存储或 Cookie 中,并在每次请求 API 时将其发送。在这种情况下,操作是从 API 返回一些数据。

JWT 的好处在于,令牌存储了用户的所有详细信息以及用户对资源的权限。当用户发送有效的 JWT 时,您的 API 无需访问数据库等其他资源来获取权限数据。

这与使用简单的 Session ID 不同。使用此机制,Session ID 通常以 Cookie 的形式发送到客户端。服务器会根据其保存的缓存列表验证 Session ID。然后,它会查找当前用户所需的所有信息以完成请求。在这种情况下,除了 Session ID 之外的所有状态都保留在后端服务器/数据库中。

如果您在“扇出”场景中需要调用多个服务,JWT 是一个绝佳的授权解决方案。使用会话 ID,每个服务都必须调用某个方法才能获取会话数据和用户数据。而使用 JWT,所有必需的权限都包含在请求中,服务只需验证签名即可。

这并不意味着 JWT 是 Web 应用程序上简单的 Web 客户端 -> 后端会话的最佳解决方案。

“它将使我的 API 变得无状态”

是的,JWT 可以消除后端对有状态会话存储的需求。如果您计划将所有用户数据和权限等放入令牌中,这样就无需在 API 上进行数据库调用来获取用户数据。听起来很棒,但是……

这可能是过早的优化

如果你正在构建一个客户端/服务器 Web 应用程序,并且预计每分钟数据库请求数少于 4,000 个(嗯,比如说 4,000 个),那么最低付费的 Postgres 和便宜的 5 或 10 美元的 Digital Ocean Droplet 就能轻松搞定。你不需要任何无状态的东西,甚至不需要 Memcached 或 Redis。

除非你预期大规模部署,否则对于大多数公司的产品,你可以先使用会话并扩展硬件,直到你拥有足够的资金和工程资源来添加其他功能,例如分布式服务和 JWT。不要过早地针对不存在的问题进行优化。

您的 API 对于用户数据来说真的是无状态的吗?

在一个实用的客户端到服务器的 Web 应用中,避免状态是非常困难的。难道每次请求时,你真的不会从数据库获取任何关于用户的其他信息吗?自从 JWT 发出以来,角色或支付状态可能都没有发生任何变化吗?用户和具体请求之间可能没有任何交集吗?

这种情况有可能存在,但总体来说不太可能。如果您使用的请求需要身份验证,那么您可能需要根据用户进行某种查找。

无法实现无状态基本账户管理

很多文章会教你如何设置并使用 JWT 登录,但却忽略了最难的部分——注销用户和将用户列入黑名单。这些功能的可行解决方案涉及状态维护。

如果你想要合法地让用户“注销”,那么你需要保存一个已被用户失效的 JWT 列表。这样你就有了一个在每次请求时都会检查的状态。

如果您使用盐来签署每个用户的令牌,以便稍后可以更改盐以注销用户,那么您必须在每次用户发出请求时检查盐的列表,现在您拥有在每次请求时检查的状态。

如果您希望能够阻止某个用户,因为他们的帐户负债、被删除或者他们在做坏事,那么现在您需要保留一个被阻止用户的列表,并且您有在每次请求时检查的状态。

您可以使用短期访问令牌和刷新令牌来解决这些问题,但现在您有两个令牌,并且您必须根据无效刷新令牌列表验证刷新令牌,并且现在您拥有在每次请求时检查的状态。

有状态的 JWT——“我只是将用户 ID 存储在我的 JWT 中”

您可以将用户标识符编码到 JWT 中的属性中,并将其用作会话 cookie,但现在您正在重新创建服务器会话,但使用 JWT 除外。

为什么要费心使用 JWT 包装器呢?直接使用某种会话库就行,不用 JWT 了。

“所有这些框架都支持 JWT,并且在浏览器和移动客户端上都能更好地运行”

Cookie 也是如此。Cookie 只是一个 HTTP 标头。任何 HTTP 客户端都可以读取和设置标头。Cookie 标头还为浏览器内置了 20 多年的安全性和功能(仅限 HTTPS、过期、站点范围、阻止 JavaScript 访问),并且针对 CSRF 令牌伪造等问题,存在众所周知且易于理解的修复方法。

每个后端 Web 框架都支持 HTTP 标头,并且实际上可能对 cookie 具有一流的支持,并将会话库(通过生成的 ID)绑定到某种数据存储。

“JWT 是安全的”

签名和验证非常安全。然而,许多文章和课程都提到将 JWT 存储在本地存储中。这并不安全。页面上的任何 JavaScript 都可以读取并使用它。

你的页面上几乎肯定存在一些并非你编写的 JavaScript,它们来自 NPM 包或 CDN。这种漏洞注入方式以前就发生过,以后也一定会再次发生。

本地存储的替代方案是将 JWT 存储在 Cookie 中。因此,现在您需要像保护老式的 Session ID 一样保护 Cookie。

在后端,你需要确保使用 HTTPS,并且需要确保不容易受到 XSS 攻击。你还必须在每次请求时验证 JWT 的签名和有效期。

那么你应该怎么做呢?

好吧,如果您正在构建 http 客户端应用程序和后端,那么您可能不需要 JWT。

JWT 在分布式系统中可用于权限管理,但对于您的简单应用程序来说,它很可能是一个错误的解决方案,并且它使事情变得比使用 ID 和 Cookie 的会话存储更复杂或更不安全。

因此,在将它添加到你的新应用中之前,一定要确保你知道为什么要使用 JWT,并了解它的局限性!!😊

文章来源:https://dev.to/darraghor/be-careful-of-the-jwt-hype-train-3e81
PREV
在 Upwork 上开发:从每小时 20 美元到每小时 80 美元
NEXT
使用 Python 的类型注释