我们现在就是Redis
有时,人们采用旨在解决一个狭隘问题的技术,并开始广泛应用。这个问题可能看起来很相似,但利用独特的技术来解决一般问题可能会产生意想不到的后果。用一个比喻,如果你是一把锤子,一切看起来都像钉子。JWT就是这样一种技术。
Okta等公司的SME有许多深入的文章和视频,讨论使用JWT代币的潜在危险和低效性[1]. 然而,这些警告被营销人员、YouTuber、博客作者、课程创作者以及其他有意或无意推广该课程的人所掩盖。
如果你看这些视频和文章,它们都只是谈论JWT的感知好处,而忽略了它的不足。更具体地说,它们只是展示如何使用它,但没有谈论JWT在实际生产环境中增加的撤销和额外复杂性。它们也从来没有将其与现有的经过测试的产品进行比较方法的深度足以真正权衡利弊。
又或许是它完美、吸引眼球、友好的名字让它如此受欢迎。“JSON”(通常很受欢迎)、“Web”(用于Web)和“Token”(意味着无状态)让人们认为它非常适合他们的Web身份验证工作。
所以我认为这是一个市场营销打败了工程师和安全专家的案例。但是,这并不全是坏事,因为黑客新闻中经常会有关于JWT的长时间、热烈的辩论(参见在这里,她E和在这里),所以还有希望。
如果你仔细想想,这些不断的争论本身应该是一个危险信号,因为你永远不会看到这样的争论,特别是在安全领域。安全应该是二进制的。技术要么是安全的,要么不是。
无论如何,在这篇博文中,我想重点讨论一下使用JWT的潜在危险,并讨论一个经过十年考验的解决方案。
为了进一步理解,当我谈论JWT时,我指的是“无状态JWT”,这是JWT流行的主要原因,也是首先使用JWT的最大原因。另外,我在下面的参考资料部分列出了所有涉及JWT本质的其他文章。
在我们理解为什么它是危险的之前,让我们先通过一个示例用例来了解它是如何工作的。
假设您正在使用Twitter。你登录,写一条推文,就像推文一样,然后转发别人的推文。所以你做了四个动作。对于每个操作,您都需要经过身份验证和授权才能执行该特定操作。
下面是传统方法中发生的情况。
问题是,第四步很慢,用户执行的每一个操作都需要重复。因此,每个API调用都会导致至少两个缓慢的DB调用,这会降低总体响应时间。
有不同的方法来实现这一点。
现在让我们看看JWT的方法。
JWT,特别是作为会话使用时,试图通过完全消除数据库查找来解决这个问题。
其主要思想是将用户信息存储在会话令牌本身中!因此,与其使用一些长长的随机字符串,不如将实际的用户信息存储在会话令牌中。为了保护它,使用只有服务器知道的秘密签名令牌的一部分。
因此,即使客户端和服务器可以看到令牌的用户信息部分,第二部分,即签名部分,也只能由服务器验证。
在下图中,令牌的粉红色部分包含有效负载(用户信息),客户端或服务器都可以看到。
但是蓝色部分使用一个秘密字符串、头和有效负载本身进行签名。因此,如果客户机篡改了有效负载(比如说模拟了另一个用户),则签名将不同,并且不会进行身份验证。
下面是我们使用JWT时的用例:
对于每个用户操作,服务器只需验证已签名的部分,获取用户信息,并允许用户执行该操作,从而完全跳过DB调用。
但是关于JWT令牌还有一件很重要的事情需要知道。那就是它使用一个过期时间来让自己过期。它通常被设置为5分钟到30分钟。而且因为它是自包含的,所以你不能轻易地撤销/失效/更新它。这才是问题的症结所在。
JWT的最大问题是令牌失效问题。因为它会一直工作到过期,所以服务器没有简单的方法来撤销它。
下面是一些会使这变得危险的用例。
想象一下,你在推特后从推特上注销。您可能认为您已从服务器注销,但事实并非如此。因为JWT是自包含的,将继续工作,直到到期。这可能是5分钟或30分钟,或者是作为令牌一部分设置的任何持续时间。因此,如果有人在这段时间内访问了该令牌,他们可以继续访问它,直到它过期。
假设你是Twitter或一些在线实时游戏的管理员,而真正的用户正在使用该系统。作为版主,你希望迅速阻止某人滥用系统。你不能,同样的原因。即使在您阻止之后,用户仍将继续访问服务器,直到令牌过期。
假设该用户是管理员,并被降级为具有较少权限的普通用户。同样,这不会立即生效,用户将继续作为管理员,直到令牌过期。
我们发现,许多实现JWT的库多年来都存在许多安全问题,甚至规范本身也存在安全问题。甚至Auth0本身,谁宣传JWT遇到了问题.
在许多复杂的现实世界应用程序中,您可能需要存储大量不同的信息。将其存储在JWT令牌中可能会超过允许的URL长度或cookie长度,从而导致问题。此外,您现在可能会在每个请求上发送大量数据。
在许多现实世界的应用程序中,服务器必须维护用户的IP并跟踪API以进行速率限制和IP白名单。因此,无论如何,你都需要使用速度极快的数据库。认为你的应用程序在JWT中变得无状态是不现实的。
一种流行的解决方案是在数据库中存储一个“已撤销令牌”列表,并在每次调用时对其进行检查。如果令牌是已撤销列表的一部分,则阻止用户执行下一个操作。但是现在您正在向DB进行额外的调用,以检查令牌是否被撤销,从而完全欺骗了JWT的目的。
尽管JWT确实消除了数据库查找,但在此过程中引入了安全问题和其他复杂性。安全性是二进制的——要么安全,要么不安全。因此,将JWT用于用户会话是很危险的。
在某些情况下,您在后端进行服务器到服务器(或微服务到微服务)通信,一个服务可能会生成JWT令牌,将其发送到另一个服务以进行授权和其他狭窄的位置,例如重置密码,您可以将JWT令牌作为一次性短期令牌发送,以验证用户的电子邮件。
解决方案是完全不将JWT用于会话目的。相反,用传统的,经过实战检验的方法更有效。
也就是说,使数据库查找速度非常快(亚毫秒),以至于额外的调用无关紧要。
有没有数据库速度如此之快,以至于可以在亚毫秒内处理数百万个请求?
当然有。它叫Redis!每天为数十亿用户提供服务的数千家公司正是为了这个目的而使用Redis!
Redi万博体育彩s Enterprise是Redis OSS的增强版,提供99.999%的可用性,可以服务数万亿次请求。它可以作为私有云上的自由软件使用,也可以作为前三大云中任何一个云上的自由软件使用。万博电竞客服
还有什么?Redis En万博体育彩terprise现在已经从仅仅是一个缓存或会话存储演变为一个功能完备的多模型数据库,并具有模块生态系统它与core Redis本机运行。例如,您可以使用RedisJSON(快10倍和市场领先者),本质上有一个实时的类似mongodb的数据库,或者使用再搜索模块(快4-100倍)并实现像Algolia一样的实时全文搜索。
如果你只是简单地使用Redis作为会话存储和一些其他数据库作为主数据库,这就是你的架构看起来的样子。需要注意的一点是Redis Enterprise提供万博体育彩的四种类型的缓存:缓存旁(延迟加载)、写后(回写)、直写和读副本,不同于Redis OSS只提供一个(缓存旁)。
注意,闪电表情符号表示速度非常快。蜗牛表情符号表示速度很慢。
如前所述,您还可以将Redis用作整个数据层的主数据库。在这个场景中,您的体系结构变得更加简单,基本上,一切都变得非常快速。
当然,公司不仅将Redis用作独立数据库,还将其用作地理分布数据库集群。