为什么要将 JWT 的 Refresh Token 存储在服务器数据库中?存储访问令牌会更好吗?

Why should I store Refresh Token for JWT in the server database? Would storing access token instead be better?

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

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

我也在考虑在 redis 中存储最新的 access-token 而不是 refresh-token 作为 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

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

  • “但是既然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. 我看不出这样做的理由。假设您有一个 Web 应用程序和一个移动应用程序连接到 RESTful API,如果用户同时登录这两个应用程序,他将拥有多个有效的访问令牌和刷新令牌,因此这对用户来说是完全正常的同时拥有多个有效令牌。
  3. 如果用户注销,只需从他的设备中删除访问令牌和刷新令牌,此外,从数据库中删除刷新令牌。在访问令牌上使用较短的过期时间(15 分钟很常见),因此您无需存储它们,因为它们很快就会过期。就是这样。