Druid 内置工具加密数据库密码
概述
数据库密码写在配置文件里,但凡项目代码提交到 Git,密码就跟着源码一起暴露了。即便是私有仓库,任何一个有权限拉代码的人都能看到。而且运维交接、新人入职……知道密码的人越多,泄露风险越大。
Druid 连接池内置了一套加密工具,可以让你在配置文件里只写密文,应用启动时 Druid 自动解密后建立连接。
最终效果:配置文件的password从Hliu1026.变成eXGMzA/PwhC7/l2tThoxCVyD9v9Hd0po2R2GYfwzTu5iSlWlY/tgaOzJBm/HYxVd...,应用启动后照样正常连接数据库。
第一步:生成密钥对并加密密码
Druid 提供了ConfigTools工具类,内嵌在druid的 jar 包里,不需要额外依赖。
写个单元测试跑一下:
@Test@SneakyThrowsvoidtestEncodePassword(){// 你的明文密码Stringpassword="Hliu1026.";// 生成密钥对(512 位 RSA),返回 [私钥, 公钥]String[]arr=ConfigTools.genKeyPair(512);StringprivateKey=arr[0];// 私钥——你保管好StringpublicKey=arr[1];// 公钥——放到配置文件里// 用私钥加密密码StringencodedPassword=ConfigTools.encrypt(arr[0],password);log.info("privateKey: {}",privateKey);log.info("publicKey: {}",publicKey);log.info("encodedPassword: {}",encodedPassword);}跑完之后控制台输出三样东西:
| 产出物 | 用途 | 放哪里 |
|---|---|---|
| 私钥(privateKey) | 用来加密密码。以后改密码、新增数据库密码都拿它来加密 | 你自己保管好,不要进 Git |
| 公钥(publicKey) | Druid 启动时用来自动解密 | 写到配置文件里 |
| 密文(encodedPassword) | 代替明文密码 | 写到配置文件的password字段 |
ConfigTools.genKeyPair(512)的参数512是 RSA 密钥长度,对密码加密够用了。
第二步:替换配置文件
把生成的公钥和密文填到application.yml对应位置:
spring:datasource:url:jdbc:mysql://127.0.0.1:3306/idle_store?useUnicode=true&characterEncoding=utf-8&...username:root# 原来:password: Hliu1026.# 现在:换成一串乱码password:eXGMzA/PwhC7/l2tThoxCVyD9v9Hd0po2R2GYfwzTu5iSlWlY/tgaOzJBm/HYxVd8zJOH4PSIDVV36mzqFSITg==type:com.alibaba.druid.pool.DruidDataSourcedruid:# ... 其他配置保持不变 ...# 告诉 Druid:密码是加密的,拿这把公钥去解密connection-properties:config.decrypt=true;config.decrypt.key=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKLulduxIyZLzneseuSanUn0+Go2IvX8lZX87HHyWsZPqnfpQoIA8XB6vZtXOk82LeCP+XJd89OQs5C+r4yYzZcCAwEAAQ==connection-properties里两项配置的含义:
| 配置项 | 含义 |
|---|---|
config.decrypt=true | 告诉 Druid:密码字段是加密的,需要先解密再用 |
config.decrypt.key=<公钥> | 用这把公钥来解密 |
至此就完成了。应用启动时,Druid 自动用公钥把密文解密成明文,建立数据库连接。
完整配置示例
spring:datasource:driver-class-name:com.mysql.cj.jdbc.Driverurl:jdbc:mysql://127.0.0.1:3306/idle_store?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghaiusername:rootpassword:eXGMzA/PwhC7/l2tThoxCVyD9v9Hd0po2R2GYfwzTu5iSlWlY/tgaOzJBm/HYxVd8zJOH4PSIDVV36mzqFSITg==type:com.alibaba.druid.pool.DruidDataSourcedruid:initial-size:5min-idle:5max-active:20max-wait:60000test-while-idle:truetime-between-eviction-runs-millis:60000min-evictable-idle-time-millis:300000max-evictable-idle-time-millis:900000validation-query:SELECT 1 FROM DUALstat-view-servlet:enabled:trueurl-pattern:/druid/*login-username:adminlogin-password:adminfilter:stat:enabled:truelog-slow-sql:trueslow-sql-millis:2000merge-sql:true# 就这一行是新增的,其他都是原来就有的connection-properties:config.decrypt=true;config.decrypt.key=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKLulduxIyZLzneseuSanUn0+Go2IvX8lZX87HHyWsZPqnfpQoIA8XB6vZtXOk82LeCP+XJd89OQs5C+r4yYzZcCAwEAAQ==加密到底在"防"什么?
有人可能会问:公钥和密文都在配置文件里,那拿到配置的人不一样能连上数据库吗?
是的,光靠密文 + 公钥,拿着这份配置去启动应用,Druid 会自动解密,数据库照连不误。所以这个加密防的不是"别人拿到配置文件后去连库"。
它防的是密码扩散。明文密码被人看到,他就知道了真实密码,可以到处去试。密文就不一样了——别人看到 eXGMzA/PwhC7… 这串乱码,他不知道明文是啥。退一步说,他真想连上数据库,光有密文还不够,还得拿到数据库地址、用户名、连接权限(白名单)、账号权限等等。密码是整个链条里最关键的一环,把它藏住了,泄露的风险就砍掉了大半。