题目
如何安全地在PHP中处理用户输入以防止SQL注入?
信息
- 类型:问答
- 难度:⭐
考点
用户输入处理,SQL注入防护,预处理语句使用
快速回答
防止SQL注入的核心方法是使用预处理语句(Prepared Statements):
- 使用
PDO或mysqli扩展代替过时的mysql扩展 - 通过
prepare()方法定义带占位符的SQL语句 - 使用
bindParam()或execute()绑定用户输入值 - 避免直接拼接用户输入到SQL语句中
1. 原理说明
SQL注入是攻击者通过构造恶意输入篡改SQL语句的攻击手段。例如用户输入' OR '1'='1可能绕过登录验证。预处理语句将SQL指令与数据分离,数据库不会将用户输入解释为SQL代码。
2. 代码示例
// 使用PDO预处理语句示例
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email');
// 绑定用户输入(假设来自表单)
$email = $_POST['email'];
$stmt->bindParam(':email', $email);
$stmt->execute();
// 获取结果
$user = $stmt->fetch();
// mysqli预处理语句示例
$mysqli = new mysqli('localhost', 'user', 'pass', 'test');
$stmt = $mysqli->prepare('SELECT * FROM users WHERE email = ?');
$stmt->bind_param('s', $_POST['email']);
$stmt->execute();3. 最佳实践
- 始终使用预处理语句:处理任何用户输入(包括表单、URL参数、Cookie)
- 选择PDO或mysqli:PDO支持多数据库,mysqli针对MySQL优化
- 设置字符集:创建连接后立即执行
$pdo->exec('SET NAMES utf8mb4') - 错误处理:启用异常模式
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)
4. 常见错误
- 拼接SQL语句:
$sql = "SELECT * FROM users WHERE id = '" . $_GET['id'] . "'" - 错误使用函数:
addslashes()或mysql_real_escape_string()不能完全防御 - 仅前端验证:JavaScript验证可被绕过,必须后端防护
5. 扩展知识
- 二次注入:即使使用预处理写入数据,读取时未过滤仍可能触发注入
- 其他防护层:
- 输入验证:
filter_var($email, FILTER_VALIDATE_EMAIL) - 最小权限原则:数据库用户仅授予必要权限
- Web应用防火墙(WAF)
- 输入验证:
- ORM框架:如Laravel的Eloquent会自动使用预处理语句