身份验证:JWT使用与会话

Pou*_*366 89 session jwt

JWT在身份验证等情况下使用会话的优势是什么?

是用作独立方法还是在会话中使用?

The*_*aan 152

JWT没有比使用"会话"更有利.JWT提供了一种在客户端上维护会话状态而不是在服务器上执行它的方法.

人们在问这个时通常意味着"使用JWT而不是使用服务器端会话有什么好处"

使用服务器端会话时,您必须将会话标识符存储在数据库中,或者将其保留在内存中,并确保客户端始终命中同一服务器.这两者都有缺点.在数据库(或其他集中存储)的情况下,这成为瓶颈和维护的事情 - 实质上是对每个请求进行的额外查询.

使用内存中的解决方案,您可以限制水平扩展,会话将受到网络问题的影响(客户端在Wifi和移动数据之间漫游,服务器重新启动等)

将会话移动到客户端意味着您删除了对服务器端会话的依赖性,但它会带来一系列挑战.
- 安全存储令牌
- 安全运输
- JWT会话有时很难无效.
- 信任客户的索赔.

这些问题由JWT和其他客户端会话机制共享.

JWT特别解决了最后一个问题.它可能有助于理解JWT是什么:

这是一些信息.对于用户会话,您可以包括用户名和令牌过期的时间.但它可以想象成任何东西,甚至会话ID或用户的整个配置文件.(请不要这样做)它有一个安全的签名,可以防止恶意方生成假令牌(你需要访问服务器的私钥来签署它们,你可以验证它们在签名后没有被修改)你发送每个请求,就像cookie或AuthorizationHeader 一样.事实上,它们通常在HTTP Authorization标头中发送,但使用cookie也很好.

令牌已签名,因此服务器可以验证其来源.我们将假设服务器信任其自己的安全签名能力(您应该使用标准库:不要尝试自己做,并正确保护服务器)

在安全传输令牌的问题上,答案通常是通过加密通道(通常是httpS)发送.

关于在客户端中安全地存储令牌,您需要确保坏人无法访问它.这(主要)意味着阻止不良网站的JS读取令牌以将其发送回给他们.使用用于缓解其他类型的XSS攻击的相同策略可以减轻这种影响.

如果您需要使JWT无效,那么肯定可以实现这一目标.仅为已请求"其他会话终止"的用户存储每用户时期是一种非常有效的方法,可能足够好.如果应用程序需要按会话失效,则可以以相同的方式维护会话ID,并且仍可以将"已杀死的令牌"表维护为比完整用户表小得多(您只需要保留比新用户表更新的记录)最长允许的令牌生存期.)因此,使令牌无效的能力部分地否定了客户端会话的好处,因为您必须维持此会话被杀死状态.这可能是比原始会话状态表小得多的表,因此查找仍然更有效.

使用JWT令牌的另一个好处是,使用可能使用的每种语言的库都可以相当容易地实现它.它也完全脱离了您的初始用户身份验证方案 - 如果您转移到基于指纹的系统,则无需对会话管理方案进行任何更改.

更微妙的好处:因为JWT可以携带"信息"并且客户可以访问它,您现在可以开始做一些聪明的事情.例如,提醒用户他们的会话将在注销前几天到期,根据令牌中的到期日期为他们提供重新进行身份验证的选项.无论你能想象什么.

简而言之:JWT回答了其他会话技术的一些问题和缺点.
1."更便宜"的身份验证,因为你可以消除数据库往返(或者至少有一个小得多的表来查询!),这反过来又可以实现水平可伸缩性.
2.防篡改客户端声明.

虽然JWT不回答安全存储或传输等其他问题,但它不会引入任何新的安全问题.

JWT周围存在很多否定性,但如果你实现与其他类型的身份验证相同的安全性,那么你会没事的.

最后一点说明:它也不是Cookies vs Tokens.Cookie是一种存储和传输信息的机制,也可用于存储和传输JWT令牌.

  • 不建议@TheTahaan localStorage 存储 JWT。您分享的链接也提到了这一点。这个[博客](https://www.rdegges.com/2018/please-stop-using-local-storage/)很好地解释了为什么 JWT 不应该存储在 localStorage 中。 (7认同)
  • 你说将 jwt 存储在本地存储中安全吗?如果没有,哪里有安全的地方可以保存它以便用户保持登录状态? (4认同)
  • 不同之处在于会话表为每个会话保存一个条目。可能有数百万用户。如果令牌已被杀死,则被杀死的令牌表只需要一行来存储令牌,并且如果该令牌已过期,则可以通过删除该行来进一步减少该令牌。因此,被杀死的令牌查找是在一个小得多的表中进行的。在现实世界的示例中,对于大型用户群来说,性能差异是几个数量级。 (4认同)
  • 如果您的后端服务器为每个登录用户维护生成 JWT 的秘密(例如存储在缓存服务器中),则使 JWT 无效的替代方法是[删除服务器中存储的秘密](https://stackoverflow.com/questions /30523238/best-practices-for-server-side-handling-of-jwt-tokens#comment80179289_30523238) (即使令牌尚未过期),因此当用户下次登录时,使用已删除密钥生成的所有令牌将自动无效此时,服务器会为用户生成另一个新的 JWT。通过这样做,不再需要存储整个 JWT。在服务器端 (3认同)
  • 值得注意的是,服务器端会话也不必在服务器上存储任何信息。服务器可以像JWT一样将客户端用作存储。真正的区别在于1)通过将值作为Cookie头以外的请求头传递来避免浏览器安全规则,以及2)JWT具有标准化格式。 (2认同)
  • 在您的评论中,您没有谈论基于缓存的解决方案+会话令牌。在我看来,这比 JWT +“杀死令牌”表“更好”,因为使用这个“杀死令牌”表,您无论如何都需要数据库访问,您也将拥有会话+缓存(也很小)。持久化 JWT 比持久化会话更难实现,因为你需要使用刷新令牌(所以需要维护两个令牌)...任何评论都会非常感激...特别是如果你有一些数字来展示 JWT + 如何实现Kill_table 比会话 + 缓存更高效;-) (2认同)

Car*_*xen 33

简短的回答是:没有.

更长的版本是:

GraphQL文档中阅读此建议后,我实现了JWT用于会话管理:

如果您不熟悉任何这些身份验证机制,我们建议使用express-jwt,因为它简单而不会牺牲任何未来的灵活性.

实施确实很简单,因为它只增加了一点复杂性.然而,过了一段时间,我(像你一样)开始想知道有什么好处.事实证明,就会话管理而言,JWT很少(或可能没有),正如本博文详细解释的那样:

停止使用JWT进行会话

  • 阅读“停止使用JWT进行会话”是一件很棒的事情! (4认同)
  • 如果您需要跨域工作怎么办?AFAIK cookie 在这种情况下不能使用。 (2认同)
  • 在这种情况下,您将牺牲浏览器提供的针对 XSS 的安全性。恕我直言,如果可能的话,应避免跨站点会话。请注意,浏览器通常将“abc.example.com”和“example.com”视为同一站点。 (2认同)

h--*_*--n 6

我有一个类似的问题,在 JWT 和令牌 + 缓存之间进行选择以进行用户身份验证。

阅读这些文章后,我很清楚 JWT 承诺的好处并没有超过它带来的问题。所以令牌 + 缓存(Redis/Memcached)是我要走的路。

Auth Headers vs JWT vs Sessions——如何为 API 选择正确的 Auth 技术

API 的认证技术

停止在会话中使用 jwt


Eya*_*rry 5

我的两分钱,在途中与 joepie91 的著名博客文章形成了一些对比。

考虑到今天(和明天)的应用程序(大部分)是云原生
无状态 JWT 身份验证具有经济利益,它随着应用程序的扩展而扩展:
云应用程序每过一秒都会产生成本
当用户不再需要“针对”会话存储进行身份验证时,此成本会降低。

处理
24/7 全天候运行会话存储需要花钱。
在 K8S 世界中,您无法摆脱基于内存的解决方案,因为 pod 是短暂的。
由于完全相同的原因,粘性会话不会很好。

存储
存储数据需要花钱。将数据存储在SSD 中的成本更高。
Session 相关的操作需要快速解决,所以光驱不是一个选择。

I/O
一些云提供商对与磁盘相关的 I/O 收费。

带宽
一些云提供商对服务器实例之间的网络活动收费。
这适用,因为几乎可以肯定 API 和会话存储是单独的实例。

将会话存储集群化
成本会进一步提高所有上述成本。

  • “在 K8S 的世界中,你无法摆脱基于内存的解决方案,因为 pod 是短暂的” 不确定你的意思。Redis 绝对可以在 K8S 环境中工作,并且 Redis pod 频繁发生故障以影响您的用户似乎不太可能。 (2认同)
  • “我个人不喜欢在构建软件时处理可能性”。我认为我们都更喜欢这一点,这就是为什么我们不应该构建依赖内存数据存储而永远不会失败的系统,因为这种可能性似乎相当高。至于你的另一点,如果你的攻击者能够持续关闭你的 Redis 实例,那么解决方案可能不需要涉及使用 JWT。 (2认同)