MySQL密码哈希验证失效问题求助
首先,最可能导致你登录密码验证失败的原因是登录脚本中对密码进行了不必要的转义处理,具体分析和修复步骤如下:
核心问题:登录时密码被修改
在你的Login.PHP里,对用户输入的密码执行了mysqli_real_escape_string:
$password = $_REQUEST['password']; $password = mysqli_real_escape_string($con,$password); // 这一步是错误的
password_verify()函数需要接收用户输入的原始明文密码,与数据库中存储的哈希值进行比对。而mysqli_real_escape_string会修改密码的原始内容(比如密码中的单引号'会被转义为\'),导致转义后的密码和注册时的原始密码不一致,自然无法通过验证。
修复步骤
1. 移除登录时的密码转义
修改Login.PHP中的密码处理代码,去掉转义步骤:
// 原代码 $password = $_REQUEST['password']; $password = mysqli_real_escape_string($con,$password); // 修改后 $password = $_REQUEST['password']; // 移除mysqli_real_escape_string这一行
不用担心SQL注入问题:因为你是先通过用户名查询用户信息,再用password_verify对比密码,密码本身并没有直接代入SQL查询语句,所以不需要转义。
2. 补充用户名存在性判断
当前登录脚本中,没有先判断查询结果是否存在就直接获取$row。如果用户名不存在,$row会是null,访问$row['password']会导致$hash为空,进而触发验证失败。建议添加判断:
$query = "SELECT * FROM `users` WHERE username='$username'"; $result = mysqli_query($con,$query) or die(mysql_error()); $rows = mysqli_num_rows($result); // 先判断用户是否存在 if ($rows > 0) { $row = mysqli_fetch_array($result); $hash = $row['password']; if (password_verify($password, $hash)) { $_SESSION['username'] = $username; $position = $row['position']; if ( $position == "freelancer" ){ header("Location: ../freelancer/index.php"); } elseif ($position == "employer"){ header("Location: ../employer/index.php"); } exit(); // 跳转后要终止脚本执行 } else { echo "<div class='form'> <h3>Username/password is incorrect.</h3> ".$hash." " .$password. " <br />Click here to <a href='login.php'>Login</a> </div>"; } } else { echo "<div class='form'> <h3>Username does not exist.</h3> <br />Click here to <a href='login.php'>Login</a> </div>"; }
3. 确认数据库密码字段长度
PASSWORD_DEFAULT生成的哈希值长度为60字符,因此你的users表中password字段的类型必须是VARCHAR(255)(不要使用TEXT或长度小于60的VARCHAR,否则哈希值会被截断,导致验证失败)。可以通过查看数据库表结构确认这一点。
4. 验证注册时哈希是否正确存入
直接查看数据库中users表的password字段,正常的哈希值应该是类似$2y$10$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx格式的字符串,而不是用户输入的原始密码。如果存储的是原始密码,说明注册脚本可能存在逻辑错误(不过从你提供的注册代码片段看,这部分是正确的)。
内容的提问来源于stack exchange,提问作者user9707828

