使用 Redis 检查每个请求的访问令牌

Posted

技术标签:

【中文标题】使用 Redis 检查每个请求的访问令牌【英文标题】:Check Access Token every Request with Redis 【发布时间】:2013-04-21 06:28:55 【问题描述】:

我目前正在为我的 RESTful API 实施 OAuth 2.0 架构。

对于每个请求,我都会在 HTTP 标头中设置一个授权承载令牌,以便我的所有客户端发出授权请求。

Authorization: Bearer sdflksd3r4823vkn95-03850432 

我了解在 API 中接受令牌直到过期日期是一种常见的做法。但是假设用户想要撤销令牌,我需要采用一种方法来检查每个请求的令牌状态。

所以我想去数据库检查每个 HTTP 请求。由于性能原因,我感觉这不会很好地扩展。

所以我想知道像 Redis 这样的解决方案是否适合非常快速地单次读取访问令牌状态?

【问题讨论】:

【参考方案1】:

为令牌使用 HMAC 的目的是让服务器可以快速验证它,而无需调用任何外部数据存储(例如 Redis、mysql 等)。由于没有共享状态(验证令牌的所有信息都是令牌本身和 HMAC 的密钥),因此这具有很好地扩展到多个服务器的额外好处。

如果您要拥有一个已撤销令牌的黑名单,那么 Redis 之类的东西可能就可以了(尽管仍然比不为每个令牌验证进行远程调用要慢)。正确设置,Redis 实例和 API 服务器之间的延迟较低,您应该会看到每个请求

奖励:另一个加快速度的方法是使用Bloom filter 来处理被拒绝的 API 请求的缓存。这样,只有在 Bloom 过滤器将请求令牌标记为可能已撤销时,您才会转到 Redis。请注意,由于这是另一层缓存,因此您必须在令牌被拒绝时更新 Bloom 过滤器的状态。

【讨论】:

我确实在考虑使用布隆过滤器。虽然我也想知道使用单例缓存是否是一个可行的选择 如果你只有一个服务器,那么你有更多的选择,因为你只需要在一个地方维护状态。拥有像 Redis 这样的外部服务器来维护状态允许您拥有多个 API 服务器。单例仅在您有单个服务器时才有效。另一种选择是分布式地图(Coherence、Hazelcast 等)。如果令牌的过期时间相对较短,那么您也可以在它们过期时从分布式地图中删除 then 以减小其大小。 优秀的答案。非常感谢!【参考方案2】:

我正在为自己制作类似的东西。 对于令牌语法和加密,我建议你使用JWT,这是一个很好的标准。 使用 redis 存储一对 token/userid 是可以的,也因为我们可以设置一个过期值。 我还在中间插入了一个布隆过滤器,但我的做法与 sehrope 建议相反:我在登录时通过布隆过滤器存储所有令牌,所以如果令牌不存在,它肯定是无效的; else 可能是正确的,但我必须检查一下 Redis 以确定;但现在我有一个问题:如果我想扩展我的身份验证系统,我需要一个身份验证服务器之间的有状态负载平衡器。 恕我直言,使用布隆过滤器创建黑名单是不正确的:如果我在布隆过滤器中将已撤销和错误的令牌列入黑名单,如果该项目未列入黑名单,布隆过滤器将返回 false (我必须在 redis 后端检查它以授权);否则,如果一个元素存在(列入黑名单),我必须在 redis 上检查它以确定,因为布隆过滤器的真实响应可能是误报。

【讨论】:

我实际上是在存储在 sessionStorage 中的 AngularJS 站点上使用 JWT 令牌。每次关闭浏览器应用程序时,他们都必须登录。这也是一个 30 分钟的到期时间,用户必须重新发行另一个令牌。我只是简单地用redis做个记录,它让我可以很快找到token。

以上是关于使用 Redis 检查每个请求的访问令牌的主要内容,如果未能解决你的问题,请参考以下文章

太频繁地更新访问令牌是不好的做法吗?

在每个请求之前重新加载凭据是一个好习惯吗?

我应该为每个请求从 sessionStorage 获取访问令牌吗?

每个请求的 JWT 令牌验证?

在不往返授权服务器的情况下检查访问令牌的有效性?

DocuSign JWT 访问令牌请求