如何正确创建PDO 修复存在SQL注入漏洞的PHP查询代码
PDO改写问题排查与正确实现
原尝试代码的错误点
你写的版本无法正常运行,核心问题如下:
- 连接实例不匹配:目标为PDO实现,但代码仍用
mysqli_connect创建mysqli连接,没有初始化PDO连接对象 - 变量名拼写错误:定义SQL语句的变量是
$query,调用prepare方法时传入的是未定义的$sql变量 - 参数绑定逻辑错误:
bind_param是mysqli扩展的方法,不属于PDO;且绑定顺序、参数类型、传值逻辑完全写反,还错误拼接了用户输入,没有实现预处理防注入的效果 - 结果集方法混用:取结果时仍调用mysqli系列函数,和PDO预处理返回的结果集不兼容
正确PDO实现代码
<?php // fetch.php // 数据库连接配置 $dbHost = 'localhost'; $dbName = 'project'; $dbUser = 'root'; $dbPwd = ''; $dbCharset = 'utf8mb4'; // 初始化PDO连接 try { $connect = new PDO( "mysql:host=$dbHost;dbname=$dbName;charset=$dbCharset", $dbUser, $dbPwd, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ] ); } catch (PDOException $e) { die("数据库连接失败:" . $e->getMessage()); } if (isset($_POST["row_id"])) { // 预处理带占位符的SQL语句 $query = "SELECT id,username,usertype,division,mobnum,userstatus,date(created_at) as created_at FROM users WHERE id = ?"; $stmt = $connect->prepare($query); // 绑定参数,id为整数类型,用PDO::PARAM_INT做类型约束 $stmt->bindParam(1, $_POST["row_id"], PDO::PARAM_INT); $stmt->execute(); // 获取单条结果并输出json $row = $stmt->fetch(); echo json_encode($row); } ?>
补充说明
- 该实现通过PDO预处理机制分离SQL逻辑和用户输入,彻底解决原代码的SQL注入漏洞
- 若数据库中
id字段为字符串类型,将参数绑定的类型改为PDO::PARAM_STR即可 - 可以简化参数绑定流程,直接在
execute方法中传入参数数组,无需单独调用bindParam,写法如下:$stmt->execute([$_POST["row_id"]]); - 初始化PDO时设置的属性默认将结果集返回为关联数组,同时开启异常报错,方便开发阶段排查问题。
内容的提问来源于stack exchange,提问作者edublog
相关产品推荐
相关产品推荐

