36

我有一个小型社区网站,我需要实现某种忘记密码的功能。我目前将密码存储在数据库中,使用MD5.

是否可以对“解密”进行排序并通过电子邮件将其发送给用户,还是我需要一个密码重置页面?

4

12 回答 12

136

MD5 散列密码不可逆。(MD5 是散列,而不是真正的加密,所以有一个细微的差别)。的,您肯定会想要提供密码“重置”过程(而不仅仅是通过电子邮件发送密码)。

为您提供安全密码重置的高级工作流程...

  1. 当用户要求重置密码时,让他们输入他们的电子邮件地址
  2. 不要指出该电子邮件地址是否有效(只是告诉他们已发送电子邮件)。这是有争议的,因为它降低了可用性(即我不知道我注册了哪封电子邮件),但它为试图收集有关哪些电子邮件实际在您的网站上注册的信息的人提供的信息较少。
  3. 生成一个令牌(也许用盐散列时间戳)并将其存储到用户记录中的数据库中。
  4. 向用户发送一封电子邮件以及指向您的 http 重置页面的链接 url 中的令牌和电子邮件地址)。
  5. 使用令牌和电子邮件地址来验证用户。
  6. 让他们选择一个新密码,替换旧密码。
  7. 此外,最好在特定时间范围(通常是 24 小时)后使这些令牌过期。
  8. (可选)记录发生了多少“忘记”尝试,如果人们请求大量电子邮件,则可能实现更复杂的功能。
  9. 或者,记录(在单独的表中)请求重置的个人的 IP 地址。从该 IP 增加计数。如果它超过了,比如说,10...忽略他们未来的请求。

为了让您更详细地了解哈希...

当您使用 PHP 中的 md5() 函数对密码之类的值进行哈希处理时,无论您在哪个服务器上运行该密码,最终值都将是相同的。(所以我们可以立即看到散列和加密之间的一个区别......不涉及私钥/公钥)。

所以在这里你会看到人们提到彩虹表的漏洞。彩虹表的一个非常基本的解释是......您 md5() 散列一堆字典单词(弱密码)以获得它们的 md5() 散列值。将它们放在数据库表(彩虹表)中。

现在,如果您破坏了网站的数据库,您可以针对您的彩虹表运行用户的散列密码,以(实质上)将散列“反转”回密码。(你并没有真正“反转”哈希......但你明白了)。

这就是“加盐”密码的最佳做法。这意味着(再次,这里非常基本的想法)您在散列之前将随机值附加到用户的密码。现在,当彩虹表针对您的数据库运行时,它不会那么容易“反转”,因为“password”的 md5() 哈希与“password384746”不同。

这是一个很好的 SO Q/A 应该会有所帮助。PHP 密码的安全哈希和盐

于 2011-07-05T16:10:11.653 回答
9

根据这篇文章基于表单的网站身份验证的权威指南,对于第 3 步和第 4 步,我不确定您是否应该发送您存储的相同令牌。

我想您必须发送令牌,然后对其进行哈希处理并将哈希令牌存储在数据库中。否则,如果您的数据库遭到破坏,则可以访问重置密码页面。

总结一下:

$token = md5(microtime (TRUE)*100000);
$tokenToSendInMail = $token;
$tokenToStoreInDB = hash($token);

其中 hash 是一个散列算法。

于 2013-05-22T16:28:08.887 回答
7

不,MD5 是不可逆的。散列密码的目的是使访问您的数据库的攻击者无法访问每个人的密码。

也就是说,MD5(尤其是未加盐的 MD5)通常可以使用彩虹表进行攻击。为了安全起见,最好使用bcrypt

于 2011-07-05T16:10:19.463 回答
3

您无法解密密码,甚至不应该考虑通过明文向用户发送密码。(这是让我永远不再使用网站的#1 方法;这是一个巨大的安全漏洞。)提供一个密码重置页面,该页面由包含时间相关密钥的链接触发,该密钥发送到用户的密码恢复电子邮件; 这就是密码恢复的最新技术。

于 2011-07-05T16:12:50.183 回答
3

您最好的办法是要求人们在注册时提交他们的电子邮件地址。然后,如果他们忘记了,有一个忘记密码链接,该链接使用一个随机值重置他们的密码,该值通过电子邮件发送给他们,这样他们就可以获得访问权限,然后将他们的密码改回更容易记住的东西。这样您就不需要损害安全性。你可以有一个链接,他们只需要提交他们的用户名,但为了更好的安全性,你应该有一个问题和答案或令人难忘的单词。

于 2011-07-05T19:37:02.987 回答
3

正如 Marcus Reed 所说,在 2015/2016 年,如果您的 PHP 版本 >=5.5,请不要使用 MD5,password_hash() 和 password_verify() 为您的密码提供简单且安全的散列,并能够提供成本并自动加盐哈希。

我目前没有投票或评论的能力,这就是我提供明确声明以避免混淆的原因。

于 2016-03-25T17:38:50.740 回答
2

MD5 旨在成为一种单向哈希。您需要让他们重置密码。

于 2011-07-05T16:09:55.907 回答
2

编写一个接受 md5 和电子邮件地址作为获取参数的页面,并在数据库中查找电子邮件和 md5 密码。按照 Jared Cobb 的说明,这应该会让你走上正确的道路。我也添加了一些示例

例如 url 发送http://yourdomain.com/resetpassword.php?code=md5codesentviaemail

 $code = isset($_GET['code']) ? $_GET['code'] : '';
    $email = isset($_GET['email']) ? $_GET['email'] : '';
$checkPw = '';

    if(empty($code) || empty($email))
    {
     die();
    }
    $sqlQuery = 'SELECT * FROM users WHERE email = "'.$email.'";
//remember to check for sql injections
    //then get the results as an array, i use a database class eg $user

    if(!empty($user['password']))
    {
     $checkPw = md5($user['password']);
    }else
    {
     die();
    }

    if($checkPw !== $code)
    {
     die();
    }else
    {
    //display form for user to change password
    }

这应该足以让您知道用户是有效用户并更改他的密码

于 2011-07-05T16:35:50.077 回答
2

使用 php 内置的 password_verify 和 password_hash。

于 2015-06-03T00:45:24.533 回答
1

不,你不能解密它。这就是整个想法。

您需要向他们发送临时密码并让他们重置密码。

于 2011-07-05T16:10:02.290 回答
1

您需要执行密码重置页面。PHP 无法解密 MD5。

于 2011-07-05T16:10:16.900 回答
1

MD5是单向功能。你不能解密它。所以你需要有一个密码重置页面。

于 2011-07-05T16:13:46.767 回答