在 PHP 中,通过 转义 和 过滤 防护 MySQL 注入攻击是基础措施。以下是具体的实现方法和实例。
---
1. 转义用户输入
转义是通过添加反斜杠 \ 来处理特殊字符(如 '、"、\、\0 等),防止它们破坏 SQL 查询结构。常用方法如下:
方法 1:使用 mysqli_real_escape_string()
mysqli_real_escape_string() 会根据数据库连接的字符集,对输入数据进行安全的转义。
<?php
// 数据库连接
$mysqli = new mysqli("localhost", "username", "password", "database");
// 用户输入
$username = $_POST['username'];
$password = $_POST['password'];
// 转义输入数据
$username = $mysqli->real_escape_string($username);
$password = $mysqli->real_escape_string($password);
// 构造 SQL 查询
$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
// 执行查询
$result = $mysqli->query($query);
?>
方法 2:使用 addslashes()
addslashes() 会简单地对单引号、双引号、反斜杠和空字符添加转义字符。
> ⚠️ 注意:addslashes() 不适合处理数据库输入,因为它不了解数据库上下文。
<?php
$username = addslashes($_POST['username']);
$password = addslashes($_POST['password']);
$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
---
2. 过滤用户输入
过滤用于确保输入数据符合预期格式,拒绝不合法或恶意输入。
方法 1:使用正则表达式
通过正则表达式验证输入格式。
<?php
$username = $_POST['username'];
// 检查用户名是否只包含字母、数字和下划线,长度在 3-20
if (!preg_match('/^[a-zA-Z0-9_]{3,20}$/', $username)) {
die("Invalid username format.");
}
方法 2:使用 PHP 的过滤器
PHP 提供了一些内置的过滤器函数,比如 filter_var()。
<?php
$id = $_GET['id'];
// 验证输入是否为整数
if (!filter_var($id, FILTER_VALIDATE_INT)) {
die("Invalid ID.");
}
方法 3:使用白名单
限定输入值为预定义的合法值。
<?php
$role = $_POST['role'];
$allowed_roles = ['admin', 'user', 'editor'];
// 检查输入是否在白名单中
if (!in_array($role, $allowed_roles)) {
die("Invalid role.");
}
---
3. 转义 + 过滤的完整实例
转义和过滤结合使用,可以有效防护 MySQL 注入。
<?php
// 数据库连接
$mysqli = new mysqli("localhost", "username", "password", "database");
// 用户输入
$username = $_POST['username'];
$password = $_POST['password'];
// 过滤输入格式
if (!preg_match('/^[a-zA-Z0-9_]{3,20}$/', $username)) {
die("Invalid username format.");
}
// 转义输入数据
$username = $mysqli->real_escape_string($username);
$password = $mysqli->real_escape_string($password);
// 构造查询
$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = $mysqli->query($query);
// 检查查询结果
if ($result->num_rows > 0) {
echo "Login successful!";
} else {
echo "Invalid username or password.";
}
?>
---
4. 对转义和过滤的评价
优点:
转义:能有效避免特殊字符破坏 SQL 语句,适用于基本的安全防护。
过滤:能够防止非法输入,限制数据范围,提高数据质量。
缺点:
转义的局限性:
手动转义增加代码复杂度。
依赖于开发者的实现,容易遗漏某些场景。
过滤的局限性:
需要针对每个输入自定义规则,复杂场景下容易出错。
建议:
虽然转义和过滤是有效的防护方法,但并不是最佳解决方案。现代 PHP 开发推荐使用参数化查询(PDO 或 MySQLi 预处理语句),因为它比手动转义更高效、更安全。
---
5. 与参数化查询结合
可以将转义和过滤与参数化查询结合使用,构建更全面的安全体系。
<?php
$pdo = new PDO("mysql:host=localhost;dbname=test", "username", "password");
// 用户输入
$username = $_POST['username'];
$password = $_POST['password'];
// 过滤输入
if (!preg_match('/^[a-zA-Z0-9_]{3,20}$/', $username)) {
die("Invalid username format.");
}
// 使用参数化查询
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username AND password = :password");
$stmt->execute([':username' => $username, ':password' => $password]);
$result = $stmt->fetch();
if ($result) {
echo "Login successful!";
} else {
echo "Invalid username or password.";
}
?>
---
总结
1. 转义:使用 mysqli_real_escape_string() 或类似方法,确保输入安全。
2. 过滤:验证和清理输入数据,保证其合法性。
3. 结合参数化查询:这是最安全和推荐的防护方案,自动处理转义,避免注入。
---
1. 转义用户输入
转义是通过添加反斜杠 \ 来处理特殊字符(如 '、"、\、\0 等),防止它们破坏 SQL 查询结构。常用方法如下:
方法 1:使用 mysqli_real_escape_string()
mysqli_real_escape_string() 会根据数据库连接的字符集,对输入数据进行安全的转义。
<?php
// 数据库连接
$mysqli = new mysqli("localhost", "username", "password", "database");
// 用户输入
$username = $_POST['username'];
$password = $_POST['password'];
// 转义输入数据
$username = $mysqli->real_escape_string($username);
$password = $mysqli->real_escape_string($password);
// 构造 SQL 查询
$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
// 执行查询
$result = $mysqli->query($query);
?>
方法 2:使用 addslashes()
addslashes() 会简单地对单引号、双引号、反斜杠和空字符添加转义字符。
> ⚠️ 注意:addslashes() 不适合处理数据库输入,因为它不了解数据库上下文。
<?php
$username = addslashes($_POST['username']);
$password = addslashes($_POST['password']);
$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
---
2. 过滤用户输入
过滤用于确保输入数据符合预期格式,拒绝不合法或恶意输入。
方法 1:使用正则表达式
通过正则表达式验证输入格式。
<?php
$username = $_POST['username'];
// 检查用户名是否只包含字母、数字和下划线,长度在 3-20
if (!preg_match('/^[a-zA-Z0-9_]{3,20}$/', $username)) {
die("Invalid username format.");
}
方法 2:使用 PHP 的过滤器
PHP 提供了一些内置的过滤器函数,比如 filter_var()。
<?php
$id = $_GET['id'];
// 验证输入是否为整数
if (!filter_var($id, FILTER_VALIDATE_INT)) {
die("Invalid ID.");
}
方法 3:使用白名单
限定输入值为预定义的合法值。
<?php
$role = $_POST['role'];
$allowed_roles = ['admin', 'user', 'editor'];
// 检查输入是否在白名单中
if (!in_array($role, $allowed_roles)) {
die("Invalid role.");
}
---
3. 转义 + 过滤的完整实例
转义和过滤结合使用,可以有效防护 MySQL 注入。
<?php
// 数据库连接
$mysqli = new mysqli("localhost", "username", "password", "database");
// 用户输入
$username = $_POST['username'];
$password = $_POST['password'];
// 过滤输入格式
if (!preg_match('/^[a-zA-Z0-9_]{3,20}$/', $username)) {
die("Invalid username format.");
}
// 转义输入数据
$username = $mysqli->real_escape_string($username);
$password = $mysqli->real_escape_string($password);
// 构造查询
$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = $mysqli->query($query);
// 检查查询结果
if ($result->num_rows > 0) {
echo "Login successful!";
} else {
echo "Invalid username or password.";
}
?>
---
4. 对转义和过滤的评价
优点:
转义:能有效避免特殊字符破坏 SQL 语句,适用于基本的安全防护。
过滤:能够防止非法输入,限制数据范围,提高数据质量。
缺点:
转义的局限性:
手动转义增加代码复杂度。
依赖于开发者的实现,容易遗漏某些场景。
过滤的局限性:
需要针对每个输入自定义规则,复杂场景下容易出错。
建议:
虽然转义和过滤是有效的防护方法,但并不是最佳解决方案。现代 PHP 开发推荐使用参数化查询(PDO 或 MySQLi 预处理语句),因为它比手动转义更高效、更安全。
---
5. 与参数化查询结合
可以将转义和过滤与参数化查询结合使用,构建更全面的安全体系。
<?php
$pdo = new PDO("mysql:host=localhost;dbname=test", "username", "password");
// 用户输入
$username = $_POST['username'];
$password = $_POST['password'];
// 过滤输入
if (!preg_match('/^[a-zA-Z0-9_]{3,20}$/', $username)) {
die("Invalid username format.");
}
// 使用参数化查询
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username AND password = :password");
$stmt->execute([':username' => $username, ':password' => $password]);
$result = $stmt->fetch();
if ($result) {
echo "Login successful!";
} else {
echo "Invalid username or password.";
}
?>
---
总结
1. 转义:使用 mysqli_real_escape_string() 或类似方法,确保输入安全。
2. 过滤:验证和清理输入数据,保证其合法性。
3. 结合参数化查询:这是最安全和推荐的防护方案,自动处理转义,避免注入。