【问题标题】:forget password page, creating a generated password to email to the user.忘记密码页面,创建生成的密码以通过电子邮件发送给用户。
【发布时间】:2012-01-07 04:37:18
【问题描述】:

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

<!--
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 \r\n";
        $messages.="Your password is $your_password \r\n";
        $messages.="Please change this password for security reasons. Thank you. \r\n";

        // 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>

【问题讨论】:

  • 由于htmlentities或其他原因,电子邮件可能显示为不可见,请检查@之类的内容是否已转换为它们的html实体以防万一?

标签: php sql phpmyadmin


【解决方案1】:

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

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

要让事情变得更复杂,请尝试更改每个哈希的盐值。

这是我使用的分步方法:

  1. 用户创建密码(通过注册表单)
  2. 一个函数创建一个随机盐,然后加密密码,在这种情况下,使用 SHA256 算法并使用一个随机创建的盐。

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

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

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

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

    $salt = $user_record['password_salt'];

    $entered_hash = hash('sha256', $salt . $entered_password);

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

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

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

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

如需更多信息(可能是密码散列技术的更好解释,请查看This post by HeyBigName。它基于 CodeIgniter,但包含的功能普遍适用。

【讨论】:

    【解决方案2】:

    我建议: 1 - 用户点击忘记密码,并输入用户名和/或电子邮件。您检查数据库中是否存在用户名和/或电子邮件,如果为真,则生成一个随机代码并将其存储在您的数据库中。 2 - 向用户发送一封电子邮件,其中包含如下链接:www.yourwebsite.com/forgot?recovery=CODEGENERATED 3 - 用户单击链接,然后检查代码是否存在于您的数据库中,如果为真,则显示填写新密码的表格。用户填写,您的保存吃了数据库。 4 - 完成。

    一个问题:如果用户没有密码,为什么要求用户填写密码字段?

    $password =$_P0ST['password']; 
    

    还有,为什么不使用:

    $your_password = createRandomPassword();
    

    改为:

    $your_password=$rows['password'];
    

    而且,为什么这两行:

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

    第一次生成新密码,但是你设置的值贴在同一个变量上..

    【讨论】:

    • 感谢您指出这些错误。我会尽量按照你的方式来解决。
    • 当然你会以正确的方式,但记住别人说的所有内容,例如加密密码等。..
    【解决方案3】:

    需要注意的几个问题:

    1. 在您使用 createRandomPassword() 创建 $password 变量后,您将使用 $_POST['password'] 中的值覆盖它。

    2. 您需要在 $tbl_name 的赋值两边加上引号,即:

      $tbl_name = "Account_Holders";

      这可能是您在数据库中找不到用户电子邮件的原因。

    3. 如果您要通过电子邮件将新密码发送给用户,那么您需要在数据库中更新该密码,以便当他们使用新密码登录时,它将与数据库中的密码匹配。为此,您需要使用更新语句:

      UPDATE Account_Holders SET Password = '$password' WHERE Email = '$email';

    注意:将密码存储在未加密的数据库中通常不是一个好主意。通常所做的是首先加密密码,然后以这种方式存储在数据库中。当您去验证用户的登录凭据时,使用相同的加密算法对他们发送的密码进行加密,并与数据库中的密码进行比较。

    【讨论】:

      【解决方案4】:

      到目前为止,问题是用户的电子邮件不在数据库中,而实际上它在数据库中。

      据我所知,您的查询没有任何问题,但不将您的 $tbl_name 值放在引号中可能没有帮助。另外,您是否仔细检查了电子邮件输入上的名称属性肯定也是电子邮件,并且它们都正确匹配?

      另外,我应该更新数据库以存储随机密码还是按照我的方式工作?

      我通常这样做的方式是这样的,当他们请求新密码时,生成一个令牌以及他们的用户 ID 和电子邮件。向他们发送带有链接的电子邮件,如下所示:

      example.com/reset/?id=THERE_ID&amp;token=RANDOM_TOKEN

      然后在该页面上检查它们是否匹配,如果匹配,让他们输入新密码。

      我听说通过电子邮件将原始密码发送给用户不是一个好主意

      老实说,你甚至不应该在你的数据库中存储原始密码,你想查找像 hash_hmac 和 password salts 这样的东西 - 在这些类型的页面上应该有其他链接供你使用使用教程/示例解决所有问题。

      最后一点,始终验证您的用户输入 (regex for example),因为您使用的是 mysql_query,所以您总是希望使用 mysql_real_escape_string 转义输入 - 查询的首选方法是使用 @ 987654325@,这些对于阻止诸如little bobby tables 进入您的站点之类的事故非常有用。

      【讨论】:

        猜你喜欢
        • 2016-08-31
        • 2011-02-19
        • 1970-01-01
        • 2013-06-13
        • 2013-06-24
        • 2015-06-22
        • 2013-03-04
        • 1970-01-01
        • 2012-02-29
        相关资源
        最近更新 更多