Druid连接池SQL防火墙规则配置:自定义黑白名单

Druid连接池SQL防火墙规则配置:自定义黑白名单

【免费下载链接】druid 阿里云计算平台DataWorks(https://help.aliyun.com/document_detail/137663.html) 团队出品,为监控而生的数据库连接池 【免费下载链接】druid 项目地址: https://gitcode.com/gh_mirrors/druid/druid

1. 为什么需要SQL防火墙?

你是否遇到过生产环境中突然出现大量慢查询?或者担心开发人员误写的DELETE语句导致全表数据被清空?Druid连接池内置的SQL防火墙(WallFilter)可以帮你解决这些问题。通过灵活的黑白名单规则,你可以精确控制哪些SQL操作被允许,哪些被拒绝,从而有效防止SQL注入攻击和误操作。

读完本文后,你将能够:

  • 理解Druid SQL防火墙的核心原理
  • 配置表级和函数级的黑白名单规则
  • 实现动态更新防火墙规则
  • 结合实际场景设计安全策略

2. SQL防火墙工作原理

Druid的SQL防火墙通过WallFilter实现,它是Druid的一个过滤器,位于JDBC调用链中,对所有SQL语句进行拦截和检查。其核心处理流程如下:

mermaid

关键实现类位于core/src/main/java/com/alibaba/druid/wall/WallFilter.java,它通过调用WallProvider的check方法对SQL进行验证。WallProvider会根据不同数据库类型(如MySQL、Oracle)提供特定的解析和验证逻辑。

3. 基础配置:开启SQL防火墙

要启用Druid的SQL防火墙,需要在数据源配置中添加WallFilter。以下是Spring环境中的配置示例:

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    <!-- 其他基础配置 -->
    <property name="url" value="jdbc:mysql://localhost:3306/test" />
    <property name="username" value="root" />
    <property name="password" value="password" />
    
    <!-- 配置过滤器 -->
    <property name="filters" value="wall,stat" />
    
    <!-- WallFilter配置 -->
    <property name="connectionProperties" value="druid.wall.logViolation=true;druid.wall.throwException=true" />
</bean>

上述配置中,druid.wall.logViolation=true表示记录违规SQL,druid.wall.throwException=true表示对违规SQL抛出异常。这些参数定义在core/src/main/java/com/alibaba/druid/wall/WallFilter.java的configFromProperties方法中。

4. 黑白名单规则配置详解

4.1 配置方式概述

Druid提供了两种配置黑白名单的方式:

  1. 通过API动态添加规则
  2. 通过配置文件加载规则

其中,配置文件方式更适合生产环境,支持动态更新。规则文件通常放置在classpath下的特定目录中,通过WallConfig的loadConfig方法加载,如core/src/main/java/com/alibaba/druid/wall/WallConfig.java的301-311行所示:

loadResource(this.denyVariants, dir + "/deny-variant.txt");
loadResource(this.denySchemas, dir + "/deny-schema.txt");
loadResource(this.denyFunctions, dir + "/deny-function.txt");
loadResource(this.denyTables, dir + "/deny-table.txt");
loadResource(this.denyObjects, dir + "/deny-object.txt");
loadResource(this.readOnlyTables, dir + "/readonly-table.txt");

loadResource(this.permitFunctions, dir + "/permit-function.txt");
loadResource(this.permitTables, dir + "/permit-table.txt");
loadResource(this.permitSchemas, dir + "/permit-schema.txt");
loadResource(this.permitVariants, dir + "/permit-variant.txt");

4.2 表级黑白名单

4.2.1 禁止操作敏感表

创建deny-table.txt文件,添加禁止操作的表名:

user_info
order_.*

上述配置将禁止对user_info表和所有以order_开头的表执行任何操作。规则支持正则表达式,由core/src/main/java/com/alibaba/druid/util/PatternMatcher.java提供匹配能力。

4.2.2 只读表设置

创建readonly-table.txt文件,添加只读表名:

product_info
system_config

配置后,对这些表的UPDATE、DELETE、INSERT操作将被拒绝。实现逻辑见core/src/main/java/com/alibaba/druid/wall/WallConfig.java的603-605行:

public boolean isReadOnly(String tableName) {
    return this.readOnlyTables.contains(tableName);
}

4.3 函数级黑白名单

4.3.1 禁用危险函数

创建deny-function.txt文件,添加禁止使用的函数:

exec
system
xp_cmdshell

这些函数通常被用于SQL注入攻击,禁止后可以有效提高安全性。函数名匹配逻辑见core/src/main/java/com/alibaba/druid/wall/WallConfig.java的649-656行:

public boolean isDenyFunction(String name) {
    if (!functionCheck) {
        return false;
    }

    name = WallVisitorUtils.form(name);
    return this.denyFunctions.contains(name);
}
4.3.2 允许特定函数

创建permit-function.txt文件,添加允许使用的函数:

concat
substring
date_format

当配置了permit-function.txt时,只有列出的函数才被允许使用,其他函数将被拒绝。

4.4 SQL操作类型控制

除了表和函数级控制,Druid还支持对SQL操作类型进行细粒度控制。这些配置通过WallConfig的属性实现,定义在core/src/main/java/com/alibaba/druid/wall/WallConfig.java中:

private boolean selectAllow = true;
private boolean deleteAllow = true;
private boolean updateAllow = true;
private boolean insertAllow = true;
private boolean dropTableAllow = true;
private boolean alterTableAllow = true;

可以通过Spring配置文件进行修改:

<bean id="wallConfig" class="com.alibaba.druid.wall.WallConfig">
    <property name="deleteAllow" value="false" />
    <property name="dropTableAllow" value="false" />
    <property name="alterTableAllow" value="false" />
</bean>

<bean id="wallFilter" class="com.alibaba.druid.wall.WallFilter">
    <property name="config" ref="wallConfig" />
</bean>

上述配置禁止了DELETE、DROP TABLE和ALTER TABLE操作,适合只读服务场景。

5. 高级应用:动态更新规则

在生产环境中,我们通常需要在不重启应用的情况下更新规则。Druid提供了两种动态更新方式:

5.1 通过JMX动态更新

Druid支持JMX管理,可以通过JConsole或其他JMX客户端修改WallConfig的属性。相关MBean定义在core/src/main/java/com/alibaba/druid/wall/WallConfigMBean.java中。

5.2 基于配置中心的动态更新

结合配置中心(如Nacos、Apollo),可以实现规则的动态推送。以下是一个简单的实现示例:

public class DynamicWallConfigUpdater {
    private WallConfig wallConfig;
    private ConfigService configService; // 配置中心客户端
    
    public void start() {
        configService.addListener("druid.wall.deny.tables", new Listener() {
            @Override
            public void receiveConfigInfo(String configInfo) {
                wallConfig.getDenyTables().clear();
                for (String table : configInfo.split(",")) {
                    wallConfig.getDenyTables().add(table.trim());
                }
            }
        });
    }
}

6. 典型场景配置示例

6.1 电商订单系统

对于电商订单系统,通常需要:

  • 禁止删除订单数据
  • 限制对用户表的更新
  • 禁止重命名或删除表

相关配置如下:

deny-table.txt

order_info
user_info

readonly-table.txt

order_info
product_info

WallConfig配置

<property name="deleteAllow" value="false" />
<property name="dropTableAllow" value="false" />
<property name="renameTableAllow" value="false" />

6.2 报表分析系统

对于报表分析系统,通常是只读场景:

WallConfig配置

<property name="selectAllow" value="true" />
<property name="deleteAllow" value="false" />
<property name="updateAllow" value="false" />
<property name="insertAllow" value="false" />
<property name="dropTableAllow" value="false" />

同时,可以限制查询返回的记录数,防止大查询拖慢系统:

<property name="selectLimit" value="1000" />

该配置定义在core/src/main/java/com/alibaba/druid/wall/WallConfig.java的129行:private int selectLimit = -1;,当值大于0时生效。

7. 监控与审计

启用SQL防火墙后,建议同时启用Druid的监控功能,以便查看SQL执行情况和防火墙拦截记录。监控配置如下:

<servlet>
    <servlet-name>DruidStatView</servlet-name>
    <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>DruidStatView</servlet-name>
    <url-pattern>/druid/*</url-pattern>
</servlet-mapping>

访问http://localhost:8080/druid/sql.html可以查看SQL执行统计,包括被WallFilter拦截的SQL记录。

8. 总结与最佳实践

Druid的SQL防火墙提供了强大的安全防护能力,但配置不当也可能影响业务正常运行。以下是一些最佳实践:

  1. 循序渐进:先启用日志模式(druid.wall.throwException=false)观察一段时间,再开启拦截模式
  2. 最小权限原则:只允许必要的表、函数和操作类型
  3. 定期审计:结合Druid监控定期审计SQL执行情况,优化规则配置
  4. 动态更新:生产环境使用动态更新机制,避免重启应用
  5. 结合其他安全措施:SQL防火墙只是安全防护的一环,还需结合网络隔离、权限控制等措施

通过合理配置Druid的SQL防火墙,你可以有效防范SQL注入攻击和误操作,提高系统的安全性和稳定性。完整的配置示例和更多高级功能,请参考官方文档doc/ha-datasource.md

【免费下载链接】druid 阿里云计算平台DataWorks(https://help.aliyun.com/document_detail/137663.html) 团队出品,为监控而生的数据库连接池 【免费下载链接】druid 项目地址: https://gitcode.com/gh_mirrors/druid/druid

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值