PHP PDO MySQL LIKE查询使用%通配符时如何处理用户输入的%符号
问题根因
你遇到的403错误并非MySQL查询执行触发,请求在到达业务代码前就被ModSecurity WAF拦截:带前导%、多段%的查询参数命中了ModSecurity内置的SQL注入特征规则,因此直接拒绝请求并触发IP封禁策略,MySQL服务实际未收到对应查询请求。
可选解决方案
转义用户输入中的LIKE通配符
这是最推荐的通用方案:%和_本身就是MySQL LIKE语法的通配符,即使用户输入未触发WAF,原样拼接也会导致查询逻辑不符合预期(比如用户输入a%b本意是搜索包含a%b的内容,实际会变成匹配a开头、b结尾的任意内容)。
处理代码示例:// 先获取用户输入 $userInput = $_GET['q'] ?? ''; // 转义用户输入里的LIKE通配符,让其作为普通字符匹配 $q = str_replace(['%', '_'], ['\\%', '\\_'], $userInput); // 再拼接前后的通配符执行查询 $sql = 'SELECT * FROM users WHERE name LIKE :q ORDER BY date_created DESC'; $stmt = $db->prepare($sql); $stmt->bindValue(':q', '%' . $q . '%', PDO::PARAM_STR); $stmt->execute(); $results = $stmt->fetchAll(PDO::FETCH_OBJ);转义后的参数不再匹配WAF的SQL注入特征,不会触发拦截,同时也保证了查询逻辑符合预期。
调整ModSecurity规则
如果你有服务器管理权限,可以先查看ModSecurity的拦截日志,定位到触发拦截的具体规则ID,根据实际业务场景调整:- 针对该搜索接口的查询参数单独加白名单,跳过对应规则检测
- 调低对应规则的触发阈值,避免正常搜索请求被误拦截
该方案适合无法修改业务代码的场景,但需要注意调整规则不要降低整体防护能力。
替换为全文索引查询
如果你的搜索场景是全文模糊匹配,可以给name字段建立FULLTEXT索引,使用MATCH AGAINST语法替代LIKE查询:SELECT * FROM users WHERE MATCH(name) AGAINST(:q IN NATURAL LANGUAGE MODE) ORDER BY date_created DESC该方案完全不需要使用
%通配符,从根源上避免触发WAF规则,同时查询性能远高于通配符在前的LIKE查询,适合数据量较大的业务场景。前端输入校验辅助拦截
可以在前端对用户输入做校验,提示用户搜索内容不能包含%、_等特殊字符,提前拦截不符合要求的请求,减少误触发的概率,该方案为软限制,需要搭配后端处理逻辑使用,不能单独作为安全策略。
内容的提问来源于stack exchange,提问作者spice
相关产品推荐
相关产品推荐

