在PHP中,防止SQL注入的最佳实践是使用 预处理语句(Prepared Statements),而不是手动转义或过滤输入,以下是两种主流方法的实现:

方法1:使用 PDO(推荐,支持多种数据库)
// 连接数据库
$dsn = 'mysql:host=localhost;dbname=test;charset=utf8mb4';
$username = 'root';
$password = '';
try {
$pdo = new PDO($dsn, $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("数据库连接失败: " . $e->getMessage());
}
// 示例:安全查询(使用命名参数)
$userInput = $_POST['user_id'];
$sql = "SELECT * FROM users WHERE id = :id";
$stmt = $pdo->prepare($sql);
// 绑定参数(自动处理类型和转义)
$stmt->bindParam(':id', $userInput, PDO::PARAM_INT); // 明确指定类型
$stmt->execute();
// 获取结果
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
方法2:使用 MySQLi(适用于MySQL)
// 连接数据库
$conn = new mysqli('localhost', 'root', '', 'test');
if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
}
// 示例:安全查询(使用占位符 ?)
$userInput = $_POST['user_id'];
$sql = "SELECT * FROM users WHERE id = ?";
$stmt = $conn->prepare($sql);
// 绑定参数(s=字符串, i=整数, d=小数, b=二进制)
$stmt->bind_param('i', $userInput); // 'i' 表示整数类型
$stmt->execute();
// 获取结果
$result = $stmt->get_result();
$results = $result->fetch_all(MYSQLI_ASSOC);
关键安全原则:
-
永远不要拼接用户输入到SQL语句中
❌ 错误示例:$sql = "SELECT * FROM users WHERE id = $userInput"; -
始终使用预处理语句
PDO和MySQLi的预处理机制会自动处理特殊字符(如引号),从根本上阻止注入。 -
指定参数类型
明确用bindParam或bind_param指定类型(如整数、字符串),避免类型混淆漏洞。
-
设置字符集
在连接字符串中指定charset=utf8mb4(PDO)或mysqli_set_charset($conn, 'utf8mb4')。
不推荐的手动转义方法(遗留方案)
仅适用于老旧代码库,新项目务必使用预处理语句!
// 使用 mysqli_real_escape_string(需先连接数据库) $input = $_POST['name']; $safe_input = mysqli_real_escape_string($conn, $input); $sql = "SELECT * FROM users WHERE name = '$safe_input'";
// 注意:此方法仍需手动处理数据类型,且易出错!

---
### 额外防御措施:
- **输入验证**:用`filter_var()`验证邮箱、URL等格式。
- **最小权限原则**:数据库用户只赋予必要权限。
- **错误处理**:生产环境关闭错误回显(避免泄露敏感信息)。
---
###
| 方案 | 安全性 | 数据库支持 | 推荐度 |
|--------------------|--------|----------------|--------|
| PDO预处理 | ★★★★★ | 多数据库 | ✅ 首选 |
| MySQLi预处理 | ★★★★★ | 仅MySQL | ✅ 推荐 |
| 手动转义 | ★★☆☆☆ | 有局限性 | ❌ 避免 |
始终选择 **预处理语句**,这是防御SQL注入最可靠的方式!
图片来源于AI模型,如侵权请联系管理员。作者:酷小编,如若转载,请注明出处:https://www.kufanyun.com/ask/295533.html

