忘记密码页面,创建生成的密码以通过电子邮件发送给用户.

2022-01-05 00:00:00 sql php phpmyadmin

我正在尝试创建一个忘记密码页面.我听说通过电子邮件将原始密码发送给用户不是一个好主意,因此我尝试创建一个随机确认密码,他们可以使用该密码登录他们的帐户,然后将密码更改为他们想要的任何密码.到目前为止,问题是说用户的电子邮件实际上不在数据库中.另外,我应该更新数据库以存储随机密码还是我的方式可以工作?我的数据库有表用户名、名字、电子邮件和密码.我在 html 表单中询问用户他们的电子邮件地址,然后将其发送到这个 php 表单.这是我第一次尝试这样做,所以它可能有很多错误,但我找到了一个教程来帮助一些人,所以它不应该.谢谢您的帮助.

I am trying to create a forgot password page. I have heard that it is not a good idea to send the original password to the user via email so I am trying to create a random confirmation password that they can use to log into their account and later change the password to whatever they want. So far the problem is it is saying the users email is not in the database when in fact it is. Also, should I update the database to store the random password or will the way I have it work? My database has the tables username, fristname, email, and password. I am asking the user for their email address in a html form then sending it to this php form. This is my first time attempting to do this so it might have a lot of errors, but I found a tutorial to help some so it shouldn't. Thanks for the help.

<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Sending Password</title>
    </head>
    <body>
        <?php
      $db_server = "server";
       $db_username = "name";
       $db_password = "pass";

       $con = mysql_connect($db_server, $db_username, $db_password);if (!$con)
                {
                    die('Could not connect: ' . mysql_error());
                }

               $database = "Test_Members";  

              $er = mysql_select_db($db_username);
        if (!$er) 
        {
         print ("Error - Could not select the database");
         exit;
        }        

        //include "session.php";


function createRandomPassword() {



    $chars = "abcdefghijkmnopqrstuvwxyz023456789";

    srand((double)microtime()*1000000);

    $i = 0;

    $pass = '' ;



    while ($i <= 7) {

        $num = rand() % 33;

        $tmp = substr($chars, $num, 1);

        $pass = $pass . $tmp;

        $i++;

    }
    return $pass;

}

$password = createRandomPassword();
$password =$_P0ST['password']; 
      $email = $_P0ST['email']; 

        $tbl_name=Account_Holders;


        $sql="SELECT password FROM $tbl_name WHERE email='$email'";
        $result=mysql_query($sql);

        // if found this e-mail address, row must be 1 row
        // keep value in variable name "$count"
        $count=mysql_num_rows($result);


        // compare if $count =1 row
        if($count==1){

        $rows=mysql_fetch_array($result);

        // keep password in $your_password
        $your_password=$rows['password']; //will this replace the users password with the random one? That is what I am attempting to do here. 

        // send e-mail to ...
        $to=$email;

        // Your subject
        $subject="Your Password";

        // From
        $header="from: Feed The Students";

        // Your message
        $messages= "Your password for login to our website 
";
        $messages.="Your password is $your_password 
";
        $messages.="Please change this password for security reasons. Thank you. 
";

        // send email
        $sentmail = mail($to,$subject,$messages,$header);

        }

        // else if $count not equal 1
        else {
        echo "Sorry we did not find your email in our database.";
        }

        // if your email succesfully sent
        if($sentmail){
        echo "Your password has been sent to your email address.";
        }
        else {
        echo "We can not send your password at this time.";
        }



        ?>


    </body>
</html>

推荐答案

首先,您不应该将用户的密码存储在您的数据库中 - 无论如何,不​​要以明文形式存储.我将在解决密码重置问题之前解决这个问题,因为它们已连接.

First of all, you shouldn't be storing the users' passwords in your database - not in cleartext, anyways. I'm going to address this before addressing the password reset problem since they're connected.

一种常见的技术是使用带盐的单向哈希算法来转换密码(参见 Wikipedia Definition of Salt 了解更多信息),然后当用户尝试登录时,执行相同的加密并比较哈希值.

A common technique is to transform the password using a one-way hash algorithm with a salt (see Wikipedia Definition of Salt for more info), and then when users attempt to login, to perform the same encryption and compare the hashes.

为了让事情变得更复杂,请尝试更改每个哈希的盐.

To make things even more complex, try changing the salt on every hash.

这是我使用的分步方法:

Here's a step-by-step method that I use:

  1. 用户创建密码(通过注册表)
  2. 一个函数创建一个随机盐,然后加密密码,在本例中,使用 SHA256 算法并使用随机创建的盐.

  1. User creates password (via a registration form)
  2. A function creates a random salt and then encrypts the password, in this case, using SHA256 algorithm and using a randomly created salt.

$password_salt = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM));

$password_hash = hash('sha256', $salt . $password);

将 $password_hash 和 $password_salt 保存到用户表中.这些将在以后尝试登录时用于对用户进行身份验证.

Save the $password_hash and the $password_salt to the users table. These will be used later to authenticate the user when they attempt to login in the future.

当用户登录时,检查用户名/电子邮件/登录名,如果找到,从用户表中获取哈希和盐,并将数据库中的密码哈希与执行相同功能返回的哈希进行比较他们输入的密码.

When the user logs in, check the username/email/login and if found, grab the hash and salt from the users table and compare the password hash from the db to the hash returned from performing the same function on what they entered as their password.

$salt = $user_record['password_salt'];

$entered_hash = hash('sha256', $salt . $entered_pa​​ssword);

在上述情况下,如果 $entered_pa​​ssword_hash == $user_record['password_hash']($user_record,来自您的数据库),则密码被验证.

In the case above, if $entered_password_hash == $user_record['password_hash'] ($user_record, being what comes from your db) then the password is validated.

注意 为了让事情变得更复杂,我实际上将密码哈希值和盐值存储在数据库的同一字段中.您可以将它们以一种或另一种方式连接在一起,因此如果您的数据库遭到破坏,密码字段对于检索用户密码实际上毫无用处.

Note To make things more complex, I actually store the password hash and the salt in the same field in the db. You can concat them together, one way or the other so if your database is compromised, the password field is effectively useless for retrieving user passwords.

现在,当您想要解决忘记密码的问题时,您可以创建一个随机密码,但它仍然会通过电子邮件发送给用户,这不是一个好主意,即使是临时密码也是如此.我建议通过电子邮件向用户发送一个点击链接,引导他们进入密码重置页面.以下是该过程的几个步骤:

Now when you want to address forgotten passwords, you can create a random password but that's still going to be emailed to the user, which isn't a good idea, even for a temporary password. I would suggest emailing the user a link to click, leading them to a password reset page. Here are a few steps for that process:

  1. 创建一个包含两列的 email_authentication 表 - userid 和 key.这将包含将用户 ID 与随机生成的密钥相关联的信息.
  2. 创建一个需要 URL 参数(例如 $k)的页面(例如:reset.php),然后在 email_authentication 表中查找该参数.如果在表中找到匹配的记录,则删除该记录,并重定向到一个页面,该页面将允许在同一记录中使用用户 ID 的密码.
  3. 用户忘记密码,点击忘记密码链接并输入正确的电子邮件地址.
  4. 在包含用户 ID 的 email_authentication 表中创建记录,并为密钥生成一个随机字符串(32 个左右的字符)(例如:'r4nd0mstr1ng')
  5. 使用 urlstring 中生成的密钥通过电子邮件向用户发送您在第 2 步中创建的页面的链接.(例如:http://foo.com/reset.php?k=r4nd0mstr1ng
  6. 用户单击电子邮件中的链接,reset.php 中的脚本在 email_authentication 表中查找r4nd0mstr1ng",发现它与用户 ID 相关联,然后他们被重定向到允许他们重置密码的表单.
  7. 重置密码时,请勿以明文形式保存!!

有关更多信息(以及对密码散列技术的更好解释,请查看 HeyBigName 的这篇博文.它基于 CodeIgniter,但包含的功能是通用的.

For more info (and probably a better explanation of the password hashing technique, have a look at This post by HeyBigName. It's based on CodeIgniter, but the functions contained are universally applicable.

相关文章