php - password_verify - 密码与哈希不匹配
问题描述
我有一个登录系统。您可以注册一个用户并稍后登录(在这种情况下,password_verify 完成了它的工作)。然后我有一个密码恢复系统。您会收到一封电子邮件,其中包含带有令牌等的链接。您更改密码并在数据库中更改(我可以通过更改的哈希看到它)。然后,如果您尝试使用新密码登录,它会显示密码错误,旧密码也不会。
/// new password is set
$newPwdHash = password_hash($pwd, PASSWORD_DEFAULT);
mysqli_stmt_bind_param($stmt, 'ss', $newPwdHash, $tokenEmail);
mysqli_stmt_execute($stmt);
$pwdCheck = password_verify($pwd, $row['pwdUsers']);
我不知道它是否有帮助,但是如果您在恢复密码时尝试设置的不是散列密码,而是通常的密码,它会在数据库中将其更改为空的空白 idk 为什么。
//login
if (isset($_POST['login'])) {
require 'db.inc.php';
$mailuid = $_POST['mailuid'];
$pwd = $_POST['pwd'];
if (empty($mailuid) || empty($pwd)) {
header('Location: ../index.php?error=empty');
exit();
} else {
$sql = 'SELECT * FROM users WHERE uidUsers=? OR emailUsers=?';
$stmt = mysqli_stmt_init($link);
if (!mysqli_stmt_prepare($stmt, $sql)) {
header('Location: ../index.php?error=sql');
exit();
} else {
mysqli_stmt_bind_param($stmt, 'ss', $mailuid, $mailuid);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
if ($row = mysqli_fetch_assoc($result)) {
$pwdCheck = password_verify($pwd, $row['pwdUsers']);
if (!$pwdCheck) {
header('Location: ../index.php?error=wrongpwdormail');
exit();
} elseif ($pwdCheck) {
session_start();
$_SESSION['id'] = $row['idUsers'];
$_SESSION['uid'] = $row['uidUsers'];
header('Location: ../index.php?login=success');
exit();
} else {
header('Location: ../index.php?error=wrongpwdormail');
exit();
}
} else {
header('Location: ../index.php?error=nouser');
exit();
}
}
}
} else {
header('Location: ../index.php');
exit();
}
//reset
$tokenEmail = $row['pwdResetEmail'];
$sql = 'SELECT * FROM users WHERE emailUsers=?';
if (!mysqli_stmt_prepare($stmt, $sql)) {
echo 'error2';
exit();
} else {
mysqli_stmt_bind_param($stmt, 's', $tokenEmail);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
if (!$row = mysqli_fetch_assoc($result)) {
echo 'error3';
exit();
} else {
$sql = 'UPDATE users SET pwdUsers=? WHERE emailUsers=?';
if (!mysqli_stmt_prepare($stmt, $sql)) {
echo 'error4';
exit();
} else {
$newPwdHash = password_hash($pwd, PASSWORD_DEFAULT);
mysqli_stmt_bind_param($stmt, 'ss', $newPwdHash, $tokenEmail);
mysqli_stmt_execute($stmt);
$sql = 'DELETE FROM pwdReset WHERE pwdResetEmail=?';
if (!mysqli_stmt_prepare($stmt, $sql)) {
echo 'error5';
exit();
} else {
mysqli_stmt_bind_param($stmt, 's', $tokenEmail);
mysqli_stmt_execute($stmt);
header('Location: ../signup.php?newpwd=updated');
}
}
}
}
解决方案
注意:除非您在登录(isset)部分之外的多个部分上复制变量,否则它很可能是未定义的,因此散列未定义的变量。所以密码永远不会匹配。
请注意您是如何在重置部分使用变量$pwd
的,即使您是$pwd
在“登录”部分中创建变量。如果代码的两个部分都包含在一个文件中并且顺序与您在 StackOverflow 上发布的顺序一致,我非常怀疑您是否达到了该部分。
if (isset($_POST['login'])) {
$mailuid = $_POST['mailuid'];
$pwd = $_POST['pwd'];
//NOTICE: unless you are duplicating the variables on multiple parts
//including OUTSIDE of the login (isset) part, it most likely is undefined
//thus, hashing an undefined variable. So the password will NEVER match.
} else {
//header('Location: ../index.php');
//exit(); //will halt execute, so it's interesting that you're even reaching the reset part.
//Unless the reset part and login part aren't in the same file.
}
重置部分和登录部分是否在同一个文件中?
else {
$newPwdHash = password_hash($pwd, PASSWORD_DEFAULT);
mysqli_stmt_bind_param($stmt, 'ss', $newPwdHash, $tokenEmail);
mysqli_stmt_execute($stmt);
$sql = 'DELETE FROM pwdReset WHERE pwdResetEmail=?';
if (!mysqli_stmt_prepare($stmt, $sql)) {
echo 'error5';
exit();
} else {
mysqli_stmt_bind_param($stmt, 's', $tokenEmail);
mysqli_stmt_execute($stmt);
header('Location: ../signup.php?newpwd=updated');
}
}
我建议您为重置部分创建一个专用页面,您可以在其中执行以下操作:
if (isset($_POST["recovery"])) { // or whatever kind of check you wish to do prior to firing your code.
$tokenEmail = $row['pwdResetEmail']; //no idea where you created this ->
//$row["pwdResetEmail"]; I assume it's a part you're either not showing us,
//or this isn't working either. I am guessing the first one (that you aren't
//showing us where you retrieve it), or else it would not be possible to
//change anything and the query should fail (correct me if I am wrong here guys).
$pwd = // NOTICE: assign the password. May it be a POST or a GET or whatever
$sql = 'SELECT * FROM users WHERE emailUsers=?';
if (!mysqli_stmt_prepare($stmt, $sql)) {
echo 'error2';
exit();
} else {
mysqli_stmt_bind_param($stmt, 's', $tokenEmail);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
if (!$row = mysqli_fetch_assoc($result)) {
echo 'error3';
exit();
} else {
$sql = 'UPDATE users SET pwdUsers=? WHERE emailUsers=?';
if (!mysqli_stmt_prepare($stmt, $sql)) {
echo 'error4';
exit();
} else {
$newPwdHash = password_hash($pwd, PASSWORD_DEFAULT); //NOTICE:
//NOW THE VARIABLE $PWD IS DEFINED
mysqli_stmt_bind_param($stmt, 'ss', $newPwdHash, $tokenEmail);
mysqli_stmt_execute($stmt);
$sql = 'DELETE FROM pwdReset WHERE pwdResetEmail=?';
if (!mysqli_stmt_prepare($stmt, $sql)) {
echo 'error5';
exit();
} else {
mysqli_stmt_bind_param($stmt, 's', $tokenEmail);
mysqli_stmt_execute($stmt);
header('Location: ../signup.php?newpwd=updated');
}
}
}
}
}
推荐阅读
- java - 为什么 for 循环运行 6 次迭代?
- c# - 如何在一个事务中拥有 Asp.Net Identity 和 EF Database-First 上下文?
- google-analytics - 如何设置 Google Analytics 可以读取的自定义用户代理
- python - Python reportLab 鸭嘴兽:底部图像
- javascript - 从节点到角度的数据检索时出现 Cors 错误
- ios - 如何知道我上传到 firebase 的文件是否已完成上传?
- intellij-idea - 生成自定义设置器 lombok 或 intelliJ
- python - 熊猫同时进行多个变换-分组聚合-加速
- bash - 作为服务运行时 Python 脚本未启动 Bash 脚本
- html - 调整为移动设备堆叠的列的高度 (@media)