ChatGPT解决这个技术问题 Extra ChatGPT

刷新令牌有什么意义?

我不得不承认我有这个问题很长时间了,从来没有真正理解过。

说身份验证令牌就像保险箱的钥匙,当它过期时就不再可用了。现在我们得到了一个魔法刷新令牌,它可以用来获取另一个可用的密钥,以及另一个……直到魔法密钥过期。那么为什么不将身份验证令牌的到期时间设置为与刷新令牌相同呢?为什么要打扰呢?

它的正当理由是什么,也许是历史原因?真的很想知道。谢谢

刷新令牌不是关于更新用户角色或撤销访问权限,也不是关于仅第一次请求用户/通行证。您只需访问令牌即可实现所有这些。 主要是减少攻击服务。如需更多信息,请参阅here

K
Kiarash

前几天我正在阅读 Taiseer Joudeh 的 article,我发现它非常有用,他说:

在我自己看来,使用刷新令牌有三个主要好处:

更新访问令牌内容:如您所知,访问令牌是自包含的令牌,一旦生成,它们就会包含有关经过身份验证的用户的所有声明(信息),现在如果我们为用户颁发长期令牌(例如 1 个月)命名为“Alex”并将他注册为“用户”角色,然后此信息将包含在授权服务器生成的令牌中。如果您稍后决定(在他获得令牌后 2 天)将他添加到“管理员”角色,则无法更新生成的令牌中包含的此信息,您需要让他重新自我验证所以授权服务器将此信息添加到这个新生成的访问令牌中,这在大多数情况下是不可行的。您可能无法联系获得长期访问令牌的用户。因此,为了克服这个问题,我们需要发布短期访问令牌(例如 30 分钟)并使用刷新令牌来获取新的访问令牌,一旦您获得新的访问令牌,授权服务器将能够为用户添加新的声明一旦生成新的访问令牌,“Alex”就会将他分配给“管理员”角色撤销经过身份验证的用户的访问权限:一旦用户获得长期访问令牌,只要他的访问令牌不是,他就可以访问服务器资源已过期,除非授权服务器实现自定义逻辑,强制您将生成的访问令牌存储在数据库中并对每个请求进行数据库检查,否则没有标准方法可以撤销访问令牌。但是使用刷新令牌,系统管理员可以通过简单地从数据库中删除刷新令牌标识符来撤销访问权限,因此一旦系统使用已删除的刷新令牌请求新的访问令牌,授权服务器将拒绝此请求,因为刷新令牌不再可用(我们将详细介绍这一点)。无需存储或询问用户名和密码:使用刷新令牌允许您在用户第一次身份验证后仅向用户询问他的用户名和密码一次,然后授权服务器可以发出非常长的刷新令牌(1 年例如),除非系统管理员尝试撤销刷新令牌,否则用户将一直保持登录状态。您可以将其视为对服务器资源进行离线访问的一种方式,如果您正在构建一个将由前端应用程序使用的 API,而在这种情况下不断询问用户名/密码是不可行的,这可能会很有用。


为什么不使用短期访问令牌,在过期时检查凭据?如果用户仍然有效,则重置访问令牌的到期时间。我不明白是否需要刷新令牌?
“...一旦生成,它们就包含有关经过身份验证的用户的所有声明(信息)...”在这里,我认为将任何与用户相关的信息(即使已加密)放入令牌中也被认为是不好的做法。
那么取决于你在谈论什么用户信息。它说“所有索赔信息”而不是所有用户信息
@RickJolly:访问令牌通常包含足够的信息来识别用户及其角色,而无需访问数据库。这通常通过签名和加密的令牌(例如 hmac 签名)来实现。在原始内容中添加、删除或更改的单个字符会为您提供完全不同的签名令牌。因此,如果在对“userid:alex;role:user;client:foobar.com;ts:1552806134”进行签名和加密后,令牌看起来像“kE4ia6”,“userid:alex;role:admin;client: barbaz.net;ts:1552806565",即使是同一个用户。
@RickJolly:另一方面,刷新令牌只是指向单个用户的不透明键。您每次都需要查询数据库以查找它属于谁(性能下降)。它实际上是用户凭据的模糊表示。因此,与其将用户名:密码存储在您的客户端上,不如存储它(最佳实践)。在一个新项目中,您可以像使用访问令牌一样使用它,但由于上述限制,您最终可能需要更具可扩展性的东西。刷新令牌/访问令牌设置是一个不错的选择。
S
Stijn de Witt

我想补充另一个观点。

无状态身份验证,无需在每个请求上访问数据库

假设您想创建一个无状态(无会话)安全机制,可以对数百万用户进行身份验证,而无需进行数据库调用来进行身份验证。对于您的应用程序获得的所有流量,为每个请求节省一次数据库调用非常值得!而且它需要是无状态的,以便可以轻松地集群并扩展到数百甚至数千台服务器。

使用老式会话,用户登录,此时我们从数据库中读取他们的用户信息。为了避免一次又一次地读取它,我们将它存储在会话中(通常在内存或一些集群缓存中)。我们将会话 ID 在 cookie 中发送给客户端,该 cookie 附加到所有后续请求。在后续请求中,我们使用会话 ID 来查找会话,该会话又包含用户信息。

将用户信息直接放入访问令牌中

但我们不想要会话。因此,我们不将用户信息存储在会话中,而是将其放入访问令牌中。我们对令牌进行签名,因此没有人可以篡改它并立即生效。我们可以在没有会话的情况下对请求进行身份验证,并且不必从数据库中为每个请求查找用户信息。

没有会话...没有办法禁止用户?

但是没有会议有一个很大的缺点。例如,如果该用户被禁止怎么办?在旧场景中,我们只是删除他的会话。然后他必须再次登录,而他将无法做到这一点。禁令完成。但是在新场景中没有会话。那我们怎么禁止他呢?我们将不得不(非常有礼貌地)要求他删除他的访问令牌。根据禁止列表检查每个传入请求?是的,会起作用,但现在我们必须再次进行我们不想要的数据库调用。

与短期令牌妥协

如果我们认为用户在被禁止 10 分钟后仍然可以使用他的帐户是可以接受的,那么我们可以创建一种在每次请求检查数据库和仅在登录时检查数据库之间的折衷方案。这就是刷新令牌的用武之地。它们允许我们使用具有短期访问令牌的无状态机制。我们无法撤销这些令牌,因为没有对它们进行数据库检查。我们只根据当前时间检查它们的到期日期。但是一旦它们过期,用户将需要提供刷新令牌来获取新的访问令牌。在这一点上,我们确实检查了 DB 并看到该用户已被禁止。所以我们拒绝访问令牌的请求,禁令生效。


“但是一旦它们过期,用户将需要提供刷新令牌才能获得新的访问令牌”。为什么要刷新令牌?为什么不根据原始令牌中的凭据重新验证用户,然后如果有效,然后重置该令牌的到期日期?
@RickJolly 因为访问令牌通常不包含凭据(刷新令牌也不包含)。它的工作方式是令牌由发行人签名。所以发行者知道令牌是有效的(直到它们过期)。通常,令牌包含用户名和角色/权限等内容。然后双方可以使用令牌来显示此类信息,而无需先进行数据库/网络调用。
好的,谢谢,但是如果我们忽略我写的关于根据访问令牌中的凭据重新验证用户的内容(这可能只是检查用户 ID 是否仍然被允许),我仍然认为没有理由刷新令牌。这就是我的问题:“为什么要刷新令牌?”
@RickJolly 点了。我猜协议的设计者得出的结论是,将两个任务分开是最简单的:为所有操作提供访问令牌,并提供刷新令牌以获取访问令牌。这将刷新的责任交给了客户端,降低了服务器的复杂性。
u
user7294900

引用的答案(通过@Anders)很有帮助,它指出:

万一被泄露,它的有效时间窗口是有限的,但令牌是通过 SSL 使用的,因此不太可能被泄露。

我认为重要的部分是访问令牌通常会被记录(特别是当用作查询参数时,这对 JSONP 很有帮助),所以最好让它们短暂存在。

还有一些其他原因,服务提供商大规模实施 OAuth 2.0:

如果不必担心撤销,API 服务器可以安全地验证访问令牌而无需数据库查找或 RPC 调用。这可以带来强大的性能优势并降低 API 服务器的复杂性。如果您可以接受 30m-60m(或任何访问令牌的长度)的令牌撤销,则最好。当然,API 服务器也可以在内存中保留最近一小时内撤销的令牌列表。由于令牌可以具有多个范围并可以访问多个不同的 API 服务,因此具有短期访问令牌会阻止 API 服务的开发人员终身访问 API 服务 B 上的用户数据。划分有利于安全性。


谢谢。但是,我认为这两个额外的理由都不够有力。 1,对于拥有数百万个应用程序的大型站点,不可能将所有 access_tokens 保存在内存中,db 查找或 rpc 调用是不可避免的。当然,我没有数据支持我的论点。 2,我认为访问令牌的范围与刷新令牌相同,至少在google的实现中是这样。因此,即使刷新令牌泄露,也无法进行跨范围攻击。
我认为避免访问令牌被记录是一个更好的理由,但只有当站点 A 由用户 B 授权以获取来自发行者 C 的访问信息并且令牌以某种方式发送给第四方时才有效。在我看来,如果站点 A 托管在第四方的服务器上,就会发生这种情况……但是如果第四方可以完全访问服务器,那仍然毫无意义,对吗?
@wangii - Re #1 - 访问令牌可以使用加密或签名进行自我验证,因此不需要数据库查找或 RPC 调用。刷新令牌可以在 OAuth 提供者处保持不透明和可撤销。 Re #2 - 是的,访问令牌的范围是相同的。但是,让服务 (A) 的开发人员终身访问服务 (B) 上的用户数据比只在用户积极使用服务 (A) 时才给予他们访问权限要糟糕得多。
我不明白。您还需要针对 db / session 验证刷新令牌,使其成为有状态的。此外,您需要在存储刷新令牌之前对其进行加密,并检查黑名单,这会导致额外的开销。给定一个短暂的访问令牌,你可能需要做很多检查......你能澄清一下吗?
@KimGysen 抱歉,我不确定您没有得到哪一部分。确实需要根据数据库或撤销列表检查刷新令牌,但其想法是每次刷新都会多次使用访问令牌。 (即 XX 或 XXX API 请求。
B
B M

缩短可能的答案:

刷新令牌允许令牌的范围/不同衰减时间。实际资源令牌是短暂的,而刷新令牌可以保持多年有效(移动应用程序)。这带来了更好的安全性(资源令牌不必受到保护)和性能(只有刷新令牌 API 必须检查数据库的有效性)。


这对我来说似乎是最清晰和最好的答案......谢谢。
为什么资源令牌不必受到保护?是因为它们的寿命很短,而且如果它们受到损害,风险会更小,因为它们很快就会过期吗?
@QuinnComendant 完全正确。更准确的可能是:资源令牌的保护不太重要,因为它们的寿命很短,并不是说它们不需要任何保护。
t
treecon

以下是已经提到的刷新令牌的好处的补充。

安全第一!

访问令牌是短暂的。如果有人窃取了访问令牌,他只能在访问令牌过期之前访问资源。

“......但是如果刷新令牌被盗怎么办?”

如果攻击者窃取了刷新令牌,他可以获得访问令牌。出于这个原因,它建议每次获得新的访问令牌时都发布一个新的刷新令牌。如果相同的刷新令牌被使用了两次,则很可能意味着刷新令牌被盗了。

当每次使用后刷新令牌发生变化时,如果授权服务器曾经检测到刷新令牌被使用了两次,则意味着它可能已被复制并正在被攻击者使用,并且授权服务器可以撤销所有访问令牌和刷新令牌相关联立即使用它。

https://www.oauth.com/oauth2-servers/making-authenticated-requests/refreshing-an-access-token/

当然,这只是另一层安全性。攻击者仍有时间获取访问令牌,直到第二次使用刷新令牌(攻击者或真实用户)。

请始终牢记,刷新令牌必须尽可能安全地存储。