You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP PDO MySQL登录查询用户名正常邮箱验证失效问题求助

问题根因

  1. 核心错误:密码匹配逻辑完全错误
    你已通过password_verify()完成明文密码和数据库存储哈希值的校验,但后续二次查询时,直接将用户输入的明文$password作为条件,和数据库中存储的哈希加密密码做等值匹配,自然无法匹配成功。
    使用用户名能验证通过的原因是SQL逻辑运算符优先级:AND优先级高于OR,你没加括号的原SQL等价于username = ? OR (email = ? AND password = ?),当输入用户名时,username = ?条件成立就会直接返回结果,跳过后面的密码校验逻辑;输入邮箱时username = ?不成立,就需要同时满足邮箱匹配+明文密码匹配哈希值,必然失败。
  2. 你添加括号后的SQL实际未生效:从你导出的实际执行SQL来看,运行的还是没有加括号的版本,说明修改没有正确同步到执行逻辑中。
  3. 二次查询完全冗余:第一次查询已经获取到了对应用户的全部数据,完全不需要重复查询数据库。

修复方案

直接修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 03:06:04