chat

详细介绍一下 druid password 的加解密

Druid 提供了对数据库连接密码的加密和解密功能,以提高安全性,防止数据库密码在配置文件中以明文形式暴露。

这种加密方式是通过 Druid 的内置功能实现的。

一、加密密码

Druid 使用 DruidPasswordCallback 进行密码的加密和解密。加密密码的步骤如下:

  1. 生成密钥文件

    首先,你需要生成一个用于加密和解密的密钥文件。这个文件会用来加密数据库密码。

      [shell]
    1
    java -cp druid-x.x.x.jar com.alibaba.druid.filter.config.ConfigTools <your_password>

    运行上述命令后,输出结果会包括三个部分:

    • privateKey: 私钥
    • publicKey: 公钥
    • password: 加密后的密码

    例如:

      [shell]
    1
    2
    3
    privateKey: MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMl1ryLz9ZfLbUI... publicKey: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL9sBkwHY... password: Dv7cWQk1jVc7K/zNFFN2asU5Cn...
  2. 保存公钥和加密密码

    • 将公钥保存到一个文件中,比如 publicKey.txt
    • 在配置文件中使用加密后的密码。

二、配置 Druid 使用加密密码

  1. 编写 DruidPasswordCallback 子类

    你需要编写一个继承 DruidPasswordCallback 的类,用于加载密钥和解密密码。示例如下:

      [java]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    import com.alibaba.druid.util.DruidPasswordCallback; import javax.crypto.Cipher; import java.io.FileReader; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Properties; import java.util.Base64; public class MyPasswordCallback extends DruidPasswordCallback { @Override public void setProperties(Properties properties) { super.setProperties(properties); String password = properties.getProperty("password"); try { String publicKeyPath = "/path/to/publicKey.txt"; String privateKey = getPrivateKey(publicKeyPath); password = decrypt(password, privateKey); setPassword(password.toCharArray()); } catch (Exception e) { e.printStackTrace(); } } private String getPrivateKey(String filename) throws Exception { FileReader reader = new FileReader(filename); char[] buffer = new char[4096]; int read = reader.read(buffer); reader.close(); return new String(buffer, 0, read); } private String decrypt(String encrypted, String privateKey) throws Exception { byte[] keyBytes = Base64.getDecoder().decode(privateKey); PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey key = keyFactory.generatePrivate(spec); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, key); byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encrypted)); return new String(decrypted); } }

    这里的 MyPasswordCallback 类用于从文件中读取私钥,并解密数据库密码。

  2. 配置文件 application.yml

    在 Druid 配置中添加以下内容:

      [yaml]
    1
    2
    3
    4
    5
    6
    7
    druid: datasource: username: myuser password: Dv7cWQk1jVc7K/zNFFN2asU5Cn... # 加密后的密码 filters: config connection-properties: config.decrypt=true;config.decrypt.key=/path/to/publicKey.txt password-callback-class-name: com.example.MyPasswordCallback

    这里需要注意:

    • password 属性中填写加密后的密码。
    • filters 中添加 config,用于启用配置解密功能。
    • connection-properties 中设置 config.decrypt=true 以启用密码解密,并指明密钥文件的位置。

三、解密密码

Druid 在运行时会根据你提供的 DruidPasswordCallback 类来解密数据库连接密码。

  • config.decrypt: 如果设置为 true,Druid 将会自动调用 DruidPasswordCallbackpassword 进行解密。

  • password-callback-class-name: 这里指向你实现的 DruidPasswordCallback 类,该类负责读取密钥并解密密码。

四、注意事项

  1. 安全性: 私钥文件的存储位置和权限必须严格控制,确保只有应用程序可以读取它,避免被不正当访问。

  2. 密钥管理: 公钥和私钥的管理应严格遵循安全管理规范,防止密钥泄漏。

  3. 性能: 解密过程会增加一定的启动时间,但对运行时性能影响较小。

通过这种加解密机制,Druid 可以在保护数据库密码安全的同时,确保应用能够顺利连接数据库。

参考资料

https://www.cnblogs.com/yeahwell/p/9252931.html

https://www.cnblogs.com/wuyun-blog/p/5679073.html

https://y0ngb1n.github.io/a/best-practice-samples-datasource-alibaba-druid.html