注:网上没有找到除了使用jasypt-spring-boot的其他简单使用方法,这里借鉴jasypt提供思路了一种思路,springboot 2.2.0之前和之后版本做法有点差异
配置文件
password: Enc[4SHQhZM1rmcHQ+X+gryPMw==]
decrypt:
prefix: Enc[
suffix: ]
key: 12345678
加解密类
import org.springframework.util.StringUtils;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import java.security.Key;
import java.security.SecureRandom;
public class DecryptUtil {
private static final String CHARSET = "utf-8";
private static final String ALGORITHM = "AES";
private static final String RANDOM_ALGORITHM = "SHA1PRNG";
public static String aesEncrypt(String content, String key) {
if (content == null || key == null) {
return null;
}
Key secretKey = getKey(key);
try {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] p = content.getBytes(CHARSET);
byte[] result = cipher.doFinal(p);
BASE64Encoder encoder = new BASE64Encoder();
String encoded = encoder.encode(result);
return encoded;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static String aesDecrypt(String content, String key) {
Key secretKey = getKey(key);
try {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
BASE64Decoder decoder = new BASE64Decoder();
byte[] c = decoder.decodeBuffer(content);
byte[] result = cipher.doFinal(c);
String plainText = new String(result, CHARSET);
return plainText;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static Key getKey(String key) {
if (StringUtils.isEmpty(key)) {
key = "12345678";// 默认key
}
try {
SecureRandom secureRandom = SecureRandom.getInstance(RANDOM_ALGORITHM);
secureRandom.setSeed(key.getBytes());
KeyGenerator generator = KeyGenerator.getInstance(ALGORITHM);
generator.init(secureRandom);
return generator.generateKey();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
String newUserName= aesEncrypt("root","");
System.out.println(newUserName);
}
}
修改属性的bean文件
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.stream.StreamSupport;
import static java.util.stream.Collectors.toList;
@Component
public class DecryptConfig implements EnvironmentAware, BeanFactoryPostProcessor{
private ConfigurableEnvironment environment;
private String decryptPrefix = "Enc["; // 解密前缀标志 默认值
private String decryptSuffix = "]"; // 解密后缀标志 默认值
private String decryptKey = "12345678"; // 解密可以 默认值
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
MutablePropertySources propSources = environment.getPropertySources();
StreamSupport.stream(propSources.spliterator(), false)
.filter(ps -> ps instanceof OriginTrackedMapPropertySource)
.collect(toList())
.forEach(ps -> convertPropertySource(ps));
}
@Override
public void setEnvironment(Environment environment) {
this.environment = (ConfigurableEnvironment) environment;
}
private void convertPropertySource(PropertySource ps) {
final Map source = (Map) ps.getSource();
setDecryptProperties(source);
source.forEach((k,v) -> {
String value = String.valueOf(v);
if (!value.startsWith(decryptPrefix) || !value.endsWith(decryptSuffix)) {
return;
}
String cipherText = value.replace(decryptPrefix, "").replace(decryptSuffix, "");
String clearText = DecryptUtil.aesDecrypt(cipherText, decryptKey);
if(source.getClass().toString().endsWith("java.util.Collections$UnmodifiableMap")){
//springboot 2.2.0之后
update(source, k, clearText);
}else{
//springboot 2.2.0之前
source.put(k, clearText);
}
});
}
private void update(Map source,Object key,String value){
try{
Field field = source.getClass().getDeclaredField("m");
field.setAccessible(true);
Map map = (Map) field.get(source);
map.put(key,value);
}catch (Exception e){
throw new RuntimeException(e);
}
}
private void setDecryptProperties(Map source) {
decryptPrefix = source.get("decrypt.prefix") == null ? decryptPrefix : String.valueOf(source.get("decrypt.prefix"));
decryptSuffix = source.get("decrypt.suffix") == null ? decryptSuffix : String.valueOf(source.get("decrypt.suffix"));
decryptKey = source.get("decrypt.key") == null ? decryptKey : String.valueOf(source.get("decrypt.key"));
}
}
yaml属性自动加密
@Component
public class EncryptRunner implements CommandLineRunner {
/**
* 文件路径
*/
private final String path = "/src/main/resources";
/**
* 文件名称
*/
private final String prefix = "application";
/**
* 要加密的属性字段
*/
private final Set<String> propSets = new HashSet<>(Arrays.asList(
"password"
));
@Autowired
private DecryptConfig decryptConfig;
@Override
public void run(String... args) throws Exception {
String userDir = System.getProperty("user.dir");
File dir = new File(userDir + File.separator + path);
//文件存在则加密
if(dir.exists()){
File[] files = dir.listFiles();
for(File file : files){
String name = file.getName();
if (name != null && name.startsWith(prefix)) {
encrypt(file);
}
}
}
}
/**
* 加密
*/
protected void encrypt(File file){
StringBuilder sb = new StringBuilder();
AtomicBoolean isUpdate = new AtomicBoolean(false);
List<String> list = FileUtil.readLines(file , "UTF-8");
if(list != null && list.size() > 0){
list.stream().forEach(line -> {
String split = ": ";
int index = line.indexOf(split);
boolean isNote = line.replace(" ", "").startsWith("#");
if(!isNote && index > -1 && index + split.length() < line.length()){
String data1 = line.substring(0, index);
String data2 = line.substring(index + split.length());
boolean flag = propSets.stream().anyMatch(prop -> data1.contains(prop));
if(flag && StringUtils.isNotEmpty(data2) &&
!data2.startsWith(decryptConfig.getDecryptPrefix())){
String encrypt = DecryptUtils.aesEncrypt(data2, decryptConfig.getDecryptKey());
sb.append(data1);
sb.append(split);
sb.append(decryptConfig.getDecryptPrefix());
sb.append(encrypt);
sb.append(decryptConfig.getDecryptSuffix());
isUpdate.set(true);
}else{
sb.append(line);
}
}else{
sb.append(line);
}
//根据操作系统识别换行符
sb.append(System.getProperty("line.separator"));
});
}
if(isUpdate.get()){
FileUtil.writeString(sb.toString(), file, "UTF-8");
}
}
}