应用场景:如对配置文件中的密文进行解密处理
废话不多说,直接上示例代码
import com.encry.JasypUtil;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.boot.origin.OriginTrackedValue;
import org.springframework.context.Enviroment;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnviroment;
import org.springframework.core.Enviroment;
import org.springframework.core.MutablePropertySources;
import org.springframework.core.PropertySource;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Properties;
@Component
public class EnableEncryptionData implements BeanFactoryPostProcessor, BeanPostProcessor, Orderd, EnviromentAware{
//以该前缀识别需要加密的文本
public static final String prefix = "encry[";
//以该后缀识别需要加密的文本
public static final String suffix= "]";
//启动时手动加参指定密钥进行解密,避免密钥显式地暴露在代码中,指定参数启动-Dencryption.privateKey=***,等号后面加上自己文本加密时的密钥
private static final property_private_key = "encryption.privateKey";
private String privateKey;
private ConfigurableEnviroment enviroment;
private static final Properties properties = new Properties();
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeanException{
MutablePropertySources propertySources = enviroment.getPropertySources();
for(PropertySource<?> propertySource:propertySources){
if(propertySource instanceOf OriginTrackedMapPropertySource){
OriginTrackedMapPropertySource om = (OriginTrackedMapPropertySource)propertySource;
Map<String,Object> source = om.getSource();
source.forEach(k,v)->{
OriginTrackedValue originTrackedValue = (OriginTrackedValue)source.get(k);
String property = enviroment.getProperty(k);
if(hasPreAndSuf(property,prefix,suffix)){
try{
String relay = splitPreAndSuf(property,prefix,suffix);
if(StringUtils.isEmpty(relay)){
return;
}
//解密
//自定义一个解密工具类,可以通过jasypt包进行编写,加密的文本也可以通过此包进行生成,生成之后再加上前后缀替换掉配置文件中需要加密的文本,如密码等
String decrypt = JasyptUtil.decryptPwd(getPrivateKey(enviroment),relay);
modify(originTrackedValue,"value",decrypt);
}catch(Exception e){
System.out.println(e.getMessage());
}
}
});
}
}
}
@Override
public int getOrder(){ return 0; }
@Override
public void setEnviroment(Enviroment enviroment){
this.enviroment = (ConfigurableEnviroment)enviroment;
}
private String splitPreAndSuf(String prpperty,String prefix,String suffix){
try{
String substring = property.substring(prefix.length(),property.length()-1);
return substring;
}catch(Exception e){
System.out.println(e.getMessage());
}
return null;
}
private boolean hasPreAndSuf(String property,String prefix,String suffix){
if(property.startsWith(prefix) && property.endsWith(suffix)){
return true;
}
return false;
}
private String getPrivateKey(ConfigurableEnviroment enviroment){
String commonPrivateKey = System.getProperty(property_private_key,"");
if(StringUtils.hasText(commonPrivateKey)){
this.privateKey = commonPrivateKey;
return commonPrivateKey;
}
String pkv = enviroment.getProperty(property_private_key);
if(StringUtils.hasText(pkv)){
this.privateKey = pkv;
return pkv;
}
String propertyValue = (String)properties.get(property_private_key);
if(StringUtils.hasText(propertyValue)){
this.privateKey = propertyValue;
return propertyValue;
}
return privateKey;
}
public static void modify(Object object,String fieldName,Object newFieldValue) throws Exception{
Field field = object.getClass().getSuperclass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object,newFieldValue);
field.setAccessible(false);
}
}
JasyptUtil工具类示例代码
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.EnviromentStringPBEConfig;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.jasypt.util.text.BasicTextEncryptor;
public class JasyptUtil{
private static final String ENCRYP_PREFIX = "ENC(";
private static final String ENCRYP_SUFFIX = ")";
/**
* 判断是否是 prefix/suffix 包裹的属性
*
* @param value
* @return
*/
public static boolean isEncryptedValue(final String value) {
boolean flag = false;
if (value == null) {
return flag;
}
final String val = value.trim();//去除空格及符号
if(val.startsWith(ENCRYP_PREFIX) && val.endsWith(ENCRYP_SUFFIX)){
flag = true;
}
return flag;
}
//生成加密结果
public static String encryptPwd(String password, String value) {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
encryptor.setConfig(cryptor(password));
return encryptor.encrypt(value);
}
//解密
public static String decyptPwd(String password, String value) {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
encryptor.setConfig(cryptor(password));
return encryptor.decrypt(isEncryptedValue(value) ? getOriginValue(value) : value);
}
/**
* 获取前后缀包裹的值
*
* @param value
* @return
*/
private static String getOriginValue(final String value) {
return value.substring(ENCRYPT_PREFIX.length(),
(value.length() - ENCRYPT_SUFFIX.length()));
}
/**
* @param password salt
* @return
*/
public static SimpleStringPBEConfig cryptor(String password) {
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword(password);
config.setAlgorithm(StandardPBEByteEncryptor.DEFAULT_ALGORITHM);
config.setKeyObtentionIterations("1000");
config.setPoolSize("1");
config.setProviderName(null);
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
config.setStringOutputType("base64");
return config;
}
}