在PHP开发中,安全是绕不开的核心话题,尤其是SQL注入攻击,它通过构造恶意输入篡改SQL语句,可能导致数据泄露、删除甚至服务器沦陷。防御SQL注入的核心原则是:永远不要信任用户输入,所有动态数据必须经过严格处理后再拼接到SQL中。
参数化查询(预处理语句)是防御SQL注入的黄金标准。以PDO为例,使用`prepare()`和`execute()`分离SQL逻辑与数据:
$pdo = new PDO(‘mysql:host=localhost;dbname=test’, ‘user’, ‘pass’);
$stmt = $pdo->prepare(‘SELECT FROM users WHERE username = :username’);
$stmt->execute([‘:username’ => $_GET[‘user’] ?? ”]);
$result = $stmt->fetchAll();
这种方式下,用户输入会被当作纯数据而非SQL代码解析,即使输入包含`’ OR 1=1–`等恶意字符也无法执行。

AI图片,仅供参考
若因特殊原因无法使用预处理,必须对输入进行转义处理。MySQLi扩展的`real_escape_string()`或PDO的`quote()`方法可转义特殊字符,但需注意连接对象必须与执行查询的对象一致:
$mysqli = new mysqli(‘localhost’, ‘user’, ‘pass’, ‘test’);
$safe_input = $mysqli->real_escape_string($_GET[‘user’]);
$query = \”SELECT FROM users WHERE username = ‘$safe_input’\”;
不过转义方法存在误用风险,仅作为备选方案。
最小权限原则是数据库安全的另一道防线。为Web应用创建专用数据库用户,仅授予必要权限(如仅SELECT/UPDATE而非DROP TABLE),即使被注入攻击,损失也可控。同时,避免在代码中硬编码数据库凭据,使用环境变量或配置文件(如`.env`)存储,并设置文件权限为600。
输入验证与过滤是前置防御。对数字ID使用`filter_var($_GET[‘id’], FILTER_VALIDATE_INT)`,对字符串限制长度并移除特殊字符。例如,用户名只允许字母数字:
$username = preg_replace(‘/[^a-zA-Z0-9]/’, ”, $_GET[‘user’] ?? ”);
结合白名单机制,拒绝所有不符合预期格式的输入。
安全开发还需关注框架特性。Laravel的Eloquent ORM、Symfony的Doctrine均默认使用参数化查询,可大幅降低风险。定期更新PHP版本和扩展库,及时修复已知漏洞。•使用工具如SQLMap进行渗透测试,或通过日志监控异常SQL语句,持续优化防御策略。