Druid 内置工具加密数据库密码

概述

数据库密码写在配置文件里,但凡项目代码提交到 Git,密码就跟着源码一起暴露了。即便是私有仓库,任何一个有权限拉代码的人都能看到。而且运维交接、新人入职……知道密码的人越多,泄露风险越大。

Druid 连接池内置了一套加密工具,可以让你在配置文件里只写密文,应用启动时 Druid 自动解密后建立连接。

最终效果:配置文件的 passwordHliu1026. 变成 eXGMzA/PwhC7/l2tThoxCVyD9v9Hd0po2R2GYfwzTu5iSlWlY/tgaOzJBm/HYxVd...,应用启动后照样正常连接数据库。


第一步:生成密钥对并加密密码

Druid 提供了 ConfigTools 工具类,内嵌在 druid 的 jar 包里,不需要额外依赖。

写个单元测试跑一下:

@Test
@SneakyThrows
void testEncodePassword() {
    // 你的明文密码
    String password = "Hliu1026.";

    // 生成密钥对(512 位 RSA),返回 [私钥, 公钥]
    String[] arr = ConfigTools.genKeyPair(512);

    String privateKey = arr[0];  // 私钥——你保管好
    String publicKey = arr[1];   // 公钥——放到配置文件里

    // 用私钥加密密码
    String encodedPassword = 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.DruidDataSource
    druid:
      # ... 其他配置保持不变 ...
      # 告诉 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.Driver
    url: jdbc:mysql://127.0.0.1:3306/idle_store?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: eXGMzA/PwhC7/l2tThoxCVyD9v9Hd0po2R2GYfwzTu5iSlWlY/tgaOzJBm/HYxVd8zJOH4PSIDVV36mzqFSITg==
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      initial-size: 5
      min-idle: 5
      max-active: 20
      max-wait: 60000
      test-while-idle: true
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
      max-evictable-idle-time-millis: 900000
      validation-query: SELECT 1 FROM DUAL
      stat-view-servlet:
        enabled: true
        url-pattern: /druid/*
        login-username: admin
        login-password: admin
      filter:
        stat:
          enabled: true
          log-slow-sql: true
          slow-sql-millis: 2000
          merge-sql: true
      # 就这一行是新增的,其他都是原来就有的
      connection-properties: config.decrypt=true;config.decrypt.key=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKLulduxIyZLzneseuSanUn0+Go2IvX8lZX87HHyWsZPqnfpQoIA8XB6vZtXOk82LeCP+XJd89OQs5C+r4yYzZcCAwEAAQ==

加密到底在"防"什么?

有人可能会问:公钥和密文都在配置文件里,那拿到配置的人不一样能连上数据库吗?

是的,光靠密文 + 公钥,拿着这份配置去启动应用,Druid 会自动解密,数据库照连不误。所以这个加密防的不是"别人拿到配置文件后去连库"。

它防的是密码扩散。明文密码被人看到,他就知道了真实密码,可以到处去试。密文就不一样了——别人看到 eXGMzA/PwhC7… 这串乱码,他不知道明文是啥。退一步说,他真想连上数据库,光有密文还不够,还得拿到数据库地址、用户名、连接权限(白名单)、账号权限等等。密码是整个链条里最关键的一环,把它藏住了,泄露的风险就砍掉了大半。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐