为什么要将 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
。所以不会出现下面的情况,
- 用户登录,获得
access-token
和 refresh-token
。
- 在前一个令牌仍然有效的情况下立即刷新他们的令牌。
- 注销,并使用他们的旧访问令牌。
由于大多数实现只将客户端在注销期间提供的 access-token
列入黑名单,我相信如果客户端使用 REST API,这种情况是可能的。
那么存储 refresh-token
有什么用,存储 access-token
反而会有任何好处。有关应用程序的更多信息,
- 我正在为登录用户使用
redis
,并将 access-token
列入黑名单(在注销期间提供)。
- 我将
refresh
和 access
令牌都存储在 httpOnly cookie 中,并将 access
令牌作为不记名令牌发送。
refresh-token
在刷新访问令牌时在 POST 正文中发送。
- 我没有使用
https
让我回答你的每一个问题:
- “但是既然
refresh-token
必须是服务端生成的,不能被篡改,而且我们也可以检查它是否已经过期,为什么还要存储呢”:
刷新令牌应该有很长的到期时间(可能几个月),这样用户就不必经常登录应用程序(尤其是在移动应用程序的情况下)。因此,如果有恶意者窃取了用户的刷新令牌,用户的受保护信息将长期暴露。万一发生这种情况,一个相当安全的应用程序应该有机制,例如,检测其用户 IP 地址的突然变化并报告它们。现在,如果用户确认他的帐户中存在奇怪的行为,则有必要撤销他的所有刷新令牌以保护他的信息,为此,有必要控制某个用户拥有的刷新令牌,所以必须存储它们。
- "如果它是
logout
那么我们不能只将 user_id
存储在数据库中以供已登录的人使用而不存储 refresh-token
":
您需要同时存储“user_id”和刷新令牌,以便您可以控制某个“user_id”的所有刷新令牌(如上所述)。如果您只想存储已登录用户的“user_id”(不存储刷新令牌),我不知道您将如何检查用户是否有权更新访问令牌而无需进行用户登录。
- “我也在考虑存储最新的
access-token
而不是 refresh-token
...”:
- 通过这样做,您将失去 JWT (https://restfulapi.net/statelessness) 提供的“无状态”方法的优势,因为您正在存储它们的状态。如果你真的想要这样的东西,最好使用像会话这样的“有状态”方法。
- 我看不出这样做的理由。假设您有一个 Web 应用程序和一个移动应用程序连接到 RESTful API,如果用户同时登录这两个应用程序,他将拥有多个有效的访问令牌和刷新令牌,因此这对用户来说是完全正常的同时拥有多个有效令牌。
- 如果用户注销,只需从他的设备中删除访问令牌和刷新令牌,此外,从数据库中删除刷新令牌。在访问令牌上使用较短的过期时间(15 分钟很常见),因此您无需存储它们,因为它们很快就会过期。就是这样。
我目前正在构建一个 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
。所以不会出现下面的情况,
- 用户登录,获得
access-token
和refresh-token
。 - 在前一个令牌仍然有效的情况下立即刷新他们的令牌。
- 注销,并使用他们的旧访问令牌。
由于大多数实现只将客户端在注销期间提供的 access-token
列入黑名单,我相信如果客户端使用 REST API,这种情况是可能的。
那么存储 refresh-token
有什么用,存储 access-token
反而会有任何好处。有关应用程序的更多信息,
- 我正在为登录用户使用
redis
,并将access-token
列入黑名单(在注销期间提供)。 - 我将
refresh
和access
令牌都存储在 httpOnly cookie 中,并将access
令牌作为不记名令牌发送。 refresh-token
在刷新访问令牌时在 POST 正文中发送。- 我没有使用
https
让我回答你的每一个问题:
- “但是既然
refresh-token
必须是服务端生成的,不能被篡改,而且我们也可以检查它是否已经过期,为什么还要存储呢”:
刷新令牌应该有很长的到期时间(可能几个月),这样用户就不必经常登录应用程序(尤其是在移动应用程序的情况下)。因此,如果有恶意者窃取了用户的刷新令牌,用户的受保护信息将长期暴露。万一发生这种情况,一个相当安全的应用程序应该有机制,例如,检测其用户 IP 地址的突然变化并报告它们。现在,如果用户确认他的帐户中存在奇怪的行为,则有必要撤销他的所有刷新令牌以保护他的信息,为此,有必要控制某个用户拥有的刷新令牌,所以必须存储它们。
- "如果它是
logout
那么我们不能只将user_id
存储在数据库中以供已登录的人使用而不存储refresh-token
":
您需要同时存储“user_id”和刷新令牌,以便您可以控制某个“user_id”的所有刷新令牌(如上所述)。如果您只想存储已登录用户的“user_id”(不存储刷新令牌),我不知道您将如何检查用户是否有权更新访问令牌而无需进行用户登录。
- “我也在考虑存储最新的
access-token
而不是refresh-token
...”:
- 通过这样做,您将失去 JWT (https://restfulapi.net/statelessness) 提供的“无状态”方法的优势,因为您正在存储它们的状态。如果你真的想要这样的东西,最好使用像会话这样的“有状态”方法。
- 我看不出这样做的理由。假设您有一个 Web 应用程序和一个移动应用程序连接到 RESTful API,如果用户同时登录这两个应用程序,他将拥有多个有效的访问令牌和刷新令牌,因此这对用户来说是完全正常的同时拥有多个有效令牌。
- 如果用户注销,只需从他的设备中删除访问令牌和刷新令牌,此外,从数据库中删除刷新令牌。在访问令牌上使用较短的过期时间(15 分钟很常见),因此您无需存储它们,因为它们很快就会过期。就是这样。