php PHP忘记密码功能

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6585649/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 00:47:45  来源:igfitidea点击:

PHP Forgot Password Function

phpsecuritymd5password-recovery

提问by Liam

I have a small community website and I need to implement some sort of forgotten password function. I currently store the passwords in the DB, encrypted with MD5.

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

Is it possible to sort of 'decrypt' and send it to user via email or would I need to have a password reset page?

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

回答by Jared Cobb

An MD5 hashed password is not reversible. (MD5 is hashing, and not really encrypting, so there's a subtle difference). And yesyou'll definitely want to provide a password "reset" process (and not simply email the password).

MD5 散列密码是不可逆的。(MD5 是散列,而不是真正的加密,所以有一个微妙的区别)。而且你一定要提供密码“复位”过程(而不是简单地通过电子邮件发送密码)。

To give you a high level workflow for secure password resets...

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

  1. When user asks to reset their password, make them enter their email address
  2. Don't indicate if that email address was valid or not (just tell them that an email was dispatched). This is open for debate as it lowers usability (i.e. I have no idea which email I registered with) but it offers less information to people trying to gather information on which emails are actually registered on your site.
  3. Generate a token (maybe hash a timestamp with a salt) and store it into the database in the user's record.
  4. Send an email to the user along with a link to your httpsreset page (token and email address in the url).
  5. Use the token and email address to validate the user.
  6. Let them choose a new password, replacing the old one.
  7. Additionally, it's a good idea to expire those tokens after a certain time frame, usually 24 hours.
  8. Optionally, record how many "forgot" attempts have happened, and perhaps implement more complex functionality if people are requesting a ton of emails.
  9. Optionally, record (in a separate table) the IP address of the individual requesting the reset. Increment a count from that IP. If it ever reaches more than, say, 10... Ignore their future requests.
  1. 当用户要求重置他们的密码时,让他们输入他们的电子邮件地址
  2. 不要指明该电子邮件地址是否有效(只需告诉他们已发送电子邮件)。这是有争议的,因为它降低了可用性(即我不知道我注册了哪个电子邮件),但它为试图收集有关哪些电子邮件实际注册在您的网站上的信息的人提供的信息较少。
  3. 生成一个令牌(可能是用盐散列时间戳)并将其存储到用户记录中的数据库中。
  4. 发送电子邮件给用户一个链接到你的http沿小号(url中令牌和电子邮件地址)复位页。
  5. 使用令牌和电子邮件地址来验证用户。
  6. 让他们选择一个新密码,替换旧密码。
  7. 此外,最好在特定时间范围(通常为 24 小时)后使这些令牌过期。
  8. 或者,记录发生了多少次“忘记”尝试,如果人们请求大量电子邮件,也许可以实现更复杂的功能。
  9. 或者,记录(在单独的表中)请求重置的个人的 IP 地址。从该 IP 增加一个计数。如果它超过了,比如说,10...忽略他们未来的要求。

To give you a little more detail into hashing...

为了让您更详细地了解散列...

When you hash a value like a password using the md5() function in PHP, the final value is going to be the same for that password no matter which server you run it on. (So there's one difference we can see right away between hashing and encryption... There's no private/public key involved).

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

So this is where you'll see people mention a vulnerability to rainbow tables. A very basic explanation of a rainbow table is... You md5() hash a bunch of dictionary words (weak passwords) in order to get their md5() hashed values. Put those in a database table (rainbow table).

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

Now, if you compromise a web site's database, you can run the users' hashed passwords against your rainbow table to (in essence) "reverse" the hash back to a password. (You're not really "reversing" the hash... But you get the idea).

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

That's where "salting" your passwords is best practice. This means (again, very basic idea here) that you append a random value to the users' passwords beforeyou hash it. Now, when the rainbow table is run against your database, it's not as easily "reversed" because the md5() hash of "password" is different than "password384746".

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

Here's a nice SO Q/A that should help. Secure hash and salt for PHP passwords

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

回答by Mansur Khan

According to this post The definitive guide to forms based website authentication, for step 3. and 4., I'm not sure you should send the same token you are storing.

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

I guess you must send the token, then hash it and stored the hashed token in DB. Otherwise, if your database is compromised, one can have access to the reset password page.

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

To summarize :

总结一下:

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

where hash is a hashing algorithm.

其中 hash 是一种散列算法。

回答by ceejayoz

No, MD5 is irreversible. The point of hashing passwords is to make it so an attacker who gets access to your database can't access everyone's passwords.

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

That said, MD5 (particularly unsalted MD5) can generally be attacked using a rainbow table. For security, you're better off using bcrypt.

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

回答by Paul Sonier

You cannot decrypt the password, and you shouldn't even consider sending a password to a user via plaintext. (That is the #1 way to make me never ever use a site again; it's a GIGANTIC security hole.) Provide a password reset page that is triggered from a link containing a time-associated key that is sent to the user's password recovery email; that's the current state of the art in password recovery.

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

回答by tom

The best thing for you to do is request people submit their email address when registering. Then if they forget, have a forgot password link which resets their password with a random value which is emailed to them so they can gain access and then change their password back to something more memorable. This way you don't need to compromise the security. You could have a link which they just need to submit their username into, butfor better security you should have a question and answer or memorable word.

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

回答by Chris

As Marcus Reed stated, in 2015/2016 if you have PHP version >=5.5 don't use MD5, password_hash() and password_verify() provide an easy and secure hashing for your password with the ability to provide a cost and automatically salts the hash.

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

I don't have the ability to vote or comment currently which is why I'm providing a definitive statement to avoid confusion.

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

回答by Marcus Reed

Use php's built in password_verify and password_hash.

使用 php 内置的 password_verify 和 password_hash。

回答by Ryan

Write a page that accepts the md5 and email address as a get paramaeter and looks in the db for the email and md5'd password. Following Jared Cobb notes, that should get you on the right path. i just added some examples as well

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

eg url to send http://yourdomain.com/resetpassword.php?code=md5codesentviaemail

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

this should be sufficient enough for you to know that the user is a valid user and change his password

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

回答by Ignacio Vazquez-Abrams

MD5 is intended to be a one-way hash. You will need to have them reset their password.

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

回答by Naftali aka Neal

No you cannot decrypt it. that is the whole idea.

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

You would need to send them a temp password and for them to reset it.

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