現在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
還原正常