建立激活/密码重置链接的最佳方式

Posted

技术标签:

【中文标题】建立激活/密码重置链接的最佳方式【英文标题】:Best way to build an activation/password reset link 【发布时间】:2017-06-04 14:31:55 【问题描述】:

构建包含激活或密码重置令牌的链接的最佳方法是什么?该 URL 将通过电子邮件发送,用户需要单击它来激活他们的帐户或重置他们的密码。这方面有很多线索,但似乎没有一致的方法,从安全和开发的角度来看,每种方法似乎都有优点和缺点:

    链接在查询字符串中包含令牌作为参数和电子邮件地址

    http://www.example.com/activations/:token?email=joe@gmail.com
    

    通过这种方法,令牌在数据库中进行哈希处理,电子邮件用于查找用户。然后使用 brycpt 之类的库将令牌与数据库中的散列版本进行比较。似乎包含敏感数据,例如查询字符串中的电子邮件地址,exposes some security risks。

    链接仅包含令牌作为参数或查询字符串。

    http://www.example.com/activations/:token
    

    这似乎是理想的解决方案,但我不知道如何比较令牌,除非存储在数据库中的令牌未经过哈希处理。从安全的角度来看,一些人认为token in the database doesn't need to be hashed,而另一些人则认为token should be hashed。假设我们在数据库中保留一个散列令牌,遍历数据库中的每个令牌并与链接中的令牌进行比较似乎非常耗时,尤其是在具有大量用户的应用程序中。所以也许我对此有误,但似乎使用这种方法需要我将令牌存储在未散列的数据库中。

有人对最佳方法有任何想法吗?

【问题讨论】:

【参考方案1】:

没有反对使用仅包含令牌的方法 2。

应该只将令牌的哈希值存储在数据库中(SQL 注入)是正确的。您看到的问题来自使用 BCrypt:

    Bcrypt 包含一个 salt,可防止在数据库中搜索令牌。 由于 BCrypt 应用了key-stretching,因此验证速度非常慢,因此无法检查每个存储的哈希值。

这两种技术,salting 和 key-stretching,对于存储弱密码是强制性的,它们使暴力破解变得不切实际。因为我们的令牌是一个非常强大的“密码”(至少 20 个字符,0-9 a-z A-Z),所以不需要这些技术,您可以将令牌的未加盐 SHA-256 存储在数据库中。这样的散列可以直接用 SQL 搜索。

为了证明它真的很安全,让我们做一个简单的计算。 20 个字符的标记将允许 7E35 组合。如果我们可以计算出3 Giga SHA-256 per second,我们仍然预计大约需要 3'700'000'000'000'000'000 年才能找到匹配项。

只需确保令牌是从加密随机源创建的。

【讨论】:

感谢您的回答!我一直在使用 bcrypt 来散列,所以我从来没有想过我可以在不使用盐的情况下进行散列!

以上是关于建立激活/密码重置链接的最佳方式的主要内容,如果未能解决你的问题,请参考以下文章

创建链接以重置密码的最佳做法是啥? [关闭]

Oracle 激活用户及重置密码

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

如何创建密码重置链接?

如何激活密码策略以在 OpenLDAP/windows 中使用扩展操作进行密码重置

ASP.NET MVC 中密码重置的最佳实践