身份验证:JWT使用vs会话

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

它是作为一个独立的方法使用还是在会话中使用?

133663 次浏览

智威汤逊并没有使用“session”的优势;本身。jwt提供了一种在客户端而不是在服务器上维护会话状态的方法。

当人们问这个问题时,通常的意思是“使用jwt比使用__abc0有什么好处”。

对于服务器端会话,您要么必须将会话标识符存储在数据库中,要么将其保存在内存中,并确保客户端始终访问相同的服务器。这两种方法都有缺点。在数据库(或其他集中式存储)的情况下,这成为一个瓶颈和需要维护的东西——本质上是每个请求都要执行的额外查询。

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

将会话移动到客户端意味着您消除了对服务器端会话的依赖,但这也带来了一系列挑战。

  • 安全地存储令牌。
  • 安全运输。
  • JWT会话有时很难失效。
  • 相信客户的主张。

jwt和其他客户端会话机制都存在这些问题。

智威汤逊特别解决了最后一个问题。了解JWT是什么可能会有所帮助:

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

令牌被签名,因此服务器可以验证它的来源。我们假设服务器相信自己有安全签名的能力(您应该使用标准库:不要尝试自己做,并适当地保护服务器)。

关于安全传输令牌的问题,答案通常是通过加密通道(通常是httpS)发送它。

关于在客户机中安全地存储令牌,您需要确保坏人无法获得它。这(主要)意味着防止来自坏网站的JS读取令牌并将其发回给他们。使用与缓解其他类型的XSS攻击相同的策略来缓解这一问题。

如果您需要使jwt失效,肯定有一些方法可以实现这一点。仅为请求“其他会话终止”的用户存储每个用户的epoch;是一个非常有效的方法,可能已经足够好了。如果应用程序需要每个会话失效,那么可以以相同的方式维护会话ID,并且“已杀死的令牌”;表仍然可以维护为比完整的用户表小得多(您只需要保留比允许的最长令牌生命周期更新的记录)。因此,使令牌失效的能力在一定程度上抵消了客户端会话的好处,因为您必须保持会话已终止状态。这个表很可能比原来的会话状态表小得多,因此查找仍然更有效。

使用JWT令牌的另一个好处是,很容易使用每种语言中可用的库来实现它。它也完全脱离了最初的用户身份验证方案——如果迁移到基于指纹的系统,则不需要对会话管理方案进行任何更改。

一个更微妙的好处是:因为JWT可以携带“信息”。这可以被客户端访问,你现在可以开始做一些聪明的事情。例如,提醒用户他们的会话将在注销前几天到期,并根据令牌中的到期日期为他们提供重新进行身份验证的选项。任何你能想到的。

简而言之:jwt回答了其他会话技术的一些问题和缺点。

  1. < p >“Cheaper"身份验证,因为您可以消除DB往返(或者至少有一个小得多的表要查询!),这反过来又支持水平可伸缩性。

  2. 防篡改客户端声明。

虽然JWTs没有解决安全存储或传输等其他问题,但它没有引入任何新的安全问题。

围绕jwt存在许多负面影响,但如果您实现了与其他类型的身份验证相同的安全性,就不会有问题。

最后一点:这也不是cookie vs .令牌。cookie是一种存储和传输信息位的机制,也可以用于存储和传输JWT令牌。

简单的答案是:一个也没有。

一个较长的版本是:

在阅读GraphQL文档中的建议后,我实现了会话管理的JWTs:

如果您不熟悉任何这些身份验证机制,我们 推荐使用express-jwt,因为它很简单,没有牺牲

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

停止在会话中使用JWT

我的两美分,这在某种程度上与joepie91著名的博客文章形成了对比。

考虑到今天(和未来)的应用程序(大部分)都是云原生的
.

有一个经济利益无状态JWT身份验证, 哪个随着应用程序的扩展而扩展:
云应用每时每刻都在增加成本
当用户不再需要“对”进行身份验证时,这种成本就降低了。会话存储。 下面详细列出了一些不使用JWT会增加应用程序成本的因素 < p > 数据库服务器
运行一个24/7的会话商店需要花钱 在K8S的世界中,您不能使用基于本地存储/内存的解决方案,因为pod是短暂的 由于同样的原因,粘性会话也不会很好 < p > 存储
存储数据需要花钱。在固态硬盘中存储数据的成本甚至更高 与会话相关的操作需要快速解析,不能使用光驱 < p > I / O
一些云提供商对与光盘相关的I/ o收费

< p > 下载
大约在2022年,可以安全地假设API和会话存储是独立的服务器实例 一些云提供商对从一个实例下载信息到另一个实例收费 < p > 扩展会话存储

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

读完这些文章后,我很清楚智威汤逊承诺的好处并没有超过它带来的问题。所以令牌+缓存(Redis/Memcached)是我的选择。

认证头vs JWT vs会话-如何为api选择正确的认证技术

api认证技术

停止在会话中使用jwt

如果您使用的是AWS,那么另一个略有不同的视角可能会有用。

我们实现了PHP5。在AWS ElastiCache上集中会话存储在多台服务器上。

在我们转到PHP7之前,它工作得很完美。PHP7很难配置,我们被断断续续的问题所困扰,似乎会话“失败/不匹配/有点混乱”。然后他们就不能在那个设备上登录,直到旧的会话过期。

我们转移到使用DynamoDb来存储会话,没有更多的问题。它稍微慢一些,但只在登录(会话存储)阶段可以注意到。

与此同时,我们实现了AWS cognito来取代我们的身份验证,并开始使用API-Gateway通过lambda python函数来交付内容。

我们使用PHP SDK对Cognito进行身份验证,然后将JWT存储在cookie中,但仍然使用PHP会话来保持我们的遗留代码正常工作。

现在我们有了两个栈,这是两个世界中最好的:PHP7做到了它的位,并将主要内容(非常快)传递给用户。然后JS接管并使用JWT提供额外的内容。

我认为JWT的伟大之处在于,它可以在这两个栈之间传递,并在两种情况下用于对用户进行身份验证。

现在我们想知道是否值得冒险,完全切换到新的JWT系统?

在PHP中,我们仍然使用我们的遗留会话,但我们也将令牌传递给cognito以验证它。这是一点额外的安全,可能是不必要的,但它给人一种温暖舒适的感觉。此外,dynamoDb还可以节省成本和维护费用。

在会话身份验证(或有状态身份验证)中,可以存储比令牌更多的数据。但是您必须将会话对象存储在某个地方,这使得身份验证集中起来。此外,您需要有额外的内存来存储会话,这将增加管理内存的额外工作。如果您的应用程序增长,现在您必须根据需要实现不同的设计,实现会话缓存服务,并将会话存储在web应用程序或数据库中。

在Jwt或一般的无状态身份验证中,您不存储任何东西。将令牌与请求标头一起发送。这使得它成为分散的身份验证。这种身份验证的缺点是令牌撤销。每个代币都有一个到期时间,如果您的代币被盗,它将一直有效直到到期。你必须实现最小化风险的逻辑。