如何利用mysqli_stmt_prepare防止PHP中SQL注入?
- 内容介绍
- 文章标签
- 相关推荐
本文共计991个文字,预计阅读时间需要4分钟。
直接使用 `mysqli_prepare()` 和 `mysqli_stmt_bind_param()` 是一种依赖原型的注入防御路径,它主要依靠参数绑定来防止注入攻击。其他任何字符字符串拼接、转换或过滤都不算真正的防御——它们只是延迟漏洞暴露的时间而已。
为什么 mysqli_query() 拼字符串一定会出事
因为数据库引擎看到的是完整语句,用户输入一旦没被隔离,就自动获得“代码身份”。比如 id = $_GET['id'],传入 1 OR 1=1,拼出来就是 SELECT * FROM user WHERE id = 1 OR 1=1,全表返回。
常见错误包括:
- 只对字符串字段用
mysqli_real_escape_string(),但数字字段不加引号,转义完全无效 - 忘了调用
mysqli_set_charset($conn, 'utf8mb4'),宽字节注入可绕过转义 - 把变量拼进 SQL 字符串里再传给
mysqli_prepare(),比如"WHERE name = '{$_POST['name']}'",prepare 根本没起作用
mysqli_prepare() 的正确调用链
必须按顺序走完三步:准备 → 绑定 → 执行。缺一不可,且绑定必须在执行前完成。
本文共计991个文字,预计阅读时间需要4分钟。
直接使用 `mysqli_prepare()` 和 `mysqli_stmt_bind_param()` 是一种依赖原型的注入防御路径,它主要依靠参数绑定来防止注入攻击。其他任何字符字符串拼接、转换或过滤都不算真正的防御——它们只是延迟漏洞暴露的时间而已。
为什么 mysqli_query() 拼字符串一定会出事
因为数据库引擎看到的是完整语句,用户输入一旦没被隔离,就自动获得“代码身份”。比如 id = $_GET['id'],传入 1 OR 1=1,拼出来就是 SELECT * FROM user WHERE id = 1 OR 1=1,全表返回。
常见错误包括:
- 只对字符串字段用
mysqli_real_escape_string(),但数字字段不加引号,转义完全无效 - 忘了调用
mysqli_set_charset($conn, 'utf8mb4'),宽字节注入可绕过转义 - 把变量拼进 SQL 字符串里再传给
mysqli_prepare(),比如"WHERE name = '{$_POST['name']}'",prepare 根本没起作用
mysqli_prepare() 的正确调用链
必须按顺序走完三步:准备 → 绑定 → 执行。缺一不可,且绑定必须在执行前完成。

