应使用预处理语句(pdo或mysqli)并严格过滤验证输入;pdo需设异常模式、用占位符、prepare后execute绑定参数;mysqli需prepare、bind_param指定类型;输入须校验类型、格式与长度。

如果在PHP应用程序中直接将用户输入拼接到SQL查询语句中,攻击者可能通过构造恶意输入篡改查询逻辑,从而读取、修改或删除数据库中的敏感数据。以下是防范SQL注入攻击的多种有效方法:
一、使用预处理语句(PDO)
预处理语句将SQL逻辑与用户数据严格分离,数据库驱动会自动对参数进行转义和类型绑定,从根本上杜绝SQL注入的可能性。
1、创建PDO连接实例,并设置错误模式为异常模式,便于捕获错误。
2、编写含占位符的SQL语句,例如 SELECT * FROM users WHERE username = ? 或使用命名参数 WHERE username = :username。
立即学习“PHP免费学习笔记(深入)”;
3、调用 prepare() 方法获取PDOStatement对象。
4、使用 execute() 方法传入参数数组,系统自动完成安全绑定。
二、使用预处理语句(MySQLi)
MySQLi扩展同样支持面向对象和过程式两种风格的预处理,其参数绑定机制与PDO原理一致,确保用户输入不参与SQL语法解析。
1、通过 mysqli_prepare() 准备SQL语句,其中使用 ? 作为参数占位符。
2、调用 mysqli_stmt_bind_param() 绑定变量,第一个参数指定类型(如 s 表示字符串,i 表示整数)。
3、执行语句时,绑定的变量值由MySQL服务器内部安全处理,不会被解释为SQL代码。
三、严格过滤与验证输入数据
在接收用户输入后、进入数据库操作前,应依据业务规则对数据类型、长度、格式进行强制校验,拒绝非法输入,形成第一道防御屏障。
1、对数字型参数使用 filter_var($input, FILTER_VALIDATE_INT) 或强制类型转换 (int)$input。
2、对邮箱字段使用 filter_var($email, FILTER_VALIDATE_EMAIL) 进行格式验证。
3、对字符串长度超出预期的输入立即截断或拒绝,例如使用 strlen($str) 判断用户名长度。
四、转义特殊字符(仅限无法使用预处理的遗留场景)
当因历史原因无法重构为预处理语句时,必须使用数据库特定的转义函数对每个用户输入单独处理,且仅在拼接前调用一次。
1、使用 mysqli_real_escape_string($connection, $input) 对输入进行转义,该函数依赖有效数据库连接。
2、严禁使用已废弃的 mysql_escape_string() 或未加连接参数的 addslashes()。
3、转义后的字符串必须用单引号包裹在SQL语句中,例如 '".mysqli_real_escape_string($conn, $user)."'。
五、最小权限原则配置数据库账户
即使SQL注入漏洞被利用,限制数据库用户的操作权限可大幅降低实际危害,防止攻击者执行高危命令或访问无关表。
1、为Web应用单独创建数据库用户,避免使用 root 或具有 SUPER 权限的账号。
2、仅授予该用户所需的具体权限,例如仅 SELECT, INSERT, UPDATE,禁用 DROP, ALTER, CREATE, FILE 等危险权限。
3、限定用户访问的数据库范围,例如只允许连接 app_database,禁止跨库查询。











