一、使用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
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
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