RESTful API:如何安全地存储承载API令牌?

cod*_*_uk 5 api rest oauth github token

我正在构建一个RESTful API。我唯一的问题是如何进行身份验证,因为我想要一种无状态方法,其中服务器拥有的唯一信息就是请求本身。

所以我想我会看看大男孩是怎么做到的。

我看到大多数服务向用户/应用程序发出令牌。然后将其用于每个后续请求。例如,Twitter和GitHub使用OAuth2,我看到它们发出了承载令牌。到目前为止,一切都很好-无状态,干净且简单:

$ curl -H“授权:令牌OAUTH-TOKEN” https://api.github.com/xyz

但是我有一个问题:我是否将该OAUTH-TOKEN令牌存储在我的数据库中以验证用户……如果是,怎么办?


(编辑以澄清问题)

假设这是我的数据库表:

用户| 令牌
abc | 123
xyz | 789

第一个用户希望使用其令牌发出API请求。因此他们知道自己的令牌是“ 123”,因此他们这样做:

curl -H“授权:承载123” https://myapi.com

这就是我的API所必须提供的所有信息,因此它查找WHERE token =“ 123”,并发现它是用户“ abc”。简单。都好。回复已返回。

理想情况下,我希望我的表是这样的(简单,没有开销),所以我的问题确实是:这样将令牌存储在数据库中是个坏主意吗?

(我想这是因为我习惯于仅由于处理正常的电子邮件/密码行而认为这很不好)

因此,然后我就想,好吧,让我们说我必要散在我的表这些令牌:我怎么会再看看行?那是关于哈希值查找的最后一个问题所在:我假设会有冲突的可能性,因为如果两个令牌具有相同的哈希值,那么如果您基于哈希值进行查找,就不会确定知道哪个用户发出了请求吗?

这使我想到了如何添加如何标识行的附加值。就像您既需要电子邮件又需要密码来标识行(而不仅仅是密码)一样,我想知道对于API请求而言,等效的内容是什么。但是,是的,最简单的解决方案是最好的,我认为将其与令牌一起传递确实可以很好地解决问题。

因此,您确实回答了“如果我确实需要存储散列的令牌,如何识别行”的问题。

唯一剩下的问题是“我什至需要将它们存储为散列-并产生这种开销吗?”

Sør*_*sen 5

我在这里没有看到问题,所以我想我误解了你的问题。这是我认为您要问的问题,请纠正我的错误:

  1. 您对身份验证的唯一要求是它是无状态的。具体来说,使用 OAuth不是必需的。
  2. 身份验证适用于您的REST API。API 令牌不用于代表您的用户访问某些其他服务。

假设这是真的,那么您可以简单地在 auth 标头中发送更多信息,而不仅仅是令牌。一个例子可能是:

Authorization: MyScheme base64urlEncodedUserName.base64urlEncodedAccessToken
Run Code Online (Sandbox Code Playgroud)

这将允许您根据用户名执行查找。

我也不明白为什么使用令牌作为密钥是一个问题,即使你将它散列存储。只是散列传入的令牌并根据散列值执行查找?


编辑:感谢您澄清问题,改进了以下回复:

在数据库中存储未散列的访问令牌是否不好?

是和否。通过存储令牌而不是用户密码,您消除了将用户密码暴露给攻击者的危险,他/她可能在多个站点中重复使用了该密码。所以它绝对没有存储未散列的密码那么糟糕。

但它仍然可能很糟糕,这取决于令牌授予访问权限的信息或操作类型 - 如果它用于论坛软件之类的东西,那么它可能没问题。如果涉及信用卡信息,那肯定是不好的。

问题本质上变成了:攻击者可以用访问令牌做什么,而他(她)已经无法做到这一点,已经入侵了数据库?如果使用令牌唯一可用的信息已经存储在数据库中,并且不能使用令牌执行危险操作,那么对令牌进行哈希处理几乎不会获得额外的安全性。

散列令牌会导致冲突吗?

嗯,这实际上提出了一个有趣的观点。许多人使用普通的散列函数和盐一起散列他们的密码。这可能会导致冲突,是的。但是,如果您对令牌进行散列,则应该使用加密散列函数来进行。在这种情况下,碰撞的机会足够低(至少如果令牌足够长),它可能会被忽略。

请参阅为什么应该对密码进行散列如何安全地存储密码以了解一些不错的加密散列。