首页 > 解决方案 > 为什么要在服务器数据库中存储 JWT 的刷新令牌?存储访问令牌会更好吗?

问题描述

我目前正在构建一个 Node.js 应用程序并尝试使用 JWT 来处理会话。在我见过的每个实现中,它refresh-token都存储在一个快速的数据库中,比如redis. 当令牌过期时,客户端发送refresh-token来获取新的access-token,然后服务器检查 是否refresh-token在数据库中,然后生成一个新的令牌。

但是既然refresh-token必须是服务端生成的,不可篡改,而且我们还可以检查是否过期,为什么还要存储呢。如果是这样,logout那么我们不能只将user_id已登录的人存储在数据库中而不存储refresh-token.

我也在考虑存储最新的access-token而不是refresh-tokeninredis作为user_id. 原因是我们access-token只会在前一个过期时生成一个新的。所以下面的场景不可能发生,

  1. 用户登录、获取access-tokenrefresh-token.
  2. 立即刷新他们的令牌,而前一个令牌仍然有效。
  3. 注销,并使用他们的旧访问令牌。

由于大多数实现仅access-token在注销期间将客户端提供的黑名单,我相信如果客户端使用 REST API,这种情况是可能的。

那么存储 , 有什么用refresh-token,并且存储access-token会以任何方式有益。有关应用程序的更多信息,

  1. redis用于登录用户,并列入黑名单access-token(在注销期间提供)。
  2. 我将refreshaccess令牌都存储在 httpOnly cookie 中,并将access令牌作为不记名令牌发送。
  3. refresh-token在刷新访问令牌时在 POST 正文中发送。
  4. 我没有使用https

标签: node.jsexpressredisjwt

解决方案


让我回答你的每一个问题:

  • “但是既然refresh-token必须是服务端生成的,不可篡改,而且我们也可以检查是否过期,为什么还要存储”:

刷新令牌意味着有很长的过期时间(可能是几个月),这样用户就不必经常登录应用程序(尤其是在移动应用程序的情况下)。因此,如果恶意人员盗取用户的刷新令牌,用户的受保护信息将长期暴露。如果发生这种情况,一个相当安全的应用程序应该有机制来检测用户 IP 地址的突然变化并报告这些变化。现在,如果用户确认他的帐户中存在奇怪的行为,则有必要撤销他的所有刷新令牌以保护他的信息,为此,需要控制某个用户拥有的刷新令牌,所以它们必须被存储。

  • “如果是这样,logout那么我们不能只将user_id已登录的人存储在数据库中而不存储refresh-token“:

您需要同时存储“user_id”和刷新令牌,以便您可以控制某个“user_id”的所有刷新令牌(如上所述)。如果您只想存储登录用户的“user_id”(不存储刷新令牌),我不知道您将如何检查用户是否有权更新访问令牌而无需让用户登录。

  • “我也在考虑存储最新的access-token而不是refresh-token......”:
  1. 通过这样做,您将失去 JWT ( https://restfulapi.net/statelessness )提供的“无状态”方法的优势,因为您正在存储它们的状态。如果你真的想要这样的东西,最好使用像会话这样的“有状态”方法。
  2. 我看不出这样做的理由。假设您有一个连接到 RESTful API 的 Web 应用程序和一个移动应用程序,如果用户同时登录这两个应用程序,他将拥有多个有效的访问令牌和刷新令牌,因此用户同时拥有多个有效令牌是完全正常的时间。
  3. 如果用户注销,只需从他的设备中删除访问令牌和刷新令牌,此外,从数据库中删除刷新令牌。对访问令牌使用较短的过期时间(15 分钟很常见),因此您无需存储它们,因为它们会很快过期。而已。

推荐阅读