【问题标题】:Best practice on generating reset password tokens生成重置密码令牌的最佳实践
【发布时间】:2013-11-29 14:08:55
【问题描述】:

关于如何构建重置密码令牌的任何最佳实践?我在想:

随机 17 个字符 [a-zA-Z0-9] + 一个全局唯一 id + 随机 17 个字符 [a-zA-Z0-9]。

是否有更好的解决方案或重置密码令牌的行业标准?

【问题讨论】:

    标签: passwords guid reset-password


    【解决方案1】:

    有一些要点需要考虑。

    1. 代码应该是真正随机的(从 MCRYPT_DEV_URANDOM 读取),不应从其他与用户相关的信息中推导出来。
    2. 理想情况下,代码采用 base62 编码 (A-Z a-z 0-9),以避免出现 Url 问题。
    3. Store only a hash of the token in the database,否则具有数据库读取权限的攻击者可以重置任何帐户。

    这导致在用户点击链接后,您必须在数据库中找到令牌的哈希值。存储令牌有两种可能的方式:

    • 您可以使用 SHA512 之类的哈希算法对令牌进行哈希处理,而无需使用盐。如果令牌非常强(最小长度 20,0-9 a-z A-Z),这是安全的。从理论上讲,您必须在将此类哈希输入数据库之前检查它是否已经存在,实际上这可以忽略不计。我实现了一个可以处理此类令牌的password-reset class
    • 您使用 BCrypt 和 salt 对令牌进行哈希处理。这允许更短的令牌,但您无法在数据库中搜索散列令牌。相反,您必须在链接中包含 row-id 才能找到令牌。

    【讨论】:

    • 谢谢你的课 (martinstoeckli.ch/php/StoPasswordReset.zip) 太棒了。特别是generateRandomBase62String()hashTokenWithBcrypt()。太棒了。
    • 关于#3,出于同样的原因,我总是做同样的事情。然而,进一步思考,访问数据库的攻击者不能简单地散列已知的纯文本,将该散列存储在数据库中,然后在密码重置 URL 中使用他选择的纯文本吗?我想攻击者需要访问数据库,以及知道使用了哪种散列算法,但这似乎是一个更小的搜索空间。
    • @DustinRasener - 获得对数据库的写访问权限比仅读访问权限要困难得多。您可以通过 SQL 注入、丢弃的备份、处置的服务器获得读取访问权限……另一方面,如果攻击者有写入数据库的权限,他不需要重置密码,他可以简单地覆盖密码哈希直接。
    • 有关Should password reset tokens be hashed when stored in a database? 的更多信息。另请注意,您的重置令牌应该过期
    • 我猜第二个选项在技术上无论如何都会更好地防御在线暴力攻击,因为每次尝试都必须不只是匹配许多用户中的任何一个,而是单个特定用户。尽管实际上,适当的锁定逻辑应该使这方面的任何好处一开始就可以忽略不计。
    猜你喜欢
    • 2013-09-25
    • 2010-12-10
    • 2017-04-06
    • 2011-03-08
    • 1970-01-01
    • 1970-01-01
    • 2019-12-05
    相关资源
    最近更新 更多