2026-04-25 09:26:51
在PHP中防止SQL注入,核心在于对用户输入进行严格验证和过滤,并使用参数化查询或预处理语句。以下是几种有效方法:
1. 使用预处理语句(Prepared Statements)或参数化查询这是防止SQL注入最有效的方法,通过将SQL结构与数据分离,确保用户输入被当作参数处理而非可执行代码。
PDO示例:
$pdo = new PDO("mysql:host=localhost;dbname=mydatabase", "username", "password");$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ? AND password = ?");$stmt->execute([$_POST['username'], $_POST['password']]);$user = $stmt->fetch();mysqli示例:
$mysqli = new mysqli("localhost", "username", "password", "mydatabase");$stmt = $mysqli->prepare("SELECT * FROM users WHERE username = ? AND password = ?");$stmt->bind_param("ss", $_POST['username'], $_POST['password']); // "ss"表示两个字符串$stmt->execute();$result = $stmt->get_result();$user = $result->fetch_assoc();原理:数据库服务器先编译SQL结构,再将数据作为参数传递,即使数据中包含SQL关键字,也会被当作普通数据处理。
2. 输入验证和过滤虽然预处理语句是首选,但输入验证可提供额外安全层,确保数据符合预期格式。
mysqli_real_escape_string():首选,考虑数据库字符集。
htmlspecialchars():用于输出到HTML时转义,不直接用于SQL。
addslashes():不推荐,因不考虑字符集,可能失效。
示例(不推荐直接拼接,仅展示转义):
$username = $mysqli->real_escape_string($_POST['username']);$password = $mysqli->real_escape_string($_POST['password']);$sql = "SELECT * FROM users WHERE username = '" . $username . "' AND password = '" . $password . "'";$result = $mysqli->query($sql);3. 最小权限原则数据库用户仅授予执行任务所需的最低权限,避免使用root或admin权限连接数据库。
4. 错误处理保持PHP和数据库服务器更新至最新版本,修复已知安全漏洞。
为什么转义特殊字符不足?最佳实践:优先使用预处理语句,而非依赖转义。
遗留代码中的SQL注入风险处理若无法立即重构整个代码库,可采取分阶段方法:
总结:防止SQL注入的核心是不信任任何用户输入,优先使用预处理语句或参数化查询,结合输入验证、最小权限原则和错误处理,可显著提升安全性。对于遗留代码,需分阶段逐步修复,避免直接拼接SQL查询。