一、使用Druid自带的加密方式

  • 先来看不对密码进行加密的配置

datasource:
  name: druidDataSource  type: com.alibaba.druid.pool.DruidDataSource  druid:
    driver-class-name: com.mysql.cj.jdbc.Driver    url: jdbc:mysql://ip:port/db?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC    username: root    # 明文密码
    password: yourpasswd    # 其它配置略................12345678910

然后得知 Druid 有自带的有加密方式,通过自带的jar包可以生成**,如下:(Aa123456 为你指定的密码)

java -cp druid-1.2.5.jar com.alibaba.druid.filter.config.ConfigTools Aa123456

privateKey:MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAtpgI1KFA4e/n/nLmUFgn70dEso/e3tq+wX49ek9pWFFGhogFmb7jDUyguSQ+Rvgt0txo7z2OdCRe9m4spzjGRwIDAQABAkBjfr65FlEjjDVvCi8DsrW4Ba6iWhEIgEuXZfGb9y+hBmTiEhWSW1UffdPD0ROTo9jg0suhNTxFcboPMF2GOdIBAiEA3gtH0jlMdi32fFCPkywh9oDzy6m5PAutrHpKEOBGm0cCIQDShFVt/eDraF2jiGzQooH+th8mdx/+OpHmDo7Q6Rv9AQIhANxlwA1n+IBZkQ7F/C0uIiwGxXcDaayzPtkzrS7hHtRjAiA+LaIB+9OcFFZb/+aL9QPKVMZ8mQDVGT2QosoiAEgpAQIhAIVq9yXbojHrW3G1cUsA1EkZ60pWjRgOrJrqbKXsULo4
publicKey:MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALaYCNShQOHv5/5y5lBYJ+9HRLKP3t7avsF+PXpPaVhRRoaIBZm+4w1MoLkkPkb4LdLcaO89jnQkXvZuLKc4xkcCAwEAAQ==password:QQ446Ed787nuj8CClXEQ+zWqLQJF+d7cQsGmRQSTF+++fXR5flrzQXGHPjewAS1/OHUpKUb+82MYD0Mj6+K2yg==12345
  • 更新yml文件为加密的方式

datasource:
  name: druidDataSource  type: com.alibaba.druid.pool.DruidDataSource  druid:
    driver-class-name: com.mysql.cj.jdbc.Driver    url: jdbc:mysql://ip:port/db?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC    username: root    # 这里填上面获取到的password
    password: QQ446Ed787nuj8CClXEQ+zWqLQJF+d7cQsGmRQSTF+++fXR5flrzQXGHPjewAS1/OHUpKUb+82MYD0Mj6+K2yg==    # 这里填上上面获取到的publicKey
    key: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALaYCNShQOHv5/5y5lBYJ+9HRLKP3t7avsF+PXpPaVhRRoaIBZm+4w1MoLkkPkb4LdLcaO89jnQkXvZuLKc4xkcCAwEAAQ==    # config.decrypt=true 设定启动解密, config.decrypt.key=${spring.datasource.druid.key} 表示使用上一行配置的公钥来解密
    connection-properties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000;config.decrypt=true;config.decrypt.key=${spring.datasource.druid.key}"
    initial-size: 1
    max-active: 20
    filters: stat,wall,slf4j,config # slf4j: 对应logback
    max-wait: 60000
    min-idle: 1
    test-while-idle: true
    test-on-borrow: false
    test-on-return: false
    pool-prepared-statements: true
    max-open-prepared-statements: 20
    async-init: true
    web-stat-filter:
      enabled: true
      exclusions: "*.js, *.gif, *.jpg, *.png, *.css, *.ico, /swagger*, /druid/*"
    stat-view-servlet:
      enabled: true
      login-username: druid      login-password: druid      allow: localhost1234567891011121314151617181920212223242526272829303132

这样就实现了最简单的加密(也就比明文好一点),当然细心的朋友应该会发现,这也只是防君子不防小人,通过Druid自带的ConfigTools可以解密:

String key = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALaYCNShQOHv5/5y5lBYJ+9HRLKP3t7avsF+PXpPaVhRRoaIBZm+4w1MoLkkPkb4LdLcaO89jnQkXvZuLKc4xkcCAwEAAQ==";String encPwd = "QQ446Ed787nuj8CClXEQ+zWqLQJF+d7cQsGmRQSTF+++fXR5flrzQXGHPjewAS1/OHUpKUb+82MYD0Mj6+K2yg==";System.out.println(ConfigTools.decrypt(key, encPwd)); // Aa123456123

只要对 Druid加密规则清楚点的开发同学应该都可以轻松拿到密码,而且最开始wenshao大佬在实现加密功能的时候,并没有遵循RSA正常的流程,正常一般是通过公钥来加密数据,保管好私钥,然后用私钥来解密数据,细心的朋友应该发现了,上面填的key是用的publicKey,就把是把publicKey当成了privateKey,完全搞反了,当然,也有人在github上问过wenshao大佬这个问题,wenshao也针对这个问题进行了 回复,大家可以去看一下;

当然,上面只是用Druid默认的生成方式,其实还可以用自定义生成RSA公钥和私钥,并通过提供给Druid提供回调的方式来解析密码,这里我不详细讲述,感兴趣的朋友可以看下 这篇文章

二、使用Jasypt加密的方式

jasypt 也能实现相同的功能,不同于Druid默只对密码进行加密,jasypt 就灵活得多,只要我们定义好加密规则,我们可以对数据库链接、账号、密码都加上密,大家可以点击链接进去看一下怎么用的,我这里把我的实现贴上来给大家参考一下

  • 首先引入依赖

<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>3.0.2</version></dependency>12345
  • 新建一个解析类

package com.yinchd.web.config;import org.jasypt.encryption.StringEncryptor;import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;import org.jasypt.encryption.pbe.StandardPBEByteEncryptor;import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/**
 * Jasypt 配置
 */@Configurationpublic class JasyptConfig {

    @Bean("jasyptStringEncryptor")
    public StringEncryptor stringEncryptor() {
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        // 加密盐值
        config.setPassword("Ayinchd@*(j^z");
        // 加密算法
        config.setAlgorithm(StandardPBEByteEncryptor.DEFAULT_ALGORITHM);
        // key迭代次数
        config.setKeyObtentionIterations("1000");
        // 池大小
        config.setPoolSize("1");
        config.setProviderName("SunJCE");
        // 随机盐生成器
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
        config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
        // 加密后输出字符串编码方式
        config.setStringOutputType("base64");
        encryptor.setConfig(config);
        return encryptor;
    }

    public static void main(String[] args) {
        StringEncryptor encryptor = new JasyptConfig().stringEncryptor();
        String url = "jdbc:mysql://ip:port/db?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC";
        String user = "root";
        String pwd = "Aa123456";
        System.out.println(encryptor.encrypt(url));
        System.out.println(encryptor.encrypt(user));
        System.out.println(encryptor.encrypt(pwd));
        // Zg2cMlfZ4fw58+gIuJsl1Tf9O1mPtubldcbXX/PW5WCDDMk2zY73hYc+k2/XgnfgFAsAqdaySVSM1zVKw6DbjhfZnQa/bBtB/mirMgPXJWHx6sLlfrOBHyh07hwfbC5+eI1kx3Sif19VSAe20ZEHu+MB3H1orJ8qBwe2M/BfDbVz4mGmfJ6cLZvfYBemLvOYvV9fgGrsMTtF3VkyNHU4BXnzy8PWMzhg
        // 7DIiWfG69scrYvG12ql5o6bKESGzXXxv
        // OlNNAnO5JZ+Bdd2Rcz44JnOMgJCtdc+xZyvQH9+XRFI=
    }}12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  • 使用 jasypt 加密的配置文件

datasource:
  name: druidDataSource  type: com.alibaba.druid.pool.DruidDataSource  druid:
    driver-class-name: com.mysql.cj.jdbc.Driver    url: ENC(Zg2cMlfZ4fw58+gIuJsl1Tf9O1mPtubldcbXX/PW5WCDDMk2zY73hYc+k2/XgnfgFAsAqdaySVSM1zVKw6    username: ENC(7DIiWfG69scrYvG12ql5o6bKESGzXXxv)    password: ENC(OlNNAnO5JZ+Bdd2Rcz44JnOMgJCtdc+xZyvQH9+XRFI=)    connection-properties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000;"
    initial-size: 1
    max-active: 20
    filters: stat,wall,slf4j,config # slf4j: 对应logback
    # 其它配置略................12345678910111213

因为 JasyptConfig 中已将配置(包含password)注入到容器中,所以上述配置已经OK,系统已经可以正常解析到配置文件中的ENC(***) 加密的数据,同理,我们也可以据此来解密:

StringEncryptor encryptor = new JasyptConfig().stringEncryptor();String url = "Zg2cMlfZ4fw58+gIuJsl1Tf9O1mPtubldcbXX/PW5WCDDMk2zY73hYc+k2/XgnfgFAsAqdaySVSM1zVKw6DbjhfZnQa/bBtB/mirMgPXJWHx6sLlfrOBHyh07hwfbC5+eI1kx3Sif19VSAe20ZEHu+MB3H1orJ8qBwe2M/BfDbVz4mGmfJ6cLZvfYBemLvOYvV9fgGrsMTtF3VkyNHU4BXnzy8PWMzhg";String user = "7DIiWfG69scrYvG12ql5o6bKESGzXXxv";String pwd = "OlNNAnO5JZ+Bdd2Rcz44JnOMgJCtdc+xZyvQH9+XRFI=";System.out.println(encryptor.decrypt(url));System.out.println(encryptor.decrypt(user));System.out.println(encryptor.decrypt(pwd));// jdbc:mysql://ip:port/db?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC// root// Aa12345612345678910

三、总结

总体来说,上述两种方式都不能称之为一种安全的方式,因为不管是druid的配置方式中,我们使用默认的也好,使用自定义的RSA加解密方式也好,我们始终要将我们的加密key给暴露在文件或者代码中,Jasypt 也一样,我们要将我们的password写在了JasyptConfig这个类中,跟配置文件相比,可能硬编码稍微安全一丢丢,但是通过反编译手段,我们一样可以拿到**信息,只能说这些手段都是防君子不防小人,能让配置文件上的信息丢失后,能给**者制造一点点难度。

版权声明:本文为sageyin原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/sageyin/article/details/114885547