一、前言
出于安全考虑,java项目配置文件中不允许出现明文密码;
为了解决这个问题,可以使用jasypt
这个jar包,这个jar包可以对字符串进行加解密,项目中引入后,在配置文件中写加密后的密码即可,项目启动时这个jar包就会对密码进行解密,不影响项目正常使用。
java类中也不允许出现明文密码,也可以利用这个jar包进行加解密。
二、解决方法
项目中,在里引入:
<!-- /artifact//jasypt -->
<dependency>
<groupId></groupId>
<artifactId>jasypt</artifactId>
<version>1.9.3</version>
</dependency>
2.编写一个加解密工具类ENC_Util.java
,样例如下:
import ;
import ;
import ;
import ;
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) {
//自己的解密方法,解密时,需要把ENC()去掉才行
if(plainText == null || ()<=5){
return "";
}else{
plainText = (4,()-1);
}
return decryptWithMD5(plainText,SALT);
}
/**
* 加密(PBEWithMD5AndDES)
* @param plainText 待加密的原文
* @param factor 加密秘钥
* @return
*/
public static String encryptWithMD5(String plainText, String factor) {
// 1. 创建加解密工具实例
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
// 2. 加解密配置
EnvironmentStringPBEConfig config = new EnvironmentStringPBEConfig();
(PBEWITHMD5ANDDES);
(factor);
(config);
// 3. 加密
return (plainText);
}
/**
* 解密(PBEWithMD5AndDES)
* @param encryptedText 待解密密文
* @param factor 解密秘钥
* @return
*/
public static String decryptWithMD5(String encryptedText, String factor) {
// 1. 创建加解密工具实例
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
// 2. 加解密配置
EnvironmentStringPBEConfig config = new EnvironmentStringPBEConfig();
(PBEWITHMD5ANDDES);
(factor);
(config);
// 3. 解密
return (encryptedText);
}
/**
* 加密(PBEWITHHMACSHA512ANDAES_256)
* @param plainText 待加密的原文
* @param factor 加密秘钥
* @return
*/
public static String encryptWithSHA512(String plainText, String factor) {
// 1. 创建加解密工具实例
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
// 2. 加解密配置
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
(factor);
(PBEWITHHMACSHA512ANDAES_256);
// 为减少配置文件的书写,以下都是 Jasyp 版本,配置文件默认配置
( "1000");
("1");
("SunJCE");
("");
("");
("base64");
(config);
// 3. 加密
return (plainText);
}
/**
* 解密(PBEWITHHMACSHA512ANDAES_256)
* @param encryptedText 待解密密文
* @param factor 解密秘钥
* @return
*/
public static String decryptWithSHA512(String encryptedText, String factor) {
// 1. 创建加解密工具实例
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
// 2. 加解密配置
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
(factor);
(PBEWITHHMACSHA512ANDAES_256);
// 为减少配置文件的书写,以下都是 Jasyp 版本,配置文件默认配置
("1000");
("1");
("SunJCE");
("");
("");
("base64");
(config);
// 3. 解密
return (encryptedText);
}
public static void main(String[] args) {
String plainText = "3s";
//这个每次跑的结果不一样
String encryptWithMD5Str = encryptWithMD5(plainText, SALT);
//虽然不一样,这个也能正常执行
String decryptWithMD5Str = decryptWithMD5(encryptWithMD5Str, SALT);
("加密前:"+plainText);
("加密后:"+encryptWithMD5Str);
("解密后:"+decryptWithMD5Str);
//String encryptWithSHA512Str = encryptWithSHA512(plainText, factor);
//String decryptWithSHA512Str = decryptWithSHA512(encryptWithSHA512Str, factor);
//("采用SHA512加密前原文密文:" + encryptWithSHA512Str);
//("采用SHA512解密后密文原文:" + decryptWithSHA512Str);
}
}
可以执行这个类的main方法,把plainText
改成待加密内容,执行后就可以生成加密后的内容;
可以修改SALT
变量,这个就是加解密用的盐值。
3.自定义一个配置文件解析类ENC_PropertyPlaceholderConfigurer
,继承PropertyPlaceholderConfigurer
,其中实现对配置文件加密内容的解密操作。样例如下:
import ;
import ;
import ;
public class ENC_PropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
/**
* 将包含ENC()的value进行转换
*/
@Override
protected String convertProperty(String propertyName, String propertyValue) {
//其实是 ^ENC\(.+\)$
//以ENC开头,包含(,中间1-N个字符,结尾是)的,就匹配成功
Pattern pattern = ("^ENC\\(.+\\)$");
Matcher matcher= (propertyValue);
if (()){
//如果是这样的格式,说明是加密后的,就返回解密后的内容
return ENC_Util.decryptWithMD5(propertyValue);
}else{
//否则直接返回即可,不做处理
return propertyValue;
}
}
}
4.把自定义的解析类配置入spring的xml文件中,这样才能让项目启动时使用自己写的这个类。
以本人的项目为例,
项目启动时,一般会先加载,其中一般会有:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:META-INF/app_config/context/context-*.xml
</param-value>
</context-param>
这段的意思是会加载resources
文件夹下的META-INF/app_config/context/
里面所有的以context-
开头的xml
文件;
(项目打成war包后会是项目名\WEB-INF\classes\META-INF\app_config\context\
)
因此,以本人的项目为例,就可以在这个路径下的xml文件里增加这样的配置:
<bean name="enc_propertyConfiger" class=".ENC_PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>META-INF/app_config/properties/</value>
<value>META-INF/app_config/properties/</value>
</list>
</property>
</bean>
其中,和里就是数据库连接的账号密码等信息。
5.修改properties
配置文件,把其中明文密码替换为ENC(密文)
格式,样例如下:
其中密文可以执行ENC_Util.java
得到。
jdbc_driverClass=
jdbc_url=jdbc:mysql://127.0.0.1:3306/mydb
jdbc_username=root
#jdbc_password=root
#用秘钥mysalt,加密就是这个,解密就是root(注意每次加密后得到的结果都不一样,不过解密得到的结果都一样)
jdbc_password=ENC(l44BhMR+f40JBsP5euOKKA==)
6.如果有的明文密码是配置在xml文件中的,那就可以用EL表达式${}
,让它读取properties中的值,例如:
<bean name="secDataSource" class="" init-method="init" destroy-method="close">
<property name="url" value="${jdbc_url}" />
<property name="username" value="${jdbc_username}" />
<property name="password" value="${jdbc_password}" />
<property name="driverClassName" value="${jdbc_driverClass}" />
...
注意,因为第4步中配置了自定义配置文件解析类,所以扫描到的properties文件就会加载入项目,xml文件就可以用EL表达式获取到值。
自己要先检查下项目中是否已经配置了默认的配置文件解析类,搜索class=“”,如果已存在,那就把这个删掉,换成自定义的(自定义的才能加解密)
7.如果ENC_Util.java里SALT变量也不允许存在,那就可以在启动参数中增加秘钥,后续在xml文件中用${}
使用。(这个还没有试,感觉应该可以)
/topics/392314029
通过 jvm 启动参数 参数 -DXXXXX, 这个XXXXX在springxml里面可以直接通过 ${XXXXX} 引用
-Dmy_salt='mysalt'
然后就可以:
<bean name="enc_propertyConfiger" class=".ENC_PropertyPlaceholderConfigurer">
<property name="mySALT" value="${my_salt}" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>META-INF/app_config/properties/uat/</value>
</list>
</property>
</bean>
public class ENC_PropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
//这样这个值就注入了,后续可以用
private String mySALT;
public void setMySALT(String mySALT){
= mySALT;
}
三、总结
可以对字符串进行加解密
项目中,可以把加密后的密码配置在properties文件里
3.然后可以自定义PropertyPlaceholderConfigurer
,在读取properties的时候进行解密
中,可以用${}
来使用解密后的密码等配置信息
中,可以用jasypt把字符串解密后使用
6.可以在tomcat启动参数中传入全局变量,作为jasypt加解密的秘钥(如果不允许配置在代码里的话),然后在xml中使用${}
获取并注入java中使用