一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

如何使用正则表达式过滤用户输入以防止SQL注入?

时间:2026-07-10 10:50:57 编辑:袖梨 来源:一聚教程网

正则表达式不能防止SQL注入,仅可用于前端提示或日志筛查;真正防护必须依赖mysqli::prepare或PDO::prepare参数化查询,并配合输入过滤与最小权限原则。

正则表达式不能防止 SQL 注入,它最多只能做前端提示或日志筛查——真正在数据库执行前拦截恶意输入,必须靠 mysqli::preparePDO::prepare

为什么用正则过滤SQL注入关键词是危险的

攻击者早就不写 SELECT 了,改用 sel/**/ect%27(URL 编码单引号)、UNI/**/ON、甚至双写绕过(SELESELECTCT)都能轻松跳过 /union|select|drop/i 这类规则。更麻烦的是,preg_replace 直接删掉匹配内容会破坏合法字段:用户昵称叫 “Union Jack” 就变成 “Jack”,而删掉 WHERE 后的空格还可能触发 MySQL strict mode 报错。

常见错误现象包括:

  • PREG_BACKTRACK_LIMIT_ERROR:超长输入+贪婪匹配(如 .*)导致 PCRE 回溯爆炸
  • 中文截断:PHP 中没加 u 修饰符,preg_match 在 UTF-8 字符串里中途崩溃
  • 大小写漏判:用 /i 本意是兼容,结果让 selECT 漏过;不如直接禁用该字段

哪些正则场景勉强可用

只在两类地方能用,且必须配合后端参数化查询:

  • 前端 JS 表单校验:比如拦截明显畸形输入 ' OR 1=1 --、连续 5 个以上括号 (((((、裸露分号结尾 ;
  • 日志关键词筛查:从 access.log 或 audit 日志里快速提取疑似攻击片段,例如匹配 /(%27)|(')|(--)|(#)/,用于告警而非阻断

推荐写法示例(PHP):

if (preg_match('/['";--=<>]|--|*//', $input)) {    // 记录日志 + 前端提示,但不拒绝请求    error_log("Suspicious input: " . $input);    echo "输入含非法符号,请检查";}

注意:['";--=] 里连字符 - 必须放最后,否则被解释为范围符;*/ 要转义。

真正该做的三件事(顺序不能错)

把精力从“怎么写正则”转移到这三步上,防护效果远超任何字符串匹配:

  • 所有数据库操作统一走 mysqli::preparePDO::prepare,变量全用 ? 占位符
  • 用户输入进 SQL 前,先过 filter_var($input, FILTER_SANITIZE_SPECIAL_CHARS)(PHP 8.1+ 推荐),或至少用 htmlspecialchars($input, ENT_QUOTES, 'UTF-8')
  • 数据库账号权限最小化——应用账号只给 SELECTINSERT,绝不要 FILEEXECUTEDROP

正则唯一不可替代的作用,是帮你发现异常输入模式;但它永远没法定义“合法 SQL”——比如 JSON 字段里嵌了 SQL 片段,或者 GraphQL 查询体混了原生语句,这种边界 case 只能靠协议层和权限层来兜底。

热门栏目