【问题标题】:Should I store JWT tokens in redis?我应该将 JWT 令牌存储在 redis 中吗?
【发布时间】:2017-12-07 00:24:44
【问题描述】:

我正在使用 ExpressJS、Mongodb(Mogoose) 构建一个应用程序。应用程序包含用户在访问它之前必须经过身份验证的路由。

目前我已经编写了一个快速中间件来做同样的事情。在这里,借助 JWT 令牌,我进行 mongodb 查询以检查用户是否经过身份验证。但觉得这可能会给我的数据库带来不必要的请求负载。

我应该为这个特定任务集成 redis 吗?
它会提高 API 性能吗?或者应该继续现有的 mongodb的方法?

如果我对此有更多见解会有所帮助。

【问题讨论】:

  • 为什么需要存储 JWT 令牌? JWT 不是用于无状态身份验证,您不需要在服务器端存储令牌,而是让客户端保留它,您只需要验证签名以查看数据是否真实。因此,在服务器端使用无状态的好处是您无需担心与会话相关的问题,您所做的恰恰相反。
  • @Redisson_RuiGu 谢谢,明白你的意思。什么是查找用户是否经过身份验证的正确方法,1)如果 jwt.verify() 返回一些有效令牌(我相信这已经足够了),2)或者我应该拿这个令牌并检查数据库(我认为这个有点贵)?
  • 您可以将用户角色和其他信息保留在有效负载部分中,然后您可以在验证令牌时了解他/她是否经过身份验证。未经身份验证的用户不会拥有一个。
  • @Redisson_RuiGu 在一种情况下我仍然感到困惑。假设我们有一个用户 (U1) 登录并存储了有效的令牌。现在管理员已删除/停用该用户 (U1)。在这种情况下,我不想让该用户 (U1) 访问真实路由。我应该如何处理这种情况?有没有办法根据用户信息(比如用户 ID)撤销 JWT 令牌?或者应该在每个请求上检查数据库以检查用户是否有效/存在。
  • 在这种情况下维护黑名单与维护白名单没有区别吗?你只是在使用 Redis 说“这个令牌还没有'注销'”

标签: node.js mongodb express redis jwt


【解决方案1】:

TLDR:如果您希望能够在某个时候撤销令牌,是的,将其存储在 Redis 之类的快速设备中。

使用 JWT 的一个有据可查的缺点是,如果例如用户需要注销或令牌已被泄露,则没有简单的方法来撤销令牌。撤销令牌意味着在一些存储中查找它,然后决定下一步做什么。由于 JWT 的要点之一是避免往返于 db,因此一个很好的折衷方案是将其存储在比 rdbms 更轻松的东西中。这对 Redis 来说是一项完美的工作。

正如 cmets 中所建议的,一个好的方法是将列表设为黑名单(即无效令牌的列表)。在每次请求时,您都会查找列表以确保令牌不存在于其中。通过使用概率算法存储令牌,您可以在查找步骤中进一步提高内存空间和性能。一种简单的方法是进行分层查找。例如,您可以有一个小型应用内商店,它只跟踪您列入黑名单的令牌的前几个(例如 1 到 4 个)字节。然后,redis 缓存将跟踪相同令牌的稍微更完整的版本(例如,前 2 到 8 个字节)。然后,您可以使用更持久的解决方案(文件系统、rdbms 等)存储列入黑名单的令牌的完整版本。这是一种乐观的查找策略,可以快速确认黑名单中不存在某个令牌(这将是更常见的情况)。如果要查找的令牌恰好与应用内黑名单中的项目匹配(因为它的前几个字节匹配),则继续在 redis 存储上进行额外查找,然后在需要时进行持久存储。一些(或全部)存储可以实现为tries 或哈希表。另一个需要考虑的高效且相对简单的实现数据结构是Bloom filter

显然,如果您经常将数百万个长期存在的令牌列入黑名单(这也可能表明您有不同的问题),则必须采用上述方法。

【讨论】:

  • 谢谢,我采取了同样的方法。在这里,我使用 redis 来跟踪所有活动用户(成对的令牌:使用 ID)。还要创建中间件来验证用户请求。该中间件检查token是否有效且在redis中是否可用,只有满足此条件,用户才能访问经过身份验证的资源。
  • @manishkeer 这不是一个很好的方法,因为你有很多用户,所以列表会有点大。相反,如果您保留黑名单,您只需要保留被撤销访问权限的用户,并且只有在令牌过期之前,您才能将令牌从黑名单中删除。另外,为什么要将使用 ID 与令牌一起存储?该信息应该已经在令牌中。这就是 JWT 的重点。
  • 谢谢。但是,对于刷新令牌,它不会是刷新令牌的白名单吗?因为如果我们有刷新令牌,我们可以将访问令牌设置为很快过期。
  • @Water 黑名单或白名单只是列出规则的例外情况。 JWT 令牌根据定义是自我验证的。如果他们使用安全签名,您可以相信他们会携带有效信息。这里的例外是当某些有效令牌应该被阻止访问时(无论出于何种原因)。因此,我们需要一个令牌列表来阻止,不管是黑名单。
  • @MichaelEkoka 有一件事我无法理解。如果我们将失效的令牌存储在 redis 中,这些令牌将在某个时间间隔内被删除。这一刻,那个令牌不是又被认为是经过验证的令牌吗?我认为刷新令牌应该在用户登录后立即存储到 redis,以便在一段时间内自动删除。
【解决方案2】:

您可以使用 Redis 来存储 jwt 标签。 Redis 存储此类数据更快、更方便。对 Redis 的请求应该不会对性能产生太大影响。你可以试试图书馆jwt-redis

【讨论】:

    猜你喜欢
    • 2020-10-03
    • 2019-04-25
    • 1970-01-01
    • 2015-09-15
    • 2016-09-13
    • 2020-10-25
    • 2016-12-03
    • 2016-12-16
    • 1970-01-01
    相关资源
    最近更新 更多