赞
踩
出于安全考虑,java项目配置文件中不允许出现明文密码;
为了解决这个问题,可以使用jasypt
这个jar包,这个jar包可以对字符串进行加解密,项目中引入后,在配置文件中写加密后的密码即可,项目启动时这个jar包就会对密码进行解密,不影响项目正常使用。
java类中也不允许出现明文密码,也可以利用这个jar包进行加解密。
1.spring项目中,在pom.xml
里引入:
<!-- https://mvnrepository.com/artifact/org.jasypt/jasypt -->
<dependency>
<groupId>org.jasypt</groupId>
<artifactId>jasypt</artifactId>
<version>1.9.3</version>
</dependency>
2.编写一个加解密工具类ENC_Util.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) { //自己的解密方法,解密时,需要把ENC()去掉才行 if(plainText == null || plainText.length()<=5){ return ""; }else{ 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 = "3s"; //这个每次跑的结果不一样 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); } }
可以执行这个类的main方法,把plainText
改成待加密内容,执行后就可以生成加密后的内容;
可以修改SALT
变量,这个就是加解密用的盐值。
3.自定义一个配置文件解析类ENC_PropertyPlaceholderConfigurer
,继承PropertyPlaceholderConfigurer
,其中实现对配置文件加密内容的解密操作。样例如下:
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ENC_PropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer { /** * 将包含ENC()的value进行转换 */ @Override protected String convertProperty(String propertyName, String propertyValue) { //其实是 ^ENC\(.+\)$ //以ENC开头,包含(,中间1-N个字符,结尾是)的,就匹配成功 Pattern pattern = Pattern.compile("^ENC\\(.+\\)$"); Matcher matcher= pattern.matcher(propertyValue); if (matcher.find()){ //如果是这样的格式,说明是加密后的,就返回解密后的内容 return ENC_Util.decryptWithMD5(propertyValue); }else{ //否则直接返回即可,不做处理 return propertyValue; } } }
4.把自定义的解析类配置入spring的xml文件中,这样才能让项目启动时使用自己写的这个类。
以本人的项目为例,
项目启动时,一般会先加载web.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="com.xxx.config.ENC_PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>META-INF/app_config/properties/db1.properties</value>
<value>META-INF/app_config/properties/db2.properties</value>
</list>
</property>
</bean>
其中,db1.properties和db2.properties里就是数据库连接的账号密码等信息。
5.修改properties
配置文件,把其中明文密码替换为ENC(密文)
格式,样例如下:
其中密文可以执行ENC_Util.java
得到。
jdbc_driverClass=com.mysql.jdbc.Driver
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="com.alibaba.druid.pool.DruidDataSource" 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=“org.springframework.beans.factory.config.PropertyPlaceholderConfigurer”,如果已存在,那就把这个删掉,换成自定义的(自定义的才能加解密)
7.如果ENC_Util.java里SALT变量也不允许存在,那就可以在启动参数中增加秘钥,后续在xml文件中用${}
使用。(这个还没有试,感觉应该可以)
https://bbs.csdn.net/topics/392314029
通过 jvm 启动参数 参数 -DXXXXX, 这个XXXXX在springxml里面可以直接通过 ${XXXXX} 引用
-Dmy_salt='mysalt'
然后就可以:
<bean name="enc_propertyConfiger" class="com.taikang.udp.timer.common.util.config.ENC_PropertyPlaceholderConfigurer">
<property name="mySALT" value="${my_salt}" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>META-INF/app_config/properties/uat/secondaryDB.properties</value>
</list>
</property>
</bean>
public class ENC_PropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
//这样这个值就注入了,后续可以用
private String mySALT;
public void setMySALT(String mySALT){
this.mySALT = mySALT;
}
1.jasypt可以对字符串进行加解密
2.spring项目中,可以把加密后的密码配置在properties文件里
3.然后可以自定义PropertyPlaceholderConfigurer
,在读取properties的时候进行解密
4.xml中,可以用${}
来使用解密后的密码等配置信息
5.java中,可以用jasypt把字符串解密后使用
6.可以在tomcat启动参数中传入全局变量,作为jasypt加解密的秘钥(如果不允许配置在代码里的话),然后在xml中使用${}
获取并注入java中使用
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。