密码匹配时密码处理程序仍返回错误的问题排查
密码验证逻辑问题排查
问题代码片段
密码匹配验证函数
protected function passwordMatch($username, $password) { $sql = 'SELECT `username`, `password` FROM `profile` WHERE `username` = ?'; $stmt = $this->connect()->prepare($sql); $stmt->execute([$username]); $result = $stmt->fetch(); if (password_verify($result['password'], $password)) { return true; } return false; }
登录验证逻辑
if ($this->passwordMatch($this->username, $this->password) !== true) { $_SESSION['error'] = 'Password not matching'; header('Location: ../login.php'); exit(); }
问题描述
预期效果:用户名与密码匹配时,用户可成功登录。
实际问题:原逻辑下无法正常登录;将判断条件从!==改为===后,密码不匹配也能登录。
问题分析
判断条件修改后的逻辑错误
原判断!== true的逻辑是:只要验证函数返回的不是true,就跳回登录页。改成=== true后,逻辑变成只有验证成功时才跳回登录页,完全违背登录验证的初衷——验证失败时本该拦截,结果反而直接跳过拦截,导致密码不匹配也能登录。密码匹配函数的核心错误
password_verify的参数顺序写反了!该函数的正确用法是password_verify(用户输入的明文密码, 数据库存储的哈希值),原代码把数据库的哈希值放在第一个参数,用户输入的密码放在第二个,导致无论密码是否正确,验证结果永远是false。这就是原逻辑下无法正常登录的根本原因。
修复方案
1. 修正password_verify参数顺序
这是解决问题的关键,调整参数顺序确保验证逻辑正确:
protected function passwordMatch($username, $password) { $sql = 'SELECT `username`, `password` FROM `profile` WHERE `username` = ?'; $stmt = $this->connect()->prepare($sql); $stmt->execute([$username]); $result = $stmt->fetch(); // 先判断用户是否存在,再执行正确的密码验证 if ($result && password_verify($password, $result['password'])) { return true; } return false; }
2. 保留正确的登录拦截逻辑
继续使用原判断条件,确保验证失败时拦截请求:
if ($this->passwordMatch($this->username, $this->password) !== true) { $_SESSION['error'] = '用户名或密码错误'; header('Location: ../login.php'); exit(); }
(建议将错误提示改为“用户名或密码错误”,避免泄露用户是否存在的敏感信息)
内容的提问来源于stack exchange,提问作者Sammo
相关产品推荐
相关产品推荐

