Druid WallFilter 防火墙需 db-type 显式匹配、校验开关启用及日志验证三者协同才生效;仅配 filters: wall 但未设 db-type 或开关未开启,将导致防护静默失效。

Druid 的 SQL 防火墙(WallFilter)不是“开个开关就自动防住”的功能,它需要三要素同时满足:显式声明数据库类型、启用校验开关、配置生效且日志可验证。白名单拦截则需结合动态 SQL 校验逻辑,不能仅靠 WallFilter 实现。
必须显式配置 db-type 并确认加载成功
WallFilter 依赖数据库类型加载对应语法解析器(如 MySqlWallProvider),不匹配或缺失会导致静默失效:
- Spring Boot 中在 application.yml 显式写死
druid.wall.db-type: mysql(MySQL 场景),不可写mysql5或mysql8;PostgreSQL 写postgresql,Oracle 写oracle - 启动时务必检查日志是否出现 WallFilter init with dbType: mysql —— 没这句说明没加载,后续所有规则都不起作用
- 使用
druid-spring-boot-starter 1.2.38+后,db-type不再自动推断,缺失即降级为无规则校验
开启关键防护开关并注意缩进格式
默认规则非常宽松(例如不拦截 UNION SELECT,也不拦 DELETE FROM t WHERE 1=1),必须手动打开具体校验项:
- 在
druid.wall.config下级配置,缩进必须对齐,否则被完全忽略 -
delete-where-alway-true-check: true→ 拦截恒真 WHERE 的 DELETE -
update-where-alway-true-check: true→ 拦截无 WHERE 或恒真 WHERE 的 UPDATE -
select-all-column-allow: false→ 禁用SELECT *(审计强要求时启用) -
log-violation: true必须搭配throw-exception: true,否则只记日志,SQL 仍会执行
白名单拦截不能只靠 WallFilter,要分层实现
WallFilter 本身不支持用户自定义字段/表名白名单,所谓“白名单拦截”需结合业务逻辑落地:
立即学习“Java免费学习笔记(深入)”;
- 动态表名、列名、ORDER BY 字段只能用 MyBatis 的
${},但必须在 DAO 层做严格校验,比如用枚举限定合法值:if (!Arrays.asList("user", "order").contains(tableName)) throw new IllegalArgumentException(); - 正则校验更通用:
if (!tableName.matches("^[a-zA-Z][a-zA-Z0-9_]{2,30}$")) { ... } - WallFilter 的
tableWhiteList和tableBlackList是静态配置项,仅用于初始化时过滤系统表,不适用于运行时用户输入 - 真正防注入的根基仍是
#{}+ PreparedStatement,WallFilter 只是补充防线
避免常见配置陷阱
很多“开了防火墙却没效果”,其实卡在基础环节:
- 误启
config filter(druid.filter.config.enabled=true)会干扰 MyBatis 的参数解析,必须设为false - 未开启 PreparedStatement 缓存:
poolPreparedStatements: true和maxPoolPreparedStatementPerConnectionSize: 20要配齐,否则 MyBatis 可能退化为 Statement - MyBatis 中混用
${}且未校验——WallFilter 拦不住,因为解析器看到的是已拼接的完整 SQL - MySQL 8.0+ 新语法(如 CTE、窗口函数)需 Druid ≥ 1.2.38,旧版 Parser 解析失败会导致整条 SQL 跳过校验


















