PHP忘记密码功能

时间:2011-07-05 16:08:06

标签: php security md5 password-recovery

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

是否可以排序'解密'并通过电子邮件发送给用户,还是需要重置密码?

12 个答案:

答案 0 :(得分:134)

MD5哈希密码不可逆。 (MD5是散列,并没有真正加密,所以有一个微妙的区别)。并且您肯定希望提供密码“重置”过程(而不是简单地通过电子邮件发送密码)。

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

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

    当您使用PHP中的md5()函数散列类似密码的值时,无论您在哪个服务器上运行该密码,最终值都将相同。 (因此,我们可以立即看到散列和加密之间的差异......没有私钥/公钥。)

    因此,您可以看到人们提到rainbow tables的漏洞。彩虹表的一个非常基本的解释是...你md5()散列一堆字典单词(弱密码),以获得他们的md5()哈希值。将它们放在数据库表(彩虹表)中。

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

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

    这是一个很好的SO Q / A应该有帮助。 Secure hash and salt for PHP passwords

答案 1 :(得分:9)

根据这篇文章The definitive guide to forms based website authentication,对于第3步和第4步,我不确定你应该发送你存储的相同令牌。

我猜你必须发送令牌,然后散列它并将散列令牌存储在DB中。否则,如果您的数据库遭到入侵,可以访问重置密码页面。

总结:

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

其中hash是一种散列算法。

答案 2 :(得分:7)

不,MD5是不可逆转的。散列密码的关键在于使得访问您数据库的攻击者无法访问每个人的密码。

也就是说,MD5(特别是未加盐的MD5)通常可以使用rainbow table进行攻击。为了安全起见,最好使用bcrypt

答案 3 :(得分:3)

您无法解密密码,甚至不应考虑通过纯文本向用户发送密码。 (这是让我再也不会使用网站的第一种方式;它是一个GIGANTIC安全漏洞。)提供一个密码重置页面,该页面是从包含与时间相关的密钥发送到用户的密码恢复电子邮件的链接触发的;这是密码恢复的当前最新技术。

答案 4 :(得分:3)

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

答案 5 :(得分:3)

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

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

答案 6 :(得分:2)

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

答案 7 :(得分:2)

编写一个接受md5和电子邮件地址作为get paramaeter的页面,并在db中查找电子邮件和md5'd密码。继Jared Cobb指出,这应该让你走上正确的道路。我刚刚添加了一些例子

例如发送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
    }

这足以让您知道用户是有效用户并更改其密码

答案 8 :(得分:2)

使用php内置的password_verify和password_hash。

答案 9 :(得分:1)

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

您需要向他们发送临时密码,然后重置密码。

答案 10 :(得分:1)

您需要进行密码重设页面。 PHP中没有办法解密MD5。

答案 11 :(得分:1)

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