springboot2 druid加密 多数据源druid加密

前言

出于对项目的安全考虑,经常需要对数据库的密码进行加密,本文我们将带大家从源码角度进行分析各个配置的作用,使用druid的自带工具对数据进行加密。

加密代码

    public static void main(String[] args) {
        String password = "test";
        String[] arguments = new String[]{password};
        try {
            ConfigTools.main(arguments);
        } catch (Exception e) {
            log.info("生成密文失败,异常信息:{}", e);
        }
    }

运行后可以得到加密后的密码

  1. privateKey:MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAlxFiZMO5fD1kOIc/B7R+dUsJ5EsxCXqGAC3SpiAHm/397LgpKi613kPRkzidA7olwT34gkXX7HNQnvYBngRyaQIDAQABAkAxRDUfgYkzUF4n5UuT+rQnEnLGZhM28SNUWZ1SGi4BHAHfp5pbyMEzDD+84hc5r5Euk7HEGkuUt2HNRPq4cpERAiEA4BRm3kfpuVfqSjij3zJ7UdiE54oWeAnG2XiG1hJvdmUCIQCslm8wUxksDgcvNUjQN8Pp9VZCBUzInlppanVZyUB5tQIgUSER3YjL5n8eJKE9M6JjY86wz+P/Hpbrl/E7YGZsVMECIQCPAOtKkGBYJ5t+W1lk5gAYeGertraDuOpTVJm99srMzQIgHX7T20MexhBxokUIQiXuaB8Z9CflpQY7StP/cedt9Wk=
    publicKey:MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJcRYmTDuXw9ZDiHPwe0fnVLCeRLMQl6hgAt0qYgB5v9/ey4KSoutd5D0ZM4nQO6JcE9+IJF1+xzUJ72AZ4EcmkCAwEAAQ==
    password:WCACUuMVJmu01PWDOUphY5Ms7CUhG80WHJi8KqyJpIrQsVEyX5prwedps2YbkJaScUGPApuX6ZiFawfWxaDDyw==

可以看出druid默认的工具类是采用非对称加密的方式进行加密的

其中private是自动生成的随机私密,我们需要关注的值有“publicKey”跟"password",需要保存好着两个值。

配置加密

  • 首先我们需要在配置文件中开启加密

从源码中分析

com.alibaba.druid.pool.DruidDataSource#init方法中,遍历了我们所有的filter。

for (Filter filter : filters) {
   filter.init(this);
}

 为了让揭秘生效,我们需要配置解密的拦截器

spring:
  datasource:
    druid:
      filters: config
  • 开启过滤器

这点比较重要,开启后表示druid加载时会走过滤器com.alibaba.druid.filter.config.ConfigFilter,改过滤器将对加密密码进行解密,

    public boolean isDecrypt(Properties connectionProperties, Properties configFileProperties) {
         // 读取CONFIG_DECRYPT配置,看是否进行加密,只有设置为true才会对数据库进行揭秘
        String decrypterId = connectionProperties.getProperty(CONFIG_DECRYPT);
        if (decrypterId == null || decrypterId.length() == 0) {
            if (configFileProperties != null) {
                decrypterId = configFileProperties.getProperty(CONFIG_DECRYPT);
            }
        }

        if (decrypterId == null || decrypterId.length() == 0) {
            decrypterId = System.getProperty(SYS_PROP_CONFIG_DECRYPT);
        }

        return Boolean.valueOf(decrypterId);
    }

从上面源码中可以看出,我们还需要配置一个CONFIG_DECRYPT,设置为true。

spring:
  datasource:
    druid:
      connect-properties:
        config.decrypt: true

此时会走解密流程,此时会调用com.alibaba.druid.filter.config.ConfigFilter#decrypt方法。

  • 公钥跟密码配置

解读decrypt的方法可以看出,我们还需要配置解密的公钥配置

spring:
  datasource:
    druid:
        config.decrypt.key: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALwTQSulMoXLHIiwpXY7V1LdLzAusZ3zPOdEHD0fSn6Nc51UAHjRli+pxgIt6M899mXhZ9k2aGzE5weuf9uNTfcCAwEAAQ==

这个公钥就是上面我们main生成的publicKey。配置好公钥后,进行我们的密码解密操作。

此时会读取我们配置的加密后的密码

spring:
  datasource:
    druid:
      password: JjtSWRv9rPnksKAvLZwFuxkpYxbyBxJKFhe5aZGo90BS7HbbQhtEvGCEt75aqDYcyzkkvOfYSxQ5sFKoURWRBQ==

这个password就是我们上面运行main方法生成的加密密码。

补充一点,对于动态数据源的配置:

由于项目中有的用的是多数据源配置:

首先应用baomidou的多数据源maven

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.5.0</version>
</dependency>

对于多数据源我们需要关注

com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration类,该类加载了多数据源的配置com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties

从配置中,我们可以看出有专门的druid的一个节点

/**
     * Druid全局参数配置
     */
    @NestedConfigurationProperty
    private DruidConfig druid = new DruidConfig();

查看com.baomidou.dynamic.datasource.spring.boot.autoconfigure.druid.DruidConfig#toProperties中源码:

// 通过判断publicKey值来判断是否加过滤器
if (publicKey != null && publicKey.length() > 0 && !filters.contains(CONFIG_STR)) {
    filters += "," + CONFIG_STR;
}
properties.setProperty(FILTERS, filters);

可以看出,我们需要配置一个publicKey,这个key就是我们上面main生成的公钥。

继续阅读下面的代码,会发现利用pulicKey还做了以下事情

Properties connectProperties = connectionProperties == null ? g.getConnectionProperties() : connectionProperties;

// 自动拼接config.decrypt跟config.decrypt.key
if (publicKey != null && publicKey.length() > 0) {
    if (connectProperties == null) {
        connectProperties = new Properties();
    }
    connectProperties.setProperty("config.decrypt", Boolean.TRUE.toString());
    connectProperties.setProperty("config.decrypt.key", publicKey);
}
this.connectionProperties = connectProperties;

从上面的代码中,可以看出,自动帮我们配置了config.decrypt跟config.decrypt.key,所以我们不需要跟配置druid一样去配置这两个属性,默认开启解密。

最后

此时我们的密码加密就完成了。

总结一下,需要对数据库数据库进行加密,我们需要进行配置四个个地方。如下

spring:
  datasource:
    druid:
      filters: config #配置过滤器
      password: ${password} #加密的密钥
      connect-properties:
        config.decrypt: true #设置为true,开启解密
        config.decrypt.key: ${publicKey} #解密的公钥

对于使用的baomidou的多数据源,我们需要配置两个地方,如下:

spring:
  datasource:
    dynamic:
      enabled: true
      primary: master
      datasource:
        master:
          type: com.alibaba.druid.pool.DruidDataSource
          url: jdbc:mysql://url/dbname?useUnicode=true&characterEncoding=utf-8&
          username: test
          password: ${passord} #加密的密码
          driver-class-name: com.mysql.jdbc.Driver
          druid:
            filters: config #开启过滤器
            publicKey: ${publicKey} #生成的公钥

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是一个示例代码,使用Spring Boot和Druid连接MySQL多数据,并且对数据库密码进行了加解密: 1. 添加依赖 在 pom.xml 文件中添加以下依赖: ``` <dependencies> <!-- Spring Boot Starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!-- Spring Boot Starter JDBC --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!-- Druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.23</version> </dependency> <!-- Jasypt --> <dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> <version>3.0.3</version> </dependency> </dependencies> ``` 2. 配置数据 在 application.yml 文件中添加以下配置: ``` # 默认数据 spring.datasource.url=jdbc:mysql://localhost:3306/db1 spring.datasource.username=root spring.datasource.password=ENC(加密后的密码) spring.datasource.driver-class-name=com.mysql.jdbc.Driver # 第二个数据 datasource2.url=jdbc:mysql://localhost:3306/db2 datasource2.username=root datasource2.password=ENC(加密后的密码) datasource2.driver-class-name=com.mysql.jdbc.Driver ``` 其中,密码字段使用 Jasypt 进行加密,格式为 `ENC(加密后的密码)`。 3. 配置Druid数据 在配置文件中添加以下配置: ``` # Druid数据配置 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource # 配置第一个数据 spring.datasource.druid.initial-size=5 spring.datasource.druid.min-idle=5 spring.datasource.druid.max-active=20 spring.datasource.druid.max-wait=60000 spring.datasource.druid.time-between-eviction-runs-millis=60000 spring.datasource.druid.min-evictable-idle-time-millis=300000 spring.datasource.druid.validation-query=SELECT 1 FROM DUAL spring.datasource.druid.test-while-idle=true spring.datasource.druid.test-on-borrow=false spring.datasource.druid.test-on-return=false spring.datasource.druid.pool-prepared-statements=true spring.datasource.druid.max-pool-prepared-statement-per-connection-size=20 spring.datasource.druid.filters=stat,wall,log4j # 配置第二个数据 datasource2.druid.initial-size=5 datasource2.druid.min-idle=5 datasource2.druid.max-active=20 datasource2.druid.max-wait=60000 datasource2.druid.time-between-eviction-runs-millis=60000 datasource2.druid.min-evictable-idle-time-millis=300000 datasource2.druid.validation-query=SELECT 1 FROM DUAL datasource2.druid.test-while-idle=true datasource2.druid.test-on-borrow=false datasource2.druid.test-on-return=false datasource2.druid.pool-prepared-statements=true datasource2.druid.max-pool-prepared-statement-per-connection-size=20 datasource2.druid.filters=stat,wall,log4j ``` 4. 配置数据连接池 在配置类中添加以下代码: ``` @Configuration public class DataSourceConfig { @Bean(name = "dataSource") @Primary @ConfigurationProperties(prefix = "spring.datasource") public DruidDataSource dataSource() { return DruidDataSourceBuilder.create().build(); } @Bean(name = "dataSource2") @ConfigurationProperties(prefix = "datasource2") public DruidDataSource dataSource2() { return DruidDataSourceBuilder.create().build(); } @Bean(name = "dataSource1TransactionManager") @Primary public DataSourceTransactionManager dataSourceTransactionManager() { return new DataSourceTransactionManager(dataSource()); } @Bean(name = "dataSource2TransactionManager") public DataSourceTransactionManager dataSource2TransactionManager() { return new DataSourceTransactionManager(dataSource2()); } @Bean(name = "dataSource1SqlSessionFactory") @Primary public SqlSessionFactory dataSourceSqlSessionFactory(@Qualifier("dataSource") DruidDataSource dataSource) throws Exception { final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml")); return sessionFactory.getObject(); } @Bean(name = "dataSource2SqlSessionFactory") public SqlSessionFactory dataSource2SqlSessionFactory(@Qualifier("dataSource2") DruidDataSource dataSource) throws Exception { final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper2/*.xml")); return sessionFactory.getObject(); } } ``` 其中,`@Primary` 注解表示默认数据,`@ConfigurationProperties` 注解表示从配置文件中读取配置。 5. 配置MyBatis 在 `application.yml` 文件中添加以下配置: ``` mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.entity ``` 6. 编写DAO和Mapper 在 `com.example.dao` 包中编写DAO和Mapper,例如: ``` @Repository public interface UserDAO { @Select("SELECT * FROM user") @Results(id = "userResultMap", value = { @Result(property = "id", column = "id", id = true), @Result(property = "name", column = "name"), @Result(property = "email", column = "email"), @Result(property = "phone", column = "phone"), @Result(property = "createTime", column = "create_time") }) List<User> list(); } @Mapper public interface UserMapper { @Select("SELECT * FROM user") @ResultMap("userResultMap") List<User> list(); } ``` 7. 使用数据 在Service中使用数据,例如: ``` @Service public class UserService { @Autowired private UserDAO userDAO; @Autowired private UserMapper userMapper; @Transactional(transactionManager = "dataSource1TransactionManager") public List<User> list() { return userDAO.list(); } @Transactional(transactionManager = "dataSource2TransactionManager") public List<User> list2() { return userMapper.list(); } } ``` 其中,`@Transactional` 注解表示开启事务,`transactionManager` 参数指定使用的数据

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值