警惕!为什么越来越多人不推荐使用JWT?
在现代 Web 应用开发中,安全性和身份验证始终是最重要的环节之一。随着互联网的发展,用户数量迅速增长,传统的基于会话的认证方式虽然已经运行多年,但在性能、可扩展性以及跨域应用方面存在局限性。为了解决这些问题,开发者们开始寻找更加灵活、高效的认证方式,而 JWT(JSON Web Token) 在这样的背景下应运而生,并迅速成为主流。
JWT 作为一种开放标准(RFC 7519),允许使用 JSON 对象安全地传输信息。它不仅可以实现用户身份验证,还能在多个应用和服务之间传递用户授权信息。这种结构简单且有效的令牌化机制,使得它特别适合于分布式系统中用户身份的跨服务传递,因此被广泛用于 OAuth 2.0 等授权框架中。此外,JWT 可以在前后端分离的应用中有效提升认证的灵活性,这也是其迅速流行的关键因素之一。
然而,尽管 JWT 拥有许多优点,它并不是没有缺陷的。在实际生产环境中,越来越多的开发者和安全专家发现,JWT 在处理长期用户会话管理时存在严重的安全隐患,如令牌吊销问题、冗余签名和潜在的中间人攻击等。这些问题让开发者们在项目中使用 JWT 时需要慎重考虑其适用性。
因此,本篇文章将深入分析 JWT 的工作原理、优点与局限性,并探讨为什么许多人认为它在某些场景下并不适合广泛使用。通过这篇文章,你将更清楚地了解 JWT 的本质、如何安全使用它以及何时应该选择其他更适合的解决方案。
什么是 JWT?
这是官方定义:JSON Web Tokens — jwt.io
JWT 是什么?
JWT 代表 JSON Web Token
。
如果你对 JWT 不太熟悉,不用担心!它们并不复杂!
你可以把 JWT 看作是一段 JSON 数据,通过验证它可以确认数据来自你信任的人。
当然,我们在这里不会深入讨论它的实现细节,但如果你有兴趣,你可以自行研究。
现在,让我们来谈谈它的流程:
当你登录一个网站时,网站会生成一个 JWT 并发送给你。
这个 JWT 就像一个包裹,里面包含了关于你的身份信息,比如用户名、角色、权限等。
然后,你每次与网站通信时都会携带这个 JWT。
每当你访问需要身份验证的页面时,你会向网站提交这个 JWT。
网站收到 JWT 后,会验证其签名,确保它是由网站发布的,并检查其中的信息以确认你的身份和权限。
如果一切正常,你就可以继续访问受保护的页面。
为什么说 JWT 不好?
首先,当我们使用 JWT 时,它通常用于以下任务:
用户在网站上注册
用户在网站上登录
用户点击并执行操作
网站使用用户的信息创建、更新或删除数据
这些任务通常涉及数据库操作,例如:
记录用户正在执行的操作
将一些用户数据添加到数据库中
检查用户的权限,看看他们是否能够执行某些操作
现在,让我们逐步看看它的一些缺点。
大小问题
这是一个无法忽视的问题。
例如,如果我们需要存储一个像 “xiaou” 这样的用户 ID:
如果存储在 cookie 中,总大小只有 5 个字节。
如果将该 ID 存储在 JWT 中,大小将增加约 51 倍。
这无疑增加了我们的带宽负担。
冗余的签名
JWT 的一个主要卖点是它的加密签名。
由于 JWT 是签名的,接收方可以验证该 JWT 是否有效且可信。
然而,过去 20 年里,几乎所有的 Web 框架都提供了使用常规会话 cookie 的加密签名功能。
实际上,大多数 Web 框架会自动为你签名(甚至加密)你的 cookie。
这意味着你可以享受与 JWT 签名相同的好处,而无需使用 JWT 本身。
在实践中,在大多数 Web 认证场景中,JWT 数据是存储在会话 cookie 中的,这意味着你现在有两层签名:一个在 cookie 上,另一个在 JWT 上。
令牌吊销问题
由于令牌在过期前仍然有效,服务器没有简单的方法吊销它们。
以下是一些可能出现危险的用例。
登出并不是真正的登出!
假设你在 微博 上发了一条推文,然后登出了。你可能认为你已经从服务器登出了,但事实并非如此。
由于 JWT 是自包含的,它在过期前一直有效,这可能是 5 分钟、30 分钟或令牌设置的任何时长。
因此,如果有人在这段时间内获取了该令牌,他们可以继续访问你的账户,直到令牌过期。
数据陈旧
假设某个用户是管理员,但被降级为权限较少的普通用户。同样,这不会立即生效,该用户将继续拥有管理员权限,直到令牌过期。
JWT 通常没有加密
这意味着任何可以进行中间人攻击并窃取 JWT 的人都会拥有你的身份验证凭据。这变得更容易,因为攻击者只需要拦截服务器和客户端之间的连接。
安全问题
关于 JWT 是否安全,我们可以参考这篇文章:
JWT (JSON Web Token) (in)security — research.securitum.com
结论
总之,JWT 适合作为在两个实体之间传输声明的一次性授权令牌。
但是,JWT 并不适合作为长期持久性数据存储机制,尤其是在管理用户会话方面。
使用 JWT 进行会话管理可能会引入一系列严重的安全性和实现问题。
相反,传统的会话机制,如会话 cookie 及其成熟的实现,更适合用于存储长期持久的数据。
话虽如此,如果你在进行自己的开发和学习时使用 JWT 而不考虑安全性或性能,那完全没有问题。
但是,一旦你涉及到生产环境,就需要避免这些潜在问题。