API请求中的访问令牌与用户名/密码

24

我知道这可能看起来像一个琐碎的问题,但我找不到答案,至少能让我心安。

如果一个移动应用正在与服务器通信,通常他们会登录并获得一个访问令牌,可以在整个会话中用于任何未来请求。

为什么不直接通过每个请求的HTTPS传递用户名和密码,而不是使用访问令牌。访问令牌需要与数据库进行验证,用户名/密码的组合也是如此。为什么要额外付出获取访问令牌的努力,如果它们发挥相同的作用?我知道我遗漏了什么,但我无法弄清楚。


2
这个问题可能更适合在[security.se]上,但非常快速的答案包括使用OAuth意味着客户端应用程序永远不会看到用户名和密码,并且访问令牌可以具有比完整密码更受限制的权限集。 - Ken Y-N
3个回答

20

你说得没错,访问令牌的验证方式与用户名和密码基本相同。在访问令牌有效期内,它基本上等同于用户名和密码。在某些情况下(取决于你的威胁模型),甚至可以在每个请求中发送用户名和密码,也许不适用于移动应用程序,但例如在服务器之间的请求中,需要适当的控制。

然而,你不希望从移动应用程序的每个请求中发送密码,因为那样就必须存储密码。

密码(或实际上是用户)的问题在于它们被重用。密码是有价值的目标,因为同一个密码可能在多个服务中使用。因此,你将其交换为寿命较短的访问令牌,如果被窃取,则对用户的风险更小。而且,你无法轻松地撤销密码,强制用户更改密码会很麻烦。撤销访问令牌很容易。

虽然可能性非常小,但有时TLS存在漏洞——虽然不是很频繁,但在过去几年中确实出现了一些漏洞。这种漏洞可能允许攻击者解密 https 发送的一些流量,或者例如一段时间前 openSSL 中出现了一个漏洞,允许攻击者提取服务器内存的部分,潜在地持有用户发送的任何内容。如果仅使用访问令牌而不是实际密码,则效果要好得多。

另一个要点是,在某些情况下(在 OAuth 流程中),你的应用程序甚至不被允许访问实际密码。当用户使用第三方身份提供者(例如 Facebook)登录时,他们不希望你的应用程序接收他们的 Facebook 密码。他们只需前往 Facebook,交换他们的凭据以获取访问令牌,你只能看到该令牌,如果你需要可以与 Facebook 进行验证。但你实际上永远不会获得用户的 Facebook 密码。当然,这仅适用于身份提供者是第三方的情况。


感谢您的合作回复。当您说密码需要存储时,将其存储在移动应用程序的内存中是否安全?我的意图是将密码或访问令牌存储在内存中,这意味着一旦应用程序被杀死,所有内容都会被清除,而不是本地存储。我有没有忽略什么?此外,如果某人可以访问访问令牌(例如解密),那么该人可以执行相同的API请求,直到它被阻止或过期,对吗? - Snake
仅将令牌存储在内存中可能是最安全的,但它会带来严重的用户体验后果(即用户必须一直重新登录 - 这不是通常的移动应用程序体验)。对于许多应用程序(取决于所管理数据的敏感性),在移动操作系统提供的适当存储中存储令牌是可以接受的。当然,如果有人拥有访问令牌,则可以使用该访问令牌允许的任何请求。 - Gabor Lengyel

7

我认为答案与安全有关。

建议始终使用访问令牌而非用户名和密码,因为:

  • 访问令牌(在大多数服务中)可以轻松生成、阻止、监视其使用和统计信息,可以设置过期时间、受限权限等等……当然,您也可以完全删除它。用户名和密码是主人,可以控制访问令牌。

  • 正如我所说,访问令牌更加安全,这是最重要的。如果您在网络应用程序(或其他任何地方)中使用用户名和密码,并且该应用程序被黑客攻击(这种情况经常发生),或者有人查看其源代码,甚至某些日志系统保存请求参数-那么您的用户和密码可能会被第三方查看,您的整个帐户可能会被黑客攻击(并且可能还有其他帐户共用相同的用户名和密码)。访问令牌消除了所有这些风险。

  • 关于速度-我不认为使用用户和密码进行授权具有任何显着优势。


1
用户名/密码访问可以像访问令牌一样被阻止、监控、过期和分配权限。另外,这只是一个次要的观点,但每个请求中的100毫秒延迟对许多应用程序来说相当大。:) 但你是正确的,检查实际密码或访问令牌并不重要。有时,访问令牌会在在线服务上进行验证(发出令牌的身份提供者),在这种情况下,它不仅仅是一个数据库查找。 - Gabor Lengyel
谢谢,当你说更安全时,你是指长期而非短期更安全。对吧?我的意思是,如果有人可以访问访问令牌,那么他可以进行相同的 API 调用,直到令牌被撤销(在短期内提供访问)。 - Snake
@Snake Safety不认为有“短期”或“长期”之分 - 我的意思是,如果有人能够进入您的应用程序源代码,那么他可以看到您存储的(即使加密的)用户名和密码。因此,将访问令牌置于风险之下比使用U&P更好。 - T.Todua

0
我可以想到几个原因。
1. 如果你的密码存储在本地浏览器中,那意味着如果你在登录状态下离开电脑或手机,其他人坐在电脑前就有可能看到你的密码。然而,如果他们只能看到一个访问令牌,那他们基本上没有得到任何东西。该令牌将在你退出登录后立即失效。
2. 如果你不断地将密码传递给服务器,而你的连接被黑客中断,他们现在就拥有了你的密码。然而,如果你只发送一个令牌,那么该令牌是无意义的,因为它会在你退出登录时失效(更不用说该令牌可能与你的IP地址相关,因此对他们来说是无法使用的)。
3. 这与前两个原因有关。当你想要执行一些涉及账户安全的操作时,询问你的密码有什么意义?当你想要更改密码时,询问你当前的密码又有什么意义?如果你在浏览器中已经有了当前密码的访问权限,那么你已经在每个请求中都发送了它,而每个恶意行为者坐在你的电脑或手机前,以及干扰你的电脑或手机与服务器的连接的恶意行为者都知道你的密码。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接