我最近调整了http://megarush.net/forgot-password-php/中的一些代码来帮助我创建忘记密码功能。我已将其更改为mysqli并在更新密码时添加了一些bcrypt功能。简而言之,用户输入他们的电子邮件地址,发送链接,此链接允许他们更新密码,但也会再次进行哈希处理。 我的问题是...... 我可以收到要发送给用户的电子邮件,但是当点击该链接时,即使在尝试新的电子邮件地址时,也会一直说“无效的链接或密码已经更改”。我出错的任何想法?感谢帮助人员!
我有一个包含email
,token
和used
的令牌表。
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'])) {}
重新开始工作
答案 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 statements或PDO与prepared 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;
}
}
}