druid我使用的版本是1.1.10,数据源postgresql
目标是通过application.yml自动装配DruidDataSource并完成数据库密码的自动解密
DruidDatasource初始化代码如下
@Bean(name = "druidDataSource", autowire = Autowire.NO, initMethod = "init")
@Primary
@ConfigurationProperties(prefix="spring.datasource")
public DruidDataSource dataSource() {
DruidDataSource druidDataSource = new DruidDataSource();
return druidDataSource;
}
在spirng配置文件application.yml(这里的配置是不完整的,详见下面)
spring:
datasource:
url: jdbc:postgresql://xx
username: postgres
password: NMbo1NhUx5TXHK(加密后的密码)
driver-class-name: org.postgresql.Driver
removeAbandoned: true
removeAbandonedTimeout: 280
这里密码是使用druid自带的com.alibaba.druid.filter.config.ConfigTools类生成的加密后的密码,其实也是用的rsa加密,生成代码如下
import com.alibaba.druid.filter.config.ConfigTools;
public class Test {
public static void main(String[] args) throws Exception{
String password = "123456";
System.out.println("明文密码: " + password);
String[] keyPair = ConfigTools.genKeyPair(512);
//私钥
String privateKey = keyPair[0];
//公钥
String publicKey = keyPair[1];
//用私钥加密后的密文
password = ConfigTools.encrypt(privateKey, password);
System.out.println("privateKey:" + privateKey);
System.out.println("publicKey:" + publicKey);
System.out.println("password:" + password);
String decryptPassword = ConfigTools.decrypt(publicKey, password);
System.out.println("解密后:" + decryptPassword);
}
}
那么如何让druid自动解密 密文的密码呢?看了网上很多写法,是这样写的application.yml的
spring:
datasource:
driver-class-name: xx
type: com.alibaba.druid.pool.DruidDataSource(这里其实不能加这行)
url: xx
username: root
password: xxx
druid:
connect-properties:(这样写不能生效)
config.decrypt: true
config.decrypt.key: # 生成的公钥 publicKey
但是实际上我在这样配置之后,spring生成的DruidDataSource中,虽然有url,username等,但是connectProperties并没有写上去
运行时提示密码错误,调试后发现connectProperties为null
在查看调试之后发现,springboot在反射生成属性时,调用的是DruidAbstractDataSource中的一系列set方法
其中在setPassword下面就是setConnectionProperties
因此想到不能写成spring.datasource.druid.connect-properties,要直接写成spring.datasource.connect-properties
(不清楚是不是因为druid或者spirngboot版本的问题)
然后发现druid的源码ConfigFilter.java的注释中提到了自动解密的写法,其中解密过程就在这个类里面
package com.alibaba.druid.filter.config;
/**
* <pre>
* 这个类主要是负责两个事情, 解密, 和下载远程的配置文件
* [解密]
*
* DruidDataSource dataSource = new DruidDataSource();
* //dataSource.setXXX 其他设置
* //下面两步很重要
* //启用config filter
* dataSource.setFilters("config");
* //使用RSA解密(使用默认密钥)
* dataSource.setConnectionPropertise("config.decrypt=true");
* dataSource.setPassword("加密的密文");
然后根据ConfigFilter源代码的解析过程,修改后的application.yml的配置
datasource:
url: jdbc:postgresql://xx
username: postgres
driver-class-name: org.postgresql.Driver
password: NMbo1NhUx5T
connectProperties: config.decrypt=true
connectProperties.config.decrypt.key: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAIx8/+Lz+yRtQA1wuQWbPOfLRe0zeHRiAXafknLYQlvl74Qqqi4Cj6dqe4c+PInmfo68Qz7zhHGfDPYLKw09Gn8CAwEAAQ==
filters: config
这样配置之后就可以正常连接数据库了
如果有datasource的配置不对,强烈建议去看一下druid的ConfigFilter的源代码是如何解析使用配置的