密码重置令牌存储 - 值应该被散列吗?

Posted

技术标签:

【中文标题】密码重置令牌存储 - 值应该被散列吗?【英文标题】:Password reset token storage - should values be hashed? 【发布时间】:2019-06-23 10:46:39 【问题描述】:

我使用从bin2hex() 生成的令牌让用户重置密码。此令牌按原样存储在数据库中,当用户使用它时,他们的令牌会针对数据库中的令牌进行搜索,如果它们相同,则可以重置密码。

我在这里(php - How to implement password reset and token expiry)读到我应该在存储之前对密码进行哈希处理。这似乎是个好主意,但我想知道如何搜索散列密码,是否还需要在发送给用户的基于令牌的 url 中包含用户名/电子邮件,以便可以再次搜索它们并且然后检查哈希令牌?

是否可以在重置链接中包含一个明显的标识符(我想这是因为它被发送到他们的电子邮件地址)。

【问题讨论】:

重置令牌只是随机字符串。它们不应该包含任何信息,因此没有什么可以散列的。您的用户表将有一个用于存储唯一令牌的 reset_token 列。如果您希望令牌过期,那么还要添加一个 reset_token_expire 列。我认为您可能使问题过于复杂。 我想我很担心,基于此链接 (***.com/questions/3164978/…) 中的讨论,如果令牌以纯文本形式存储并且有人获得了对数据库的访问权限,那么他们将拥有该令牌对安全产生影响。你是对的,对于一个小应用程序来说它可能过于复杂。 【参考方案1】:

是的,您应该散列密码重置令牌,因为

重置令牌过期,并非每个用户都有一个活动令牌 用户在更改密码时会注意到,但在更改密码时不会注意到 密码被破解,因此可以采取措施限制损害 (更改密码和其他敏感数据等)。

此外,由于用户重复使用密码,攻击者可以尝试破解其他帐户的密码,例如用户的电子邮件,从而增加损失。

要点:

如果您的令牌有足够的熵,假设 20 个随机字符 0-9 a-z A-Z,那么您可以计算一个无盐快速哈希(例如 SHA-256 或 SHA-512)并存储它。这是安全的,因为不可能成功地暴力破解如此强大的“密码”。盐渍已完成,因为人们选择的密码通常相对较弱,因为它们必须被记住。

如果“密码重置令牌”允许某人使用其他明文信息重置密码,那么它实际上与密码和Should be treated as such 相同。 让它们在几分钟或几小时后过期,并将它们视为秘密,因为它们是。

我希望这会有所帮助

【讨论】:

感谢您的回答。我的令牌来自 bin2hex(random_bytes(64)) 所以应该可以防止暴力攻击。我仍然不完全清楚如何使用用户明文令牌与存储的散列令牌搜索数据库?也许我错过了什么。 好的,我想我现在明白了: 1. 生成一个长随机字符串 $token 并将其作为明文作为 url 的一部分发送给用户 2. 使用 hash(md5, $令牌)并将其存储在数据库中 3. 当用户使用基于令牌的 url 时,抓取明文令牌,对其进行哈希处理并在数据库中查找结果,然后检查它是否仍然有效。事实上,md5 散列总是产生我错过的相同字符串。再次感谢您

以上是关于密码重置令牌存储 - 值应该被散列吗?的主要内容,如果未能解决你的问题,请参考以下文章

以 html 帖子形式存储重置密码令牌是不是安全?

生成重置密码令牌的最佳实践

如何创建密码重置链接?

Laravel 手动生成重置密码令牌:收到错误“此密码重置令牌无效”

身份密码重置令牌无效

Laravel 更改密码重置特定令牌的令牌持续时间