如何修复这个PHP忘记密码脚本?

如何修复这个PHP忘记密码脚本?,php,passwords,reset,Php,Passwords,Reset,因此,基本上,我正在尝试制作一个简单、安全、被遗忘的密码脚本 有两个脚本,一个允许用户输入他们的电子邮件地址。这将向他们发送一封电子邮件,其中包含一个链接,他们必须访问该链接才能保存新密码 第二个脚本是链接指向的地方。此脚本保存新密码 为了安全起见,我在数据库中创建了一个名为“token”的新表。它有三个领域;令牌,电子邮件,已使用。Token是由10个字母和数字随机生成的字符串,email只是用户的电子邮件地址,used是1或0的整数,表示是否使用了Token 一旦您阅读了这两个脚本,您将能够

因此,基本上,我正在尝试制作一个简单、安全、被遗忘的密码脚本

有两个脚本,一个允许用户输入他们的电子邮件地址。这将向他们发送一封电子邮件,其中包含一个链接,他们必须访问该链接才能保存新密码

第二个脚本是链接指向的地方。此脚本保存新密码

为了安全起见,我在数据库中创建了一个名为“token”的新表。它有三个领域;令牌,电子邮件,已使用。Token是由10个字母和数字随机生成的字符串,email只是用户的电子邮件地址,used是1或0的整数,表示是否使用了Token

一旦您阅读了这两个脚本,您将能够对我的结构有更多的了解。它们不会太长,一点也不复杂

出了什么问题

好的,所以只有一件小事情出错了,这就是reset-password.php脚本。这就是用户收到电子邮件后的目的地。基本上,我键入一个新密码,然后单击“重置密码”,但什么也没发生。没有显示任何错误或确认,数据库中也没有任何更改。我似乎无法调试这个,并且已经搜索和尝试了几个小时了。所有的帮助和建议将不胜感激

请记住,我还是PHP和MySQL的新手。现在已经使用PHP大约8周了,MySQL只使用了2周

忘记密码。php

<?php
//Forgotten password script

    //Variable to save errors
    $errors = array();

    $email = $_POST['email'];

    include 'config.php';
    mysql_connect("$db_host", "$db_username", "$db_password")or die("cannot connect"); 
    mysql_select_db("$db_name")or die("cannot select DB");

    $query = "SELECT email FROM users WHERE email='" . $email . "'";
    $result = mysql_query($query);
    $num = mysql_num_rows($result);
    if($num==0)
    {
        echo ("<div style='color:red;'>Email address is not registered</div>");
        die();
    }

    $token = getRandomString(10);
    $query = "INSERT INTO tokens (token,email) VALUES ('".$token."','".$email."')";
    mysql_query($query);

    //function to renerate the token
    function getRandomString($length) 
    {
        $validCharacters = "ABCDEFGHIJKLMNPQRSTUXYVWZ123456789";
        $validCharNumber = strlen($validCharacters);
        $result = "";

        for ($i = 0; $i < $length; $i++) 
        {
            $index = mt_rand(0, $validCharNumber - 1);
            $result .= $validCharacters[$index];
        }
        return $result;
    }

    //Send the reset link to the user
    function mailresetlink($to,$token)
    {
        $subject = "Password Reset";
        $message = '
        <html>
        <head>
        <title>Password Reset</title>
        </head>
        <body>
        <p>Click on the given link to reset your password <a href="http://domain.com/reset-password.php?token='.$token.'">Reset Password</a></p>

        </body>
        </html>
        ';
        $headers = "MIME-Version: 1.0" . "\r\n";
        $headers .= "Content-type:text/html;charset=iso-8859-1" . "\r\n";
        $headers .= 'From: Password Reset <noreply@domain.com>' . "\r\n";

        if(mail($to,$subject,$message,$headers))
        {
            echo "We have sent the password reset link to your email at <strong>".$to."</strong>"; 
        }
    }

    //If email is posted, send the email
    if(isset($_POST['email']))
    {
        mailresetlink($email,$token);
    }


?>




<table align="center" style="padding-bottom:40px;">
    <form action="<?php $_SERVER['PHP_SELF']; ?>" method="post">
    <tr>
    <td>Email Address: </td>
    <td><input type="text" name="email" /></td>
    </tr>
    <tr>
    <td colspan="2" align="center"><input type="submit" value="Reset My Password" /></td></tr>
    <input type="hidden" name="register" value="TRUE" />
</form>
</table>
<?php
//Reset password script

    $token = $_GET['token'];
    $email;

    include 'config.php';
    mysql_connect("$db_host", "$db_username", "$db_password") or die("cannot connect"); 
    mysql_select_db("$db_name")or die("cannot select DB");

    if(!isset($_POST['newpassword']))
    {
        $query = "SELECT email FROM tokens WHERE token='" . $token . "' AND used = 0";
        $result = mysql_query($query);
        while($row = mysql_fetch_array($result))
        {
            $email = $row['email'];
        }


        if ($email != '')
        {
            $_SESSION['email'] = $email;
        }
        else 
        {
            echo "Invalid link or Password already changed";
        }
    }


    $pass = $_POST['newpassword'];
    $email = $_SESSION['email'];

    //Save new password
    if(isset($_POST['newpassword']) && isset($_SESSION['email']))
    {
        $query = "UPDATE users SET password = SHA('$password') WHERE email='" . $email . "'";
        $result = mysql_query($query);
        if($result)
        {
            mysql_query("UPDATE tokens SET used=1 WHERE token='" . $token . "'");
        }
        echo "Your password has been changed successfully";
        if(!$result)
        {
            echo "An error occurred. Please try the again or contact us at admin@domain.com";
        }
    }

?>



<table align="center" style="padding-bottom:40px;">
    <form action="<?php $_SERVER['PHP_SELF']; ?>" method="post">
    <tr>
    <td>New Password:</td>
    <td><input type="password" name="newpassword" id="password"/></td>
    </tr>
    <tr>
    <td colspan="2" align="center"><input type="submit" value="Change Password"></td></tr>
    <input type="hidden" name="reset" value="TRUE" />
</form>
</table>

在输入新密码参数后,我看不到您在重置页面上将令牌参数传递给服务器的任何地方。我想你应该有另一个隐藏的
控件
$\u服务器['PHP\u SELF']
不返回查询字符串参数。这可能是您当前问题的原因

具体来说,

<table align="center" style="padding-bottom:40px;">
    <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
    <tr>
    <td>New Password:</td>
    <td><input type="password" name="newpassword" id="password"/></td>
    </tr>
    <tr>
    <td colspan="2" align="center"><input type="submit" value="Change Password"></td></tr>
    <input type="hidden" name="reset" value="TRUE" />
</form>
</table>


在输入新密码参数后,我看不到您在重置页面上将令牌参数传递给服务器的任何地方。我想你应该有另一个隐藏的
控件
$\u服务器['PHP\u SELF']
不返回查询字符串参数。这可能是您当前问题的原因

具体来说,

<table align="center" style="padding-bottom:40px;">
    <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
    <tr>
    <td>New Password:</td>
    <td><input type="password" name="newpassword" id="password"/></td>
    </tr>
    <tr>
    <td colspan="2" align="center"><input type="submit" value="Change Password"></td></tr>
    <input type="hidden" name="reset" value="TRUE" />
</form>
</table>


嘿,伙计们。不要担心安全性有多强。这是我的一位教授分配给我的一项简单的uni任务,他只需要为他的一个简单网站提供一个简单的工作恢复系统。这个例子已经研究了好几个小时了,我知道它是可以修复的…@Mitch-谢谢!虽然,在做了更改之后,我现在得到了“无效链接或密码已更改”的错误。不确定它为什么要输入“else”语句……您是否将
$\u GET
全局变量更新为
$\u REQUEST
?如果不是,这可能会导致
$token
变量为空,这可能会导致该错误。@Mitch-在我的第一个版本中,$token变量保存得非常好。如您所见,我的reset-password.php脚本的最开始就是保存令牌。我甚至试着回显令牌,看看它是否正确保存,结果是。但是,是的,在你让我做的更新中,我按照你说的做了正确的更改。首先,问题不在于令牌,而在于reset-password.php脚本中最后一个“if”语句。不要担心安全性有多强。这是我的一位教授分配给我的一项简单的uni任务,他只需要为他的一个简单网站提供一个简单的工作恢复系统。这个例子已经研究了好几个小时了,我知道它是可以修复的…@Mitch-谢谢!虽然,在做了更改之后,我现在得到了“无效链接或密码已更改”的错误。不确定它为什么要输入“else”语句……您是否将
$\u GET
全局变量更新为
$\u REQUEST
?如果不是,这可能会导致
$token
变量为空,这可能会导致该错误。@Mitch-在我的第一个版本中,$token变量保存得非常好。如您所见,我的reset-password.php脚本的最开始就是保存令牌。我甚至试着回显令牌,看看它是否正确保存,结果是。但是,是的,在你让我做的更新中,我按照你说的做了正确的更改。首先,问题不在于令牌,而在于reset-password.php脚本中的最后一个“if”语句。Mitch的答案应该可以解决您的问题。正如前面所说的,函数是不安全的,在早期的回答中,它试图指出一个过程是什么样子的。@martinstoeckli-正如我在Mitch的帖子上发表的新评论所示,不幸的是,他的回答没有解决我的代码问题。在第一个get请求中,你从数据库中获取电子邮件并将其存储在会话中,然后在第二个post请求中,你从会话中读取电子邮件。这不是必需的,请仅在必要时(提交表格后)阅读电子邮件。在您的示例中它不起作用的原因是,您没有在脚本开始时调用
session\u start()
,但实际上,这里不需要会话。Mitch的答案应该可以解决您的问题。正如前面所说的,函数是不安全的,在早期的回答中,它试图指出一个过程是什么样子的。@martinstoeckli-正如我在Mitch的帖子上发表的新评论所示,不幸的是,他的回答没有解决我的代码问题。在第一个get请求中,你从数据库中获取电子邮件并将其存储在会话中,然后在第二个post请求中,你从会话中读取电子邮件。这不是必需的,请仅在必要时(提交表格后)阅读电子邮件。在您的示例中它不起作用的原因是,您没有调用
session\u start()