使用忘记密码邮件功能,在重置页面上不断出现错误

时间:2016-04-06 11:52:10

标签: php mysql sql mysqli

我最近调整了http://megarush.net/forgot-password-php/中的一些代码来帮助我创建忘记密码功能。我已将其更改为mysqli并在更新密码时添加了一些bcrypt功能。简而言之,用户输入他们的电子邮件地址,发送链接,此链接允许他们更新密码,但也会再次进行哈希处理。 我的问题是...... 我可以收到要发送给用户的电子邮件,但是当点击该链接时,即使在尝试新的电子邮件地址时,也会一直说“无效的链接或密码已经更改”。我出错的任何想法?感谢帮助人员!

我有一个包含emailtokenused的令牌表。

forgot.php

<?php require 'header.php'; 

if (!isset($_GET['email'])) {
  echo '<form action="forgot.php">
        Enter Your Email Id:
        <input type="text" name="email" />
        <input type="submit" value="Reset My Password" />
        </form>';
  exit();
}

$email = $_GET['email'];
$sql = "SELECT email FROM user WHERE email='$email'";
$query = $mysqli_conn->query($sql);
if ($query->num_rows == 0) {
  echo "Email id is not registered";
  die();
}

$token = getRandomString(10);
$sql = "INSERT INTO `tokens` (`token`, `email`) VALUES ('{$token}','{$email}')";
$query = $mysqli_conn->query($sql);

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;
}

function mailresetlink($to, $token) {
  $subject = "Forgot Password";
  $uri = 'http://' . $_SERVER['HTTP_HOST'];
  $message = '
    <html>
    <head>
    <title>Forgot Password</title>
    </head>
    <body>
    <p>Click on the given link to reset your password <a     
    href="' . $uri . '/project/reset.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: Admin<webmaster@example.com>' . "\r\n";
  $headers.= 'Cc: Admin@example.com' . "\r\n";
  if (mail($to, $subject, $message, $headers)) {
    echo "We have sent the password reset link to your  email id <b>" . $to . "      
    </b>";
  }
}

if (isset($_GET['email'])) mailresetlink($email, $token);
?>

reset.php

<?php require 'header.php';

$token = $_GET['token'];

if (!isset($_POST['password'])) {
  $sql = "SELECT email FROM tokens WHERE token='" . $token . "' and used=0";
  $query = $mysqli_conn->query($sql);
  while ($row = mysqli_fetch_array($query)) {
    $email = $row['email'];
  }

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

$password = $_POST['password'];
$email = $_SESSION['email'];

if (!isset($password)) {
  echo '<form method="post">
        enter your new password:<input type="password" name="password" />
        <input type="submit" value="Change Password">
        </form>';
}

if (isset($_POST['password']) && isset($_SESSION['email'])) {
  $password = password_hash($password, PASSWORD_DEFAULT);
  $sql = "UPDATE user SET password= '$password' where email='$email'";
  $query = mysqli_query($sql);
  if ($query) mysqli_query("UPDATE tokens SET used=1 WHERE token='$token'");
  echo "Your password is changed successfully";
  if (!$query) echo "An error occurred";
}

?>  

更新:现在修复了无效错误并显示了表单,但现在只显示“发生了错误”。添加sql错误以获取任何错误,它似乎没有问题,直到它更新密码,因为我已经回显变量和

   if (isset($_POST['password']) && isset($_SESSION['email'])) {}

重新开始工作

1 个答案:

答案 0 :(得分:2)

您的查询未触发的原因是您没有将数据库连接传递给所有mysqli_query(),而是在此代码块中:

if (isset($_POST['password']) && isset($_SESSION['email'])) {
  $password = password_hash($password, PASSWORD_DEFAULT);
  $sql = "UPDATE user SET password= '$password' where email='$email'";
  $query = mysqli_query($sql);
  if ($query) mysqli_query("UPDATE tokens SET used=1 WHERE token='$token'");
  echo "Your password is changed successfully";
  if (!$query) echo "An error occurred";
}

正如您对$query = $mysqli_conn->query($sql);所做的那样。

请记住检查错误。

if (!$query) echo "An error occurred";对您没有帮助。

在打开PHP标记后立即将错误报告添加到文件的顶部 例如
<?php error_reporting(E_ALL); ini_set('display_errors', 1);然后代码的其余部分,看它是否产生任何结果,  以及or die(mysqli_error($mysqli_conn))mysqli_query()

您目前的代码向SQL injection开放。使用prepared statementsPDOprepared statements

<强>脚注:

你应该使用条件empty()而不是if ($email != ''),它会更好。

另一件事:当使用UPDATE时,最好使用mysqli_affected_rows()来表示真相,因为你可能会得到误报。

以下是使用mysqli_affected_rows()的示例,我将isset()更改为!empty()以获取密码POST数组:

if (!empty($_POST['password']) && isset($_SESSION['email'])) {

  $password = password_hash($password, PASSWORD_DEFAULT);
  $sql = "UPDATE user SET password= '$password' where email='$email'";
  $query = mysqli_query($mysqli_conn, $sql) or die(mysqli_error($mysqli_conn));

  if (mysqli_affected_rows($mysqli_conn)){
    mysqli_query($mysqli_conn, "UPDATE tokens SET used=1 WHERE token='$token'");

      echo "Your password is changed successfully";
  }
  else {
    echo "An error occured: " . mysqli_error($mysqli_conn);
    }


}

修改

更改整个块:

$token = $_GET['token'];

if (!isset($_POST['password'])) {
  $sql = "SELECT email FROM tokens WHERE token='" . $token . "' and used=0";
  $query = $mysqli_conn->query($sql);
  while ($row = mysqli_fetch_array($query)) {
    $email = $row['email'];
  }

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

在摆脱这个代码块时(暂时):

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

上面的第一个代码块将替换为并检查该行是否与mysqli_num_rows()一起存在:

if (isset($_GET['token'])) {

$token = $_GET['token'];

$sql = "SELECT email FROM tokens WHERE token='" . $token . "' and used=0";
$query = $mysqli_conn->query($sql)  or die(mysqli_error($mysqli_conn));

    if(mysqli_num_rows($query) > 0){

        while ($row = mysqli_fetch_array($query)) {

            $email = $row['email'];
            $_SESSION['email'] = $email;

        }

    }

}