PHP怎么转义SQL字符 PHP防止SQL注入字符串处理【解决】

4次阅读

必须用预处理语句(pdomysqli)防止sql注入,addslashes()无效且危险;表名、字段名等需白名单校验;输出过滤(如htmlspecialchars)不防sql注入。

PHP怎么转义SQL字符 PHP防止SQL注入字符串处理【解决】

php里别用 addslashes() 做SQL转义

它不能防SQL注入,只做简单反斜杠插入,对多字节编码、宽字符、不同字符集下的绕过完全无效。MySQL 5.7+ 默认 strict mode 下甚至可能直接报错。

  • addslashes() 不识别当前连接的字符集,mysql_real_escape_string() 已废弃且依赖过时扩展
  • 它不处理引号外的上下文(比如数字型参数、ORDER BY 子句、表名),误用等于白防
  • 如果数据库连接用了 gbkbig5,攻击者可用 %A1%AA 这类双字节构造截断,绕过 addslashes()

必须用预处理语句(PDO 或 mysqli

这是唯一被广泛验证、语言层和驱动层共同保障的安全方案。核心不是“转义字符串”,而是把数据和SQL结构彻底分离。

  • PDO 示例:$stmt = $pdo->prepare("select * FROM users WHERE id = ? AND status = ?"); $stmt->execute([$id, $status]);
  • MySQLi 示例:$stmt = $mysqli->prepare("INSERT intO log (msg) VALUES (?)"); $stmt->bind_param("s", $msg); $stmt->execute();
  • 占位符只支持值(? 或命名参数如 :name),不能用于表名、字段名、ORDER BY 字段——这些必须走白名单校验
  • 开启 PDO::ATTR_EMULATE_PREPARES = false,否则 PDO 会在客户端模拟预处理,失去服务端解析保护

真要拼接 SQL(极少数场景),用 mysqli_real_escape_string() 而非全局函数

仅限你明确控制了连接字符集、且确认无法用预处理的遗留代码。它依赖当前 mysqli 实例的连接状态,比 addslashes() 可靠,但仍是次选。

  • 必须先建立连接,再调用:$escaped = mysqli_real_escape_string($mysqli, $input);
  • 不能写成 mysqli_real_escape_string($input)(缺连接资源,会警告并返回 false
  • 如果连接字符集没设对(比如 PHP 连接时没执行 SET NAMES utf8mb4),它依然可能失效
  • 注意:它不处理数字型参数的类型校验,传入 "1 OR 1=1" 给 int 字段仍可能被绕过,所以仍需配合 (int) 强转或 filter_var($x, FILTER_VALIDATE_INT)

过滤输出和过滤输入是两回事,别混

防SQL注入只管“进数据库前”;htmlspecialchars() 是防xss,用在输出到HTML时,对SQL毫无作用。

立即学习PHP免费学习笔记(深入)”;

  • 常见错误:对用户输入先 htmlspecialchars() 再插进SQL——这会让单引号变成 ',存进库的是 HTML 实体,不是原始字符
  • 更糟的是:从库读出后又 htmlspecialchars() 一次,导致显示为乱码
  • 记住:入库用预处理,出库按用途处理——HTML 输出用 htmlspecialchars()json 输出用 json_encode(),CSV 用 fputcsv()

事情说清了就结束。真正难的不是写对那几行 prepare,而是所有动态拼接点——包括 ORDER BYLIMIT、表名——都得有对应校验逻辑,而这类地方最容易被漏掉。

text=ZqhQzanResources