PHP PDO MySQL登录查询用户名正常邮箱验证失效问题求助
问题根因
- 核心错误:密码匹配逻辑完全错误
你已通过password_verify()完成明文密码和数据库存储哈希值的校验,但后续二次查询时,直接将用户输入的明文$password作为条件,和数据库中存储的哈希加密密码做等值匹配,自然无法匹配成功。
使用用户名能验证通过的原因是SQL逻辑运算符优先级:AND优先级高于OR,你没加括号的原SQL等价于username = ? OR (email = ? AND password = ?),当输入用户名时,username = ?条件成立就会直接返回结果,跳过后面的密码校验逻辑;输入邮箱时username = ?不成立,就需要同时满足邮箱匹配+明文密码匹配哈希值,必然失败。 - 你添加括号后的SQL实际未生效:从你导出的实际执行SQL来看,运行的还是没有加括号的版本,说明修改没有正确同步到执行逻辑中。
- 二次查询完全冗余:第一次查询已经获取到了对应用户的全部数据,完全不需要重复查询数据库。
修复方案
直接修改user.class.php中的loginUser方法,删除冗余的二次查询逻辑,复用第一次查询的结果即可:
protected function loginUser($userID, $password){ // 第一次查询直接查全字段,不需要只查密码 $sql = "SELECT * FROM db_cms_users WHERE username = ? OR email = ?"; $stmt = $this->connect()->prepare($sql); if(!$stmt->execute([$userID, $userID])){ $stmt = null; header("location: index.php?error=failstmt"); exit(); } if($stmt->rowCount() == 0){ $stmt = null; header("location: login.php?error=loginerror"); exit(); } // 用fetch取单行数据即可,不需要fetchAll $userInfo = $stmt->fetch(PDO::FETCH_ASSOC); $checkPwd = password_verify($password, $userInfo['password']); if($checkPwd == false){ $stmt = null; header("location: index.php?error=wrongpwd"); exit(); }elseif($checkPwd == true){ // 直接用第一次查询的结果创建session,删除所有冗余的二次查询逻辑 session_start(); $_SESSION['username'] = $userInfo['username']; $_SESSION['uid'] = $userInfo['id']; return true; } }
额外优化建议
- 用户名、邮箱字段建议改为
varchar类型,不要用text,可以加索引大幅提升查询效率 session_start()建议放在逻辑入口统一调用,不要放在方法内重复执行
内容的提问来源于stack exchange,提问作者DebuggingBytes
相关产品推荐
相关产品推荐

