2024-03-10 01:34:20
在 PHP PDO 中解决 OR 和 AND 混合使用导致的 SQL 查询问题,需通过调整运算符优先级或优化查询逻辑实现,同时需结合安全实践保障用户身份验证流程的安全性。
一、问题分析:运算符优先级导致的逻辑错误原始 SQL 查询语句:
SELECT * FROM db_cms_users WHERE username = ? OR email = ? AND password = ?问题核心:
方法 1:使用括号调整优先级通过括号强制先计算 OR 部分,确保逻辑正确:
SELECT * FROM db_cms_users WHERE (username = ? OR email = ?) AND password = ?效果:
方法 2:优化查询逻辑(推荐)分两步验证:
优化后的代码示例:
protected function loginUser($userID, $password) { // 查询用户名或邮箱对应的用户信息(仅必要字段) $sql = "SELECT username, id, password FROM db_cms_users WHERE username = ? OR email = ?"; $stmt = $this->connect()->prepare($sql); if (!$stmt->execute([$userID, $userID])) { header("location: index.php?error=failstmt"); exit(); } if ($stmt->rowCount() == 0) { header("location: login.php?error=loginerror"); exit(); } $user = $stmt->fetchAll(); // 验证密码哈希 $checkPwd = password_verify($password, $user[0]['password']); if (!$checkPwd) { header("location: index.php?error=wrongpwd"); exit(); } else { session_start(); $_SESSION['username'] = $user[0]['username']; $_SESSION['uid'] = $user[0]['id']; return true; }}优化点:
避免信息泄露
登录失败时统一返回“无效凭据”,不提示具体错误类型(如“用户名不存在”或“密码错误”),防止攻击者枚举账户。
密码哈希存储
使用 password_hash() 生成密码哈希,存储哈希值而非明文密码。
示例:$hashedPassword = password_hash($plainPassword, PASSWORD_DEFAULT);
防止 SQL 注入
始终使用 PDO 预处理语句(prepare() + execute()),避免拼接 SQL 字符串。
会话安全配置
启用 HTTPS 后设置 session.cookie_secure = 1,确保 Cookie 仅通过加密连接传输。
设置 session.cookie_httponly = 1,防止 JavaScript 访问 Cookie,降低 XSS 攻击风险。
示例(PHP 配置):session.cookie_secure = 1session.cookie_httponly = 1