如今的开发习惯,不管是公司的项目仍是我的的项目,都会选择将源码上传到 Git 服务器(GitHub、Gitee 或是自建服务器),但只要将源码提交到公网服务器就会存在源码泄漏的风险,而数据库配置信息做为源码的一部分,一旦出现源码泄漏,那么数据库中的全部数据都会公之于众,其产生的不良后果没法预期(好比某某酒店的信息)。java
因而为了不这种问题的产生,咱们至少要对数据库的密码进行加密操做,这样即便获得了源码,也不会形成数据的泄露,也算保住了最后一块遮羞布。mysql
对于 Java 项目来讲,要想快速实现数据库的加密,最简单可行的方案就是使用阿里巴巴提供的 Druid 来实现加密。git
Druid(中文译为“德鲁伊”)是阿里巴巴开源的一款 Java 语言中最好的数据库链接池。Druid 提供了强大的监控和扩展功能,固然也包含了数据库的加密功能。github
Druid 开源地址:https://github.com/alibaba/druid/spring
对于本文来讲,咱们重点来看它的第 3 个特性,也就是使用 Druid 来实现数据库密码加密。sql
在没有进行密码加密以前,项目的交互流程是这样的:
数据库
在使用了密码加密以后,项目的交互流程就变成了这样:
编程
本示例运行环境:安全
Spring Boot 2.4.3服务器
MySQL 5.7
Java 1.8
Idea 2020.1.3
Maven 项目:
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.5</version> </dependency>
Gradle 项目:
compile 'com.alibaba:druid-spring-boot-starter:1.2.5'
获取 Druid 最新版本:https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter
Druid 添加完成以后就能够借助 Druid 中提供的 ConfigTools
类来加密密码了,实现代码以下:
import com.alibaba.druid.filter.config.ConfigTools; class MyTests { public static void main(String[] args) throws Exception { // 须要加密的明文命名 String password = "youPassword"; // 【注意:这里要改成你本身的密码】 // 调用 druid 生成私钥、公钥、密文 ConfigTools.main(new String[]{password}); } }
以上代码执行的结果以下:
privateKey:MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEApOjcMWSDzJiKVGmtcBBoQPtM9tVW2H2cnS6xZK7NrbzQXYWLQD2zefIrrx9vMvqRIHEqkmAHTuUcUXHgCxu0cwIDAQABAkAlqo5ItdWo0Jqf5zdXJlg5p2yP4HCiqCYyfKzF+2s9KEmgWZJWTctZDsgQ0iYUohORR59I+J4nabhel1x5/INpAiEA6jwSyFqMUPOh1XlrzNFek+RthOQ5n4+ALPo+vULayO0CIQC0O7JM9sIq+tg+jCGv+ypk6vbuRKY9m5W2rSRXapGm3wIgRHul3jAjIDPrF/f1HaAFL+Y0Yws7Ebyp8/yCRWF7iA0CIALbe20q8FMcHPeI4zPWCIsHCpkmb3hEkjAOOKhGIT8DAiAqiUuz92NqKeyjmOfons1ka65EzVwA3NDhZ6+IQcnuig==
publicKey:MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKTo3DFkg8yYilRprXAQaED7TPbVVth9nJ0usWSuza280F2Fi0A9s3nyK68fbzL6kSBxKpJgB07lHFFx4AsbtHMCAwEAAQ==
password:IMgKm27bOHok3/+5aDL4jGBoVVZkpicbbM6pIXQppi3dI7h3jngSAqhqwqYnfuYpyVJ0k++q9xWWnHtd6sAWnQ==
从上述结果能够看出,使用 ConfigTools
类会生成 3 部分的内容:
PS:要实现数据库的加密,主要使用的是 publicKey(公钥)和 password(密文),这就把明文转换成密文了。
完成了以上操做以后,只须要将上一步生成的公钥和密文添加到项目的配置文件 application.yml(或application.xml)中就实现了加密操做了,具体配置信息以下:
spring: # MySQL 配置 datasource: driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource druid: url: jdbc:mysql://127.0.0.1:3306/testdb?serverTimezone=Asia/Shanghai&characterEncoding=UTF-8&useSSL=false username: root password: IMgKm27bOHok3/+5aDL4jGBoVVZkpicbbM6pIXQppi3dI7h3jngSAqhqwqYnfuYpyVJ0k++q9xWWnHtd6sAWnQ== # encrypt config filters: config connect-properties: config.decrypt: true config.decrypt.key: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKTo3DFkg8yYilRprXAQaED7TPbVVth9nJ0usWSuza280F2Fi0A9s3nyK68fbzL6kSBxKpJgB07lHFFx4AsbtHMCAwEAAQ==
其中 password 对应的是上一步生成的 password(密文),而 config.decrypt.key 对应的是上一步生成的 publicKey(公钥),以下图所示:
这里提供一个原始的配置文件,以便和加密后的配置文件进行比对:
通过前面 3 步的配置以后,咱们的程序就能够正常运行了,但这远没有结束!
在第 3 步配置时,咱们将密文和公钥都写入配置文件,这就会形成当有人拿到密文和公钥以后,就可使用 Druid 将加密的密码还原出来了,这就比如一把插着钥匙的锁是极不安全的。
所以咱们正确的使用姿式:是将公钥找一个安全的地方保存起来,每次在项目启动时动态的将公钥设置到项目中,这样就能够有效的保证密码的安全了。
接下来咱们将 Spring Boot 的公钥设置为配置项,在项目运行时再替换为具体的值,最终的安全配置信息以下:
spring: # MySQL 配置 datasource: driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource druid: url: jdbc:mysql://127.0.0.1:3306/testdb?serverTimezone=Asia/Shanghai&characterEncoding=UTF-8&useSSL=false username: root password: IMgKm27bOHok3/+5aDL4jGBoVVZkpicbbM6pIXQppi3dI7h3jngSAqhqwqYnfuYpyVJ0k++q9xWWnHtd6sAWnQ== # encrypt config filters: config connect-properties: config.decrypt: true config.decrypt.key: ${spring.datasource.druid.publickey}
能够看出公钥被修改为“${spring.datasource.druid.publickey}”了,这就至关于使用占位符先把坑给占上,等项目启动时再更换上具体的值。
PS:“spring.datasource.druid.publickey”并不是是固定不可变的 key,此 key 值用户可自行定义。
开发环境只须要在 Idea 的启动参数中配置公钥的值便可,以下图所示:
当咱们输入正确的公钥值时程序能够正常运行,当输入一个错误的公钥值时就会提示解码失败,以下图所示:
生产环境在启动 jar 包时只须要动态设置公钥的值便可,参考如下命令:
java -jar xxx.jar --spring.datasource.druid.publickey=你的公钥
通过上述步骤以后,咱们就完成 MySQL 密码的加密了,这样当 Spring Boot 项目启动时,Druid 的拦截器会使用密文和公钥将密码还原成真实的密码以供项目使用,固然这一切都无需人工干预(无需编写任何代码),Druid 已经帮我封装好了,咱们只须要经过以上配置便可。
什么?你想知道 Druid 是如何经过密文和公钥还原出真实的密码的?
没问题,知足你,其实 ConfigTools
类中已经提供了相应实现,代码以下:
// 密文 String password = "VwH1mu2IUpqjfKTd+gSikiZgJTi+3Y5zFIFRfxYnH1UqHzm1K8TIHnMaV3TErBaGsVEaGV0e63pb0Ys3Wdm7Kg=="; // 公钥 String publicKey = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALWIEp19IM04sB+vQXnEOH9gFNFdL5TFGSEhORgHj4MnfTfBSNaOoSgCaM8BOpjiHmwuEb7LpvmXI1x/ymUvNzECAwEAAQ=="; // 还原成真实的密码 String result = ConfigTools.decrypt(publicKey, password); System.out.println("最终结果:" + result);
本文咱们使用阿里巴巴开源的 Druid 实现了 MySQL 的密码加密,Druid 的加密过程很是方便,无需编写任何代码,只须要添加 Druid 依赖,再经过 Druid 的工具类生成密文,最后将密文配置到 application.yml 文件便可。项目在运行时会经过拦截器将密文转换成真正的密码,从而实现了 MySQL 密码的加密和解码的过程。
原创不易,若是以为本文对你有帮助,请点个赞再走呗。
关注公众号「Java中文社群」查看更多 Druid 干货。