JWT 本身并没有使用“会话”的优势。 JWT 提供了一种在客户端维护会话状态的方法,而不是在服务器上进行维护。
人们在问这个问题时通常的意思是“使用 JWT 比使用 JWT 有什么好处?服务器端会话".
对于服务器端会话,您要么必须将会话标识符存储在数据库中,要么将其保留在内存中并确保客户端始终访问同一服务器。这两者都有缺点。对于数据库(或其他集中式存储)来说,这成为瓶颈并且需要维护——本质上是对每个请求执行额外的查询。
使用内存解决方案,您会限制水平扩展,并且会话将受到网络问题的影响(客户端在 Wifi 和移动数据之间漫游、服务器重新启动等)。
将会话移至客户端意味着您消除了对服务器端会话的依赖,但它也带来了一系列挑战。
- 安全地存储令牌。
- 安全运输。
- JWT 会话有时很难失效。
- 相信客户的说法。
JWT 和其他客户端会话机制都存在这些问题。
JWT 特别解决了最后一个问题。它可能有助于理解 JWT 是什么:
这是一点信息。对于用户会话,您可以包含用户名和令牌过期时间。但它可以是任何东西,甚至是会话 ID 或用户的整个配置文件(但请不要这样做)。
它具有安全签名,可以防止恶意方生成虚假令牌(您需要访问服务器的私钥来对它们进行签名,并且可以验证它们在签名后没有被修改)。
您可以通过每个请求发送它们,就像 cookie 或Authorization
将发送标头。事实上,它们通常是在 HTTP 中发送的Authorization
header 但使用 cookie 也可以。
该令牌已签名,因此服务器可以验证其来源。我们将假设服务器信任其自身的安全签名能力(您应该使用标准库:不要尝试自己执行此操作,并正确保护服务器)。
关于安全传输令牌的问题,答案通常是通过加密通道(通常是 httpS)发送。
关于将令牌安全地存储在客户端,您需要确保坏人无法获取它。这(主要)意味着阻止不良网站的 JS 读取令牌并将其发送回给他们。使用与缓解其他类型的 XSS 攻击相同的策略可以缓解这种情况。
如果您需要使 JWT 失效,肯定有多种方法可以实现。仅为请求“终止其他会话”的用户存储每个用户的纪元是一种非常有效的方法,可能已经足够好了。如果应用程序需要每个会话失效,则可以以相同的方式维护会话 ID,并且“killed tokens”表仍然可以保持比完整用户表小得多(您只需要保留比完整用户表更新的记录)允许的最长令牌生命周期)。因此,使令牌无效的能力部分抵消了客户端会话的好处,因为您必须维持此会话终止状态。这很可能是一个比原始会话状态表小得多的表,因此查找仍然更有效。
使用 JWT 令牌的另一个好处是,使用可能包含您期望拥有的每种语言的库来实现相当容易。它也完全脱离了您最初的用户身份验证方案 - 如果您转向基于指纹的系统,则无需对会话管理方案进行任何更改。
一个更微妙的好处:因为 JWT 可以携带“信息”并且客户端可以访问它,所以您现在可以开始做一些聪明的事情。例如,提醒用户,他们的会话将在注销前几天到期,让他们可以根据令牌中的到期日期重新进行身份验证。无论你能想象到什么。
简而言之:JWT 回答了其他会话技术的一些问题和缺点。
-
“更便宜”的身份验证,因为您可以消除数据库往返(或者至少可以查询更小的表!),从而实现水平可扩展性。
-
防篡改的客户端声明。
虽然 JWT 没有解决安全存储或传输等其他问题,但它没有引入任何新的安全问题。
JWT 存在很多负面影响,但如果您实现与其他类型的身份验证相同的安全性,那就没问题。
最后一点:这也不是 Cookie 与令牌的比较。 Cookie 是一种存储和传输信息位的机制,也可用于存储和传输 JWT 令牌。