老司机:非谷歌规模就无需使用JWT?


该文认为:在大多数情况下,您不应使用 JSON Web Tokens (JWT) 作为身份验证令牌,尤其是你的系统规模没有达到 Google/Facebook 规模运营时,特别规模是每秒处理少于 10k 个请求情况下更不应该使用JWT。

什么是JWT
JSON Web Tokens(JWT)是一种用于认证的令牌标准,它包含头部、负载和签名。JWT的核心思想是,任何拥有相应验证密钥的人都可以验证负载的真实性,并且没有被篡改。JWT规范(RFC 7519)建议使用一些众所周知的注册声明名称,如发行者、受众、主题、过期时间等。

JWT主要好处

  • 接收者不需要连接到用户数据库来验证令牌的真实性:

在像Google这样的大型系统中,认证服务可以是一个独立的服务,像其他服务一样进行管理和扩展,并且是唯一需要访问集中式用户数据库的服务。所有其他服务可以仅依赖JWT中存储的信息,而不需要访问用户数据库,这将避免用户数据库成为瓶颈。

刷新令牌
为了实现注销或会话失效,认证令牌应该有一个相当短的生命周期,最多5分钟。客户端还会收到第二个令牌,即所谓的刷新令牌,它可以用来从认证服务请求一个新的认证令牌。这给了认证服务一个机会去查询用户数据库,看看用户或特定会话是否在此期间被阻止。

刷新令牌,而不是对令牌进行认证,是一种“真正的”会话性质的令牌:

  • 刷新令牌代表与认证服务的会话(可以被撤销)
  • 而认证令牌只是用于最多几个请求的派生凭据。

从Google的角度来看,这将保持会话活跃的责任委托给了客户端,即不是Google服务器的责任。

假设您不是 Google。请检查以下哪些情况适用于您,如果答案是Yes,就不需要JWT:

  • 您想要实现注销令牌,因此现在您要保留有效 JWT 的允许列表或已撤销 JWT 的拒绝列表。要检查这一点,您需要在每次请求时访问数据库。
  • 您需要能够完全阻止用户,因此您检查数据库中的“用户活跃”标志。每次请求时您都会访问数据库。
  • 您需要在用户对象和数据库中的其他对象之间建立额外的关系。每次请求时您都会访问数据库。
  • 您的服务会对数据库中的数据执行任何操作。每次请求都会访问数据库。


总结
对于大多数应用程序来说,使用 JWT 作为身份验证令牌的弊端和复杂性超过了其带来的好处。

使用 JWT 进行身份验证的主要问题是:

  1. 由于 JWT 被设计为无状态的,因此在到期之前撤销/使令牌无效非常困难。如果令牌被泄露,则可能导致安全风险。
  2. 管理安全签名/验证密钥以及实施 JWT 缺陷解决方法的复杂性增加。
  3. 由于 JWT 的范围和特性过于广泛,存在潜在的安全漏洞,从而导致实施错误。
  4. JWT 是为不记名令牌认证而设计的,其安全性低于所有权证明令牌。

与使用 JWT 相比,对于大多数应用程序来说,一种更简单、更安全的方法是使用存储在数据库中的不透明会话令牌以及用于实现可扩展性的缓存层。这可以轻松撤销令牌,降低复杂性并改善安全实践。

JWT 对于特定用例仍然有用,例如 API 身份验证或在各方之间安全地传输数据,但应该明智地使用它们,并清楚地了解它们的局限性和潜在的安全风险。

在不需要JWT时:

  1. 直接用Web框架提供的常规会话机制即可,这种方式已经经受了时间的考验。
  2. 如果您需要一些大型系统,使用valkey来存储会话数据,。这样,还是使用经过身份验证的用户ID来查询数据库,但对于未经身份验证的请求,它可能会更快/使用更少的资源。


网友讨论
1、如果只有一个单体网络应用程序作为身份提供者,单体内部做出所有身份验证,那么你可能不需要 JWT。
在多个服务间共享会话本身就是一个分布式系统问题,需要注意许多安全问题,而使用令牌可能是一个不错的选择。

2、在大多数用例中,随机令牌就可以了,一切都取决于它如何存储以及在何处存储。
但这也意味着你可以将 JWT 用作大多数应用程序的“随机令牌”,生成它们的成本并不高,并且只在以下情况下使用额外的容量:

  • - 当你想检查签名时(例如在到达你的应用层之前拒绝)
  • - 在恢复会话之前存储您想要的非敏感 base64 数据

创建和处理 JWT 的成本和复杂程度完全取决于您的需要,因此在我看来,它具有足够的灵活性,可以轻松使用且几乎不会产生任何惩罚。

3、JWT 的优点在于它们会过期,每个缓存都有 TTL,因此您只需将条目的 TTL 设置为您正在缓存的令牌的到期日期即可,无需每晚手工清理。


4、这篇文章似乎根本没有提到微服务架构?对我来说,这是使用 JWT 的主要原因。这样你就可以通过微服务服务到服务调用链传递身份验证,如果你没有微服务,那么就没有什么理由使用 JWT了。
单体系统不要使用 JWT,但有很多公司(无论好坏)都使用微服务。

5、JWT 最适合零信任机器对机器身份验证,在确认请求者身份后,您可能还想授权某些动词/操作/角色。

6、即使在不及谷歌规模的较小的环境中运行,也应该使用JWT:

  • 1) 您可能不希望应用服务器直接访问认证服务或认证数据库。当敏感数据跨服务共享时,您可能没有足够的资源来控制员工对敏感数据的访问。您可能希望将有限的资源用于对包含最敏感数据的系统进行安全审计,而将这些系统与其他系统分开则会有所帮助。
  • 2)根据您使用的第三方服务,在授权和其他服务之间建立连接可能并不现实,即使建立了连接,延迟也可能会很严重,因此您不希望它阻止每个请求。这对于混合环境尤为重要,例如,在主机库中使用了 20 年的数据库,其中包含您的用户数据,以及由顾问在 PaaS 上为您构建的新服务。
  • 3)人们觉得失效JWT令牌是个噩梦,但你只需要授权服务签署失效令牌并传递给面向客户端的服务,而这些服务只需要在授权令牌的最大 TTL 内保留这些令牌,之后就可以将它们从缓存中驱逐。这可能是由于拥有像谷歌这样的庞大环境,也可能只是一种降低成本的方法,因为你需要按字节存储或按云上的出站请求付费。你可以说,存储失效数据与存储会话数据一样糟糕,但关键问题是 "在哪里?"和 "多长时间?"。
  • 4) 您可能不希望将敏感的用户数据存储在您希望托管应用程序的辖区内。这不是公司的大问题,而是取决于您所提供服务的性质。