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


Using forgot password mail function, keep getting error on reset page

我最近改编了一些来自http://megarush.net/forgot-password-php/帮助我创建忘记密码功能。我把它改成了mysqli,并在更新密码时添加了一些bcrypt功能。简而言之,用户输入他们的电子邮件地址,收到一个链接,这个链接允许他们更新密码,但也会再次被散列我的问题是…我可以将电子邮件发送给用户,但当单击链接时,即使在尝试新的电子邮件地址时,它也会一直显示"无效链接或密码已更改"。你知道我哪里错了吗?感谢大家的帮助!

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

忘记了.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'])) {}

返回工作

您的查询没有启动的原因是您没有将数据库连接传递给所有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);,然后是代码的其余部分,看看它是否产生了什么,以及CCD_ 8至CCD_。


您当前的代码对SQL注入是开放的。将准备好的语句PDO已准备好的报表一起使用。


脚注:

您应该使用条件empty()而不是if ($email != ''),这样更好。

另一件事:当使用UPDATE时,最好使用mysqli_affected_rows()来表示真实性,因为您可能会得到假阳性。

  • http://php.net/manual/en/mysqli.affected-rows.php

下面是一个使用mysqli_affected_rows()的示例,我将密码POST数组的isset()更改为!empty()

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