是什么阻止某人伪造密码重置 link?

What stops someone from forging a password reset link?

我正在为一个网站创建配置文件系统,我正准备在 PHP 中编写密码重置功能。

基本上,我要求用户提供他们的电子邮件地址,然后设置一个随机的 md5 密码并将其通过电子邮件发送给他们,它以 link 格式出现,如

www.mysite.com/reset.php?email=myemail@myemail.com&hash=hashgoeshere

当有人可以伪造密码重置 link 并使用哈希值而不是密码时,将密码隐藏在 md5 后面有什么意义?

您应该选择如下工作流程:

  • 生成一个新的 GUID,将其保存在用户帐户中,命名为 PasswordResetToken
  • 您发送的电子邮件应将用户重定向到 /reset.php?email=myemail@email.com&resetToken=XXXXXXXXXXX
  • 您验证指定的用户帐户是否存在重置令牌
  • 要求用户输入他们选择的新密码并保存。
  • 将保存的重置令牌作废,使其无法再次使用

extremely/statistically 不太可能有人会猜到 link 将某人的密码设置为他们选择的密码,除非 (a) 确实为该帐户发出了重置请求,并且 (b ) 他们可能会猜到您生成的 GUID。

问题是,您不应该在 link 中发送令牌的哈希值(甚至密码),而是发送一个随机的 token:

http://www.example.com/reset.php?token=78dk3hi3479s8j383o98u3

在数据库中,您将令牌的 散列 与用户 ID 一起存储。现在,当用户点击 link 时,您将获得令牌并可以再次计算此令牌的哈希值。如果它与数据库中存储的哈希匹配,那么您可以允许用户重置他的密码。

由于攻击者必须发送原始令牌,而你在服务器端计算散列,他无法伪造有效令牌。这也可以保护令牌,以防攻击者具有对数据库的读取权限(SQL-注入)。