Answers:
JWT不能说每个会话都使用“会话”。JWT提供了一种在客户端上维护会话状态的方法,而不是在服务器上进行维护。
人们常问的意思是“使用JWT相对于使用服务器端会话有什么好处? ”
对于服务器端会话,您要么必须将会话标识符存储在数据库中,要么将其保留在内存中,并确保客户端始终访问同一服务器。这两个都有缺点。对于数据库(或其他集中式存储),这将成为瓶颈和需要维护的工作-本质上是对每个请求都要执行的额外查询。
使用内存中解决方案,您可以限制水平扩展,并且会话将受到网络问题的影响(客户端在Wifi和移动数据之间漫游,服务器重新启动等)
将会话移至客户端意味着您删除了对服务器端会话的依赖性,但是这带来了一系列挑战。
JWT和其他客户端会话机制都共享这些问题。
JWT特别解决了其中的最后一个问题。了解什么是JWT可能会有所帮助:
这是一些信息。对于用户会话,您可以包括用户名和令牌过期的时间。但是可以想象,它可以是任何东西,甚至包括会话ID或用户的整个个人资料。(但是请不要这样做)它具有一个安全的签名,可以防止恶意方生成伪造的令牌(您需要访问服务器的私钥来对其进行签名,并且可以验证它们在签名后没有被修改)。发送每个请求,就像Authorization
发送Cookie或Header 一样。实际上,它们通常在HTTP Authorization
标头中发送,但是使用cookie也可以。
令牌已签名,因此服务器可以验证其来源。我们将假定服务器信任自己的安全签名能力(您应该使用标准库:请勿尝试自己做,并正确保护服务器)
关于安全传输令牌的问题,答案通常是通过加密通道(通常是httpS)发送令牌。
关于将令牌安全地存储在客户端中,您需要确保坏人无法使用它。这(主要是)意味着防止不良网站的JS读取令牌并将其发回给它们。使用与缓解其他类型的XSS攻击相同的策略可以缓解这种情况。
如果您需要使JWT失效,那么肯定有一些方法可以实现。仅为请求“其他会话终止”的用户存储每个用户的纪元是一种非常有效的方法,可能已经足够了。如果应用程序需要按会话无效,则可以以相同的方式维护会话ID,并且仍可以将“ killed tokens”表维护为小于完整用户表(您只需保留比因此,使令牌无效的能力会部分抵消客户端会话的好处,因为您必须保持此会话的终止状态。该表很有可能比原始会话状态表小得多,因此查找仍然更加高效。
使用JWT令牌的另一个好处是,使用可能支持您期望使用的每种语言的库可以很容易地实现。它也与您的初始用户身份验证方案完全脱离-如果您使用基于指纹的系统,则无需对会话管理方案进行任何更改。
一个更微妙的好处:因为JWT可以携带“信息”,并且客户端可以访问它,所以您现在可以开始做一些聪明的事情。例如,提醒用户他们的会话将在注销前几天到期,并根据令牌中的到期日期为他们提供重新认证的选项。随你所想。
简而言之:JWT回答了其他会话技术的一些问题和缺点。
尽管JWT不能解决安全存储或传输之类的其他问题,但它并未引入任何新的安全性问题。
JWT周围存在很多消极因素,但是如果您实现与其他类型的身份验证相同的安全性,那将很好。
最后一点:不是Cookie还是代币。Cookies是一种用于存储和传输信息位的机制,也可以用于存储和传输JWT令牌。
简短的答案是: 无。
较长的版本是:
阅读GraphQL docs中的建议后,我实现了用于会话管理的JWT:
如果您不熟悉这些身份验证机制中的任何一种,我们建议使用express-jwt,因为它很简单,而且不会牺牲任何将来的灵活性。
实现确实很简单,因为它只增加了一点点复杂性。过了一会儿,我(像您一样)开始想知道这些好处是什么。事实证明,就会话管理而言,JWT很少(或可能没有),正如此博客文章详细解释的那样:
我的两美分,这与joepie91著名的博客文章形成了鲜明的对比。
考虑到当今(以及未来)的应用程序(大部分)都是云原生
的。无状态JWT身份验证具有经济利益,它随着应用程序的扩展而扩展:
云应用程序伴随着人们的一口气而招致成本。
当用户不再需要“针对”会话存储进行身份验证时,可以降低此成本。
处理
24/7全天候运行会话存储需要花费金钱。
在K8S的世界中,您无法摆脱基于内存的解决方案,因为吊舱是短暂的。
完全相同的原因,粘性会话的效果不佳。
存储
存储数据需要花费金钱。将数据存储在SSD中的成本甚至更高。
与会话相关的操作需要快速解决,因此无法选择光盘驱动器。
I / O
一些云提供商会为与光盘相关的I / O收费。
带宽
一些云提供商对服务器实例之间的网络活动收费。
这适用,因为几乎可以确定API和会话存储是单独的实例。
将会话存储集群化
该成本将所有上述成本进一步提升。
我在JWT和令牌+缓存之间进行用户身份验证时有一个类似的问题。
在阅读了这些文章之后,对我来说很明显,JWT承诺的收益不会超过它带来的问题。所以令牌+缓存(Redis / Memcached)是适合我的方法。