SpringBoot中Druid加密数据连接信息
现在SpringBoot做web开发经常用到Druid
做数据源,但数据库连接的相关信息比如username
,password
等关键信息有时候直接写在配置文件中,容易暴露,虽然也可以用指定外部配置文件的方式避免生产环境敏感数据泄露,但其实Druid
还内置了数据库加密功能。
1. druid依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.22</version>
</dependency>
2. 生成加密后的连接信息
import com.alibaba.druid.filter.config.ConfigTools;
@Test
public void testEncrypt() throws Exception {
String password = "123456";
ConfigTools.main(new String[]{password});
}
输出结果:
privateKey:MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAoWVj3PyjACvyzeOkPq79TdkcvmcHeOw/Vm7eUPC7SRrJ8wFkjCFEWsxInBFO7HAe0cjTNOI7P39IA45DmxCntwIDAQABAkEAgwEVii7W8DC8KTr5+pd3rFTq6/IdMp4w2yuq8PA2VSNC4QbVBfBSLBorZLvwiWrokiC44zULrsb8HzdcMKmPIQIhAP9n1ammYQxKryrr3KAD/sAk9JYPup5ZZA7ZNTinDANtAiEAocWL6QjzrCye5iOq/CZkAEUu48n6v1s/EkBfL65nPTMCIFCDt0OIA8gQMzBgsmhvWfvQqpoz0yzgGT7lEnYNkyfxAiADqH3zdRpdiFzHg4L4VL3qK6ZVzFl5Pkz80qvUXjNDdQIgGDdsK68goZG5IHdJTVTwW5S3Z2XcGFDI7gQ20rskBIY=
publicKey:MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKFlY9z8owAr8s3jpD6u/U3ZHL5nB3jsP1Zu3lDwu0kayfMBZIwhRFrMSJwRTuxwHtHI0zTiOz9/SAOOQ5sQp7cCAwEAAQ==
password:jbj2tfygiIdcrA8NaxBd8HL/967fN7QSxDPXxqG1diezq3g0PnWrpyYdv0OxM1Ra/RyZaPg3Ik5cr8HOsMFXvg==
privateKey
==> 私钥(没用到)
publicKey
==> 公钥
password
==> 密文
3. 修改连接配置
先看常规版明文连接配置信息:
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test
username: root
password: 123456
改成加密连接配置信息:
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test
username: root
# password 改成生成的 password(密文)
password: jbj2tfygiIdcrA8NaxBd8HL/967fN7QSxDPXxqG1diezq3g0PnWrpyYdv0OxM1Ra/RyZaPg3Ik5cr8HOsMFXvg==
# 新增以下内容
filters: config
connect-properties:
config.decrypt: true
# config.decrypt.key 对应生成的 publicKey(公钥)
config.decrypt.key: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKFlY9z8owAr8s3jpD6u/U3ZHL5nB3jsP1Zu3lDwu0kayfMBZIwhRFrMSJwRTuxwHtHI0zTiOz9/SAOOQ5sQp7cCAwEAAQ==
这个时候已经可以正常使用了,但还没有做到安全!
因为这个“锁”跟“钥匙”都放在一个地方,并不安全,正确操作方式是将password
和config.decrypt.key
配置成变量,在生产环境通过环境变量的方式传递进去即可,因此最终修改成如下形式:
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test
username: root
password: ${db.password}
filters: config
connect-properties:
config.decrypt: true
config.decrypt.key: ${db.publicKey}
在生产环境启动时,传递变量进去,例如:
java -jar xxx.jar --db.password=密文 --db.publicKey=公钥
一般SpringBoot项目的配置文件都会区分多个环境,比如dev
、prod
等,为了便于开发,dev
环境就可以直接明文,而prod
环境就启用连接加密即可
4. 密码的还原
由于Druid
的拦截器会在SpringBoot项目启动时自动将密文跟公钥还原成真实密码,因此配置完加密后无需再改别处。但我们可以直接通过代码的方式,基于密文跟公钥还原真实密码,依旧是使用ConfigTools
:
import com.alibaba.druid.filter.config.ConfigTools;
@Test
public void testDecrypt() throws Exception {
String publicKey = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAIF+TFbqgRWPF5ojWHmqMkyzDS08BDxe7aSB8tUaAaZReF9QJNU6MT+LyAhTQe71NXPwwP/9FpfXWJyxpYjQTe0CAwEAAQ==";
String password = "VqhrppUJ7BeLAnO6Juf1I0u6rDpXFvSV4/anW8qxI5QF9ip1ClPdvIcX4BS5sUz5wvtBygx4mAYjOh0CajEgrQ==";
String result = ConfigTools.decrypt(publicKey, password);
System.out.println("result:" + result);
}
结果:
result:123456
还原正常