ThinkPHP 5.1 的 like 查询本身不引发 SQL 注入,但错误字符串拼接会绕过参数绑定;必须使用结构化写法(如 where('field','like','%'.input('q/s').'%'))并配合类型约束、转义及字段白名单。

ThinkPHP 5.1 的 like 查询本身不自动触发 SQL 注入,但**错误的字符串拼接方式会彻底绕过框架的参数绑定机制**,让 like 成为高危入口。关键不是“用不用 like”,而是“怎么传值”。
别这样写:双引号/单引号内直接拼接
以下写法完全失效预处理,等同于裸奔:
-
where("title like '%". input('q') . "%'")—— 单/双引号包裹 + 字符串拼接,input('q')中的' OR 1=1 --会被原样执行 -
where("title like '%" . input('q') . "%')—— 同上,括号和引号都挡不住注入 -
where('title', 'like', '%' . input('q') . '%')—— ✅ 这个安全,但注意:仅当input('q')是纯字符串且未被二次污染时才成立;若它来自 JSON 解析、Base64 解码或数据库回填,仍需额外过滤
必须用框架识别的结构化写法
让 ThinkPHP 明确知道你在做「参数化 like 匹配」,它才会启用 PDO 绑定:
-
where('title', 'like', '%' . input('q/s') . '%')——/s强制字符串类型,防数组绕过;%写在 PHP 层,不进 SQL 模板 -
where(['title' => ['like', '%' . input('q/s') . '%']])—— 数组式写法,兼容性更强,自动触发绑定 -
where(function ($query) { $query->where('title', 'like', '%' . input('q/s') . '%'); })—— 闭包封装,适合复杂条件,同样安全
搜索关键词含特殊符号?先转义再拼
用户搜 100% 或 abc_ 时,% 和 _ 是 SQL 通配符,需手动转义(不是防注入,是保语义):
- 用
addcslashes()转义:$safeQ = addcslashes(input('q/s'), '%_\'); - 再构造:
where('title', 'like', '%' . $safeQ . '%', ['escape' => '\']) - 最后加
->bind(['escape' => '\'])确保 ESCAPE 子句生效(TP5.1 支持该语法)
绝对禁止动态字段名参与 like
不要让用户决定“对哪个字段 like”——field=input('col') + like 是双重风险:
- 字段名无法参数化,必须白名单校验:
$allow = ['title', 'content', 'remark']; $col = in_array(input('col'), $allow) ? input('col') : 'title'; - 然后才:
where($col, 'like', '%' . input('q/s') . '%') - 禁用
raw()或exp包裹字段名,例如where(raw(input('col')) . ' like ?', ['%' . input('q') . '%'])—— ❌ 危险,raw()表示“你来负责安全”,而你并没有
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











