wallfilter需db-type显式匹配、校验开关启用及parser版本适配三者协同才生效;仅配置filters: wall但未设db-type或开关未开启,将导致防护静默失效。

WallFilter 不是开关式功能,开就“防住”,关就“失效”——它依赖配置生效、SQL解析上下文、数据库类型匹配三者协同。直接加 filters: wall 但没配 db-type,或用错 Provider(比如 MySQL 场景配了 db-type: postgresql),WallFilter 就会静默跳过校验。
确认 WallFilter 实际加载并绑定正确数据库类型
Spring Boot 下仅靠 druid.filters=wall,stat 不足以激活完整防护。Druid 必须知道你连的是哪种数据库,才能加载对应的 WallProvider(如 MySqlWallProvider)做语义分析。
-
db-type必须显式指定,且值要与实际 JDBC URL 匹配:MySQL 用mysql,PostgreSQL 用postgresql,Oracle 用oracle;写成mysql5或mysql8会失败 - 若使用
druid-spring-boot-starter1.2.38+,db-type不再自动推断,缺失即降级为无规则校验 - 启动时检查日志是否含
WallFilter init with dbType: mysql—— 没这句说明没加载成功
绕过 WHERE 条件的 DELETE/UPDATE 是默认拦截项,但需开启对应检查开关
WallFilter 对 DELETE FROM t WHERE 1=1 或 UPDATE t SET x=1 这类无条件操作,默认不报错,除非你主动启用校验开关。
-
delete-where-alway-true-check: true才会拦截恒真WHERE的DELETE -
update-where-alway-true-check: true才会拦截无WHERE或恒真WHERE的UPDATE -
select-all-column-allow: false可禁用SELECT *(部分审计场景需要) - 这些开关在
application.yml中属于druid.wall.config下级,缩进必须对齐,否则被忽略
误报和漏报常源于参数化 SQL 被绕过或 Parser 版本不匹配
Druid 的 WallFilter 基于自研 SQL Parser 做语义分析,不是正则匹配。但它只解析原始 SQL 字符串,一旦你在代码里拼接字符串(如 "SELECT * FROM user WHERE name = '" + name + "'"),Parser 看到的就是完整恶意语句,而 MyBatis 的 #{} 或 JDBC PreparedStatement 参数会被剥离,Parser 只看到占位符 —— 这是设计使然,也是安全前提。
- 拼接 SQL 时触发拦截 ≠ 防注入成功,只是暴露了坏习惯;真正防住靠的是参数化 +
WallFilter双保险 - MySQL 8.0+ 的窗口函数、CTE 等新语法,旧版 Druid(如 1.2.20)Parser 可能解析失败,导致整条 SQL 被跳过校验 —— 建议升到 1.2.38+
-
log-violation: true必须配合throw-exception: true使用,否则违规 SQL 仅记日志,业务继续执行
WallFilter 不拦截所有注入变种,别把它当万能盾
WallFilter 主要覆盖语法层风险:恒真条件、全表删改、危险关键字(DROP、EXEC)、宽字节绕过等。但它不处理逻辑层注入(如权限绕过 where user_id=#{userId} and status=1)、不检测盲注行为、也不防 ORM 层的 HQL/JPQL 注入。
- 它不分析运行时参数值,所以
WHERE id IN (#{idList})若传入恶意数组,仍可能被利用 - 对存储过程调用、
UNION SELECT后带子查询等复杂嵌套,解析覆盖率取决于 Parser 版本,非 100% - 线上建议始终开启
log-violation,定期扫日志里的Violation:行,比等告警更早发现问题模式
WallFilter 的有效性高度依赖配置精度和 SQL 编写规范。最常被忽略的不是“怎么开”,而是“开对没”——db-type 错、config 缩进错、Parser 版本老、或者把拼接 SQL 当参数化用,都会让防火墙形同虚设。











