PDO execute返回True但教师表为空,随机用户名登录为何判定成功?
问题根源:误解了PDO
execute()的返回值 嘿,我一眼就看出问题所在了——你完全误解了PDO中execute()方法的返回值含义!
$query->execute()返回的true,只代表这条SQL语句成功执行了,和有没有查询到匹配的数据根本不是一回事。比如你用随机用户名查教师表时,虽然没有找到任何符合条件的行,但这条SELECT语句本身语法合法、没有执行错误,所以execute()还是会返回true。你的代码把这个返回值当成了“是否找到用户”的判断依据,自然会出现不管输入什么用户名都能“登录”的诡异情况。
另外,你的代码还有两个致命的安全漏洞:
- 完全没做密码验证!只要SQL执行成功就直接登录,等于把系统大门完全敞开了
- 两次查询的写法冗余,很容易出现逻辑疏漏
修正后的代码示例
下面是修复了所有问题的代码,兼顾了正确性和安全性:
// 先查询教师表,同时获取用户密码 $query = $pdo->prepare("SELECT `username`, `password` FROM `teachers` WHERE `username` = :username"); $query->execute(array(":username" => $username)); $teacher = $query->fetch(PDO::FETCH_ASSOC); if ($teacher) { // 验证密码(注意:数据库里必须存哈希后的密码,不能存明文!) if (password_verify($password, $teacher['password'])) { $_SESSION["current_user"] = [ "username" => $username, "role" => "teacher" ]; echo("<script>location.href = 'home.php';</script>"); exit; } } // 教师表没找到,再查学生表 $query = $pdo->prepare("SELECT `username`, `password` FROM `students` WHERE `username` = :username"); $query->execute(array(":username" => $username)); $student = $query->fetch(PDO::FETCH_ASSOC); if ($student) { if (password_verify($password, $student['password'])) { $_SESSION["current_user"] = [ "username" => $username, "role" => "student" ]; echo("<script>location.href = 'home.php';</script>"); exit; } } // 用户名不存在或密码错误 echo("<script>alert('用户名或密码错误'); location.href = 'index.php';</script>");
额外优化建议
- 合并用户表:更合理的设计是用一个
users表,新增role字段标记用户身份(teacher/student),这样只需要一次查询就能完成验证,减少代码冗余和数据库请求 - 强制密码哈希:必须用
password_hash()生成哈希值存进数据库,绝对不能存明文密码——这是Web系统安全的基本底线 - 统一错误提示:为了防止恶意枚举用户名,建议统一提示“用户名或密码错误”,不要区分两种错误场景
内容的提问来源于stack exchange,提问作者user9782033
相关产品推荐
相关产品推荐

