WallFilter本质是SQL字符串的静态解析器,非精准防御;它依赖正确配置db-type、开启对应检查项、匹配Parser版本,仅对语法层明确节点拦截,不介入语义与PreparedStatement流程。

WallFilter 不是“精准防御”,它只做语法层拦截
WallFilter 无法识别语义、不分析执行上下文、不介入 PreparedStatement 参数绑定过程,所谓“精准”是误解。它本质是 SQL 字符串的静态解析器,靠 MySqlWallProvider(或对应数据库的 Provider)把原始 SQL 拆成抽象语法树(AST),再按预设规则扫描关键词、结构和模式。
它能拦住 UNION SELECT、INTO OUTFILE、无 WHERE 的 DELETE,是因为这些在 AST 上表现为明确节点;但它对 SELECT * FROM user WHERE name = #{name} 完全放行——因为 #{name} 被 Parser 当作占位符剥离,剩下的是干净的骨架。
- 真正起防护作用的是 MyBatis 的
#{} → PreparedStatement流程,WallFilter 只是最后一道“查岗”的哨兵 - 一旦代码里出现
${tableName}拼接,WallFilter 才会看到完整恶意字符串,这时才可能触发拦截 - Base64 编码、注释绕过(
/* */ OR 1=1 --)、宽字节注入等,它基本无效
db-type 配错,WallFilter 就等于没开
WallFilter 必须加载匹配的 WallProvider 才能工作。MySQL 场景下写 db-type: mysql5 或 mysql8,或漏配 db-type,都会导致日志里找不到 WallFilter init with dbType: mysql —— 这说明整个防火墙模块根本没启动,后续所有配置形同虚设。
- Spring Boot 中必须显式声明:
spring.datasource.druid.wall.db-type=mysql - 值只能是
mysql、postgresql、oracle等标准枚举名,大小写敏感 - 1.2.38+ 版本起,
db-type不再自动推断,缺失即降级为无规则校验
常见报错其实是配置开关没打开
遇到 sql injection violation, part alway true condition not allow 或 multi-statement not allow,不是 WallFilter “误报”,而是你没启用对应检查项。它的默认策略非常宽松,多数危险行为需要手动开闸。
-
delete-where-alway-true-check: true才拦截DELETE FROM t WHERE 1=1 -
multi-statement-allow: false是默认值,但若业务真要分号多语句,得设为true(注意:这不提升安全性,只是放开语法) - 所有
druid.wall.config.xxx配置必须缩进对齐,YAML 解析失败时字段直接被忽略
Parser 版本不匹配会导致整条 SQL 跳过校验
Druid 的 SQL 解析能力取决于内置 Parser。MySQL 8.0+ 的 CTE(WITH ... AS)、窗口函数(ROW_NUMBER() OVER)在旧版 Druid(如 1.2.20)中会直接抛 syntax error,Parser 放弃解析,整条 SQL 就绕过了 WallFilter 校验。
- 升级到
druid 1.2.38+是首选方案,它已适配主流新版语法 - 临时妥协可设
strictSyntaxCheck: false,但这只是关掉语法检查,不等于关掉注入规则 - 不要在
connection-init-sql里执行SET sql_mode='',宽字节注入可能借此复活
WallFilter 的价值不在“精准”,而在“可控”。它不替代参数化,也不覆盖代码漏洞,但能把开发误操作(如漏写 WHERE)、脚本误执行(如 DROP TABLE)、以及部分低阶注入 payload 拦在连接池入口。真正容易被忽略的,是它极度依赖配置完整性——少一个 db-type,或缩进错两格,它就彻底静默。

















