出于安全考虑,java项目配置文件中不允许出现明文密码;
为了解决这个问题,可以使用jasypt
这个jar包,这个jar包可以对字符串进行加解密,项目中引入后,在配置文件中写加密后的密码即可,项目启动时这个jar包就会对密码进行解密,不影响项目正常使用。
java类中也不允许出现明文密码,也可以利用这个jar包进行加解密。
1.springboot项目中,在pom.xml
里引入:
com.github.ulisesbocchio
jasypt-spring-boot-starter
2.1.2
2.在启动类Application.java
中,引入:
import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties;
@EnableEncryptableProperties
3.可以编写一个ENC_Util.java
工具类,用来对字符串加解密(获取加密字符串、解密java类中的密码可以用,解密配置文件里的密码用不到),内容如下:
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
public class ENC_Util {
private static final String SALT = "mysalt";
/**
* jasypt-1.9.3 加解密工具类( jasypt-spring-boot-starter 是 2.1.2 )
*/
private static final String PBEWITHMD5ANDDES = "PBEWithMD5AndDES";
private static final String PBEWITHHMACSHA512ANDAES_256 = "PBEWITHHMACSHA512ANDAES_256";
public static String encryptWithMD5(String plainText) {
return encryptWithMD5(plainText,SALT);
}
public static String decryptWithMD5(String plainText) {
//java项目里用的解密方法,解密时,需要把ENC()去掉才行
if(plainText == null || plainText.length()<=5){
return "";
}else{
//截取字符串,把ENC()去掉
plainText = plainText.substring(4,plainText.length()-1);
}
return decryptWithMD5(plainText,SALT);
}
/**
* Jasyp2.x 加密(PBEWithMD5AndDES)
* @param plainText 待加密的原文
* @param factor 加密秘钥
* @return java.lang.String
*/
public static String encryptWithMD5(String plainText, String factor) {
// 1. 创建加解密工具实例
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
// 2. 加解密配置
EnvironmentStringPBEConfig config = new EnvironmentStringPBEConfig();
config.setAlgorithm(PBEWITHMD5ANDDES);
config.setPassword(factor);
encryptor.setConfig(config);
// 3. 加密
return encryptor.encrypt(plainText);
}
/**
* Jaspy2.x 解密(PBEWithMD5AndDES)
* @param encryptedText 待解密密文
* @param factor 解密秘钥
* @return java.lang.String
*/
public static String decryptWithMD5(String encryptedText, String factor) {
// 1. 创建加解密工具实例
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
// 2. 加解密配置
EnvironmentStringPBEConfig config = new EnvironmentStringPBEConfig();
config.setAlgorithm(PBEWITHMD5ANDDES);
config.setPassword(factor);
encryptor.setConfig(config);
// 3. 解密
return encryptor.decrypt(encryptedText);
}
/**
* Jasyp3.x 加密(PBEWITHHMACSHA512ANDAES_256)
* @param plainText 待加密的原文
* @param factor 加密秘钥
* @return java.lang.String
*/
public static String encryptWithSHA512(String plainText, String factor) {
// 1. 创建加解密工具实例
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
// 2. 加解密配置
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword(factor);
config.setAlgorithm(PBEWITHHMACSHA512ANDAES_256);
// 为减少配置文件的书写,以下都是 Jasyp 3.x 版本,配置文件默认配置
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);
// 3. 加密
return encryptor.encrypt(plainText);
}
/**
* Jaspy3.x 解密(PBEWITHHMACSHA512ANDAES_256)
* @param encryptedText 待解密密文
* @param factor 解密秘钥
* @return java.lang.String
*/
public static String decryptWithSHA512(String encryptedText, String factor) {
// 1. 创建加解密工具实例
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
// 2. 加解密配置
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword(factor);
config.setAlgorithm(PBEWITHHMACSHA512ANDAES_256);
// 为减少配置文件的书写,以下都是 Jasyp 3.x 版本,配置文件默认配置
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);
// 3. 解密
return encryptor.decrypt(encryptedText);
}
public static void main(String[] args) {
//待加密字符串
String plainText = "123456";
//这个每次跑的结果不一样
String encryptWithMD5Str = encryptWithMD5(plainText, SALT);
//虽然不一样,这个也能正常执行
String decryptWithMD5Str = decryptWithMD5(encryptWithMD5Str, SALT);
System.out.println("加密前:"+plainText);
System.out.println("加密后:"+encryptWithMD5Str);
System.out.println("解密后:"+decryptWithMD5Str);
//String encryptWithSHA512Str = encryptWithSHA512(plainText, factor);
//String decryptWithSHA512Str = decryptWithSHA512(encryptWithSHA512Str, factor);
//System.out.println("采用SHA512加密前原文密文:" + encryptWithSHA512Str);
//System.out.println("采用SHA512解密后密文原文:" + decryptWithSHA512Str);
}
}
4.举个例子,上面的密码是123456
,盐值是mysalt
,加密后的结果是dLJEFB7/7QJYan40UefGvQ==
;
这个每次加密后的结果都不一样,不过解密后的结果是一样的,都是123456
5.修改配置文件application.yml
,先加上jasypt
的配置信息:
jasypt:
encryptor:
algorithm: PBEWithMD5AndDES
pool-size: 1
salt-generator-classname: org.jasypt.salt.RandomSaltGenerator
password: mysalt
注意,这里的password就是盐值,如果这里安全人员也不允许写,那就可以写在启动命令中,例如:
jasypt:
encryptor:
algorithm: PBEWithMD5AndDES
pool-size: 1
salt-generator-classname: org.jasypt.salt.RandomSaltGenerator
然后项目启动命令里加上:
java -jar -Djasypt.encryptor.password=mysalt
6.修改配置文件application.yml
,在之前明文密码的地方,用ENC(密文密码)
代替,例如:
spring.datasource:
url: jdbc:mysql://10.123.123.123:3306/mydbname?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: ENC(dLJEFB7/7QJYan40UefGvQ==)
driver-class-name: com.mysql.cj.jdbc.Driver
这个在项目启动后,jar包就会把dLJEFB7/7QJYan40UefGvQ==
解密成123456
,并正确连接数据库了。
7.如果java文件中还有明文密码,也可以换成密文密码,然后用上方的ENC_Util.java
解密一下,例如:
private static Connection getConnection() {
Connection conn = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://10.123.123.123:3306/mydbname?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";
String username = "root";
//这里是util里截取字符串后才解密的,也可以不加ENC(),然后util里也不截取字符串
String password = ENC_Util.decryptWithMD5("ENC(dLJEFB7/7QJYan40UefGvQ==)");
//String password = ENC_Util.decryptWithMD5("dLJEFB7/7QJYan40UefGvQ==");
Properties props = new Properties();
props.setProperty("user", username);
props.setProperty("password", password);
conn = DriverManager.getConnection(url, props);
} catch (Exception e) {
logger.error(e.getMessage());
}
return conn;
}