我正在为一个网站创建一个配置文件系统,我正在PHP中编码密码重置功能。
基本上,我要求用户提供他们的电子邮件地址,然后设置一个随机md5密码并通过电子邮件发送给他们它以格式为
的链接形式出现www.mysite.com/reset.php ?电子邮件= myemail@myemail.com&散列= hashgoeshere
当有人可以伪造密码重置链接并使用哈希值而不是密码时,在md5后面隐藏密码有什么意义?
您应该选择如下的工作流:
- 生成一个新的GUID,将其保存到用户帐户中,将其命名为PasswordResetToken
- 您发送的邮件应该重定向用户到/reset.php?email=myemail@email.com&resetToken=XXXXXXXXXXX
- 您验证指定的用户帐户的重置令牌是否存在
- 要求用户输入自己选择的新密码并保存。
- 使保存的重置令牌无效,使其不能再次使用
这将是极其/统计上不太可能有人可以猜到一个链接,设置某人的密码为他们所选择的,除非(a)重置请求真的为该帐户,和(b)他们可以碰巧猜测你生成的GUID。
问题是,您不应该在链接中发送令牌的哈希值(甚至密码),而是发送随机的令牌:
http://www.example.com/reset.php?token=78dk3hi3479s8j383o98u3
在数据库中存储令牌的散列和用户id。现在,当用户单击链接时,您将获得令牌,并可以再次计算该令牌的哈希值。如果它与数据库中存储的散列匹配,那么您可以允许用户重置他的密码。
由于攻击者必须发送原始令牌,并且您在服务器端计算哈希值,因此他无法伪造有效令牌。这还可以在攻击者对数据库具有读访问权(sql注入)的情况下保护令牌。