Z
ZHANK
编程在线教程PHP 教程预处理与防注入
数据库

预处理与防注入

prepare/execute 预处理、SQL 注入原理与防御、参数绑定

预处理与防注入

SQL 注入是 Web 安全的第一大威胁。预处理(Prepared Statement)是唯一正确的防御方式。

学完本章你将: 掌握 prepare/execute、SQL 注入原理、参数绑定。


SQL 注入演示

php
<?php
// ❌ 危险——拼接用户输入
$name = $_GET['name'];  // 用户输入:'; DROP TABLE users; --
$pdo->query("SELECT * FROM users WHERE name = '$name'");
// 实际执行:SELECT * FROM users WHERE name = ''; DROP TABLE users; --'
// 整张表被删!
php
<?php
// ✅ 安全——预处理(参数与 SQL 分离)
$stmt = $pdo->prepare("SELECT * FROM users WHERE name = :name");
$stmt->execute(["name" => $_GET['name']]);
// 无论用户输入什么,都只是"数据",绝对不会被当作 SQL 执行

占位符的两种写法

php
<?php
// 命名占位符(推荐——可读性好)
$stmt = $pdo->prepare("SELECT * FROM users WHERE name = :name AND age > :age");
$stmt->execute(["name" => "小明", "age" => 18]);

// 问号占位符(短但易出错)
$stmt = $pdo->prepare("SELECT * FROM users WHERE name = ? AND age > ?");
$stmt->execute(["小明", 18]);

IN 子句的参数绑定

php
<?php
// IN 子句需要动态构建占位符
$ids = [1, 2, 3, 5, 8];
$inPlaceholders = implode(",", array_fill(0, count($ids), "?"));
$stmt = $pdo->prepare("SELECT * FROM users WHERE id IN ($inPlaceholders)");
$stmt->execute($ids);

防御清单

php
<?php
// ✅ 永远使用预处理——即使只是简单查询
// ✅ 关闭模拟预处理(ATTR_EMULATE_PREPARES = false)
// ✅ 用 htmlspecialchars 输出到 HTML(防 XSS)
// ✅ 用 filter_var 验证输入格式
// ❌ 绝不拼接用户输入到 SQL