password_hash加密后password_verify验证失败,求问题排查
password_verify()验证密码失败问题排查
注册时设置密码为“1”,使用password_verify()验证数据库中存储的哈希密码时无法通过,但使用md5()或sha1()哈希时验证正常。已知password_hash是更安全的密码哈希实现,需找出问题所在。
相关代码
handleForms.php
if (isset($_POST['registerUserBtn'])) { $username = sanitizeInput($_POST['username']); $first_name = sanitizeInput($_POST['first_name']); $last_name = sanitizeInput($_POST['last_name']); $password = $_POST['password']; $confirm_password = $_POST['confirm_password']; if (!empty($username) && !empty($first_name) && !empty($last_name) && !empty($password) && !empty($confirm_password)) { if ($password == $confirm_password) { $insertQuery = insertNewUser($pdo, $username, $first_name, $last_name, password_hash($_POST['password'], PASSWORD_DEFAULT)); if ($insertQuery) { header("Location: ../login.php"); } else { header("Location: ../register.php"); } } else { $_SESSION['message'] = "请确保两次输入的密码一致"; header("Location: ../register.php"); } } else { $_SESSION['message'] = "请确保所有输入字段不为空!"; header("Location: ../register.php"); } } if (isset($_POST['loginUserBtn'])) { $username = sanitizeInput($_POST['username']); $password = $_POST['password']; if (!empty($username) && !empty($password)) { $loginQuery = loginUser($pdo, $username, $password); $userIDFromDB = $loginQuery['user_id']; $usernameFromDB = $loginQuery['username']; $passwordFromDB = $loginQuery['password']; echo "你输入的密码: " . $password . "<br>"; echo "数据库存储的哈希: " . $passwordFromDB . "<br>"; if (password_verify($password, $passwordFromDB)) { echo "验证通过"; } else { echo "验证失败"; } } else { $_SESSION['message'] = "请确保登录输入字段不为空!"; header("Location: ../login.php"); } }
models.php
function insertNewUser($pdo, $username, $first_name, $last_name, $password) { $checkUserSql = "SELECT * FROM user_accounts WHERE username = ?"; $checkUserSqlStmt = $pdo->prepare($checkUserSql); $checkUserSqlStmt->execute([$username]); if ($checkUserSqlStmt->rowCount() == 0) { $sql = "INSERT INTO user_accounts (username, first_name, last_name, password) VALUES(?,?,?,?)"; $stmt = $pdo->prepare($sql); $executeQuery = $stmt->execute([$username, $first_name, $last_name, $password]); if ($executeQuery) { $_SESSION['message'] = "用户注册成功"; return true; } else { $_SESSION['message'] = "数据库查询出错"; } } else { $_SESSION['message'] = "该用户名已存在"; } } function loginUser($pdo, $username, $password) { $sql = "SELECT * FROM user_accounts WHERE username=?"; $stmt = $pdo->prepare($sql); $stmt->execute([$username]); if ($stmt->rowCount() == 1) { $userInfoRow = $stmt->fetch(); return $userInfoRow; } }
问题原因及解决办法
最可能的问题是数据库中password字段的长度不足:
PASSWORD_DEFAULT(默认使用bcrypt算法)生成的哈希字符串长度约为60个字符;- 若之前使用
md5()/sha1(),对应的字段长度可能设置为VARCHAR(32)或VARCHAR(40),会导致存储哈希时被截断,从而使password_verify()验证失败。
解决步骤:
- 检查数据库
user_accounts表的password字段类型,修改为VARCHAR(255)(留足余量适配未来哈希算法的变化); - 修改字段长度后,重新注册用户(确保完整的哈希值被存储);
- 使用新注册的账号登录测试,验证
password_verify()是否正常工作。
临时调试方法:在登录逻辑中添加echo strlen($passwordFromDB);,如果输出长度小于60,即可确认是字段截断导致的问题。
内容的提问来源于stack exchange,提问作者mynameiswadey
相关产品推荐
相关产品推荐

