概要
奇安信代码卫士检测,jar包内容.zip发现配置文件中密码明文显示,得出结论为中等级缺陷,系统安全性将会受到威胁,故将配置文件中存储的密码经过jasypt加密处理的密码值。
代码
1.加密解密工具类 AESUtil
。
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class AESUtil {
private static final String ALGORITHM = "AES";
private static final String TRANSFORMATION = "AES/ECB/PKCS5Padding";
// 生成一个随机的AES密钥
public static SecretKey generateKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
keyGenerator.init(128); // 128位AES密钥
return keyGenerator.generateKey();
}
private static final String FIXED_KEY = "abcdef0123456789"; // 16字节(128位)的十六进制密钥
public static SecretKeySpec getFixedKey() {
// AES密钥长度可以是128位(16字节)、192位(24字节)或256位(32字节)
// 这里我们使用128位的密钥,即16个十六进制字符
byte[] keyBytes = new byte[16];
for (int i = 0; i < FIXED_KEY.length(); i += 2) {
// 每两个字符表示一个字节,将其转换为字节数组
String hexByte = FIXED_KEY.substring(i, i + 2);
int intValue = Integer.parseInt(hexByte, 16);
keyBytes[i / 2] = (byte) intValue;
}
return new SecretKeySpec(keyBytes, "AES");
}
// AES加密
public static String encrypt(String data) throws Exception {
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, getFixedKey());
byte[] encryptedBytes = cipher.doFinal(data.getBytes("UTF-8"));
return Base64.getEncoder().encodeToString(encryptedBytes);
}
// AES解密
public static String decrypt(String encryptedData) throws Exception {
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, getFixedKey());
byte[] decodedBytes = Base64.getDecoder().decode(encryptedData);
byte[] decryptedBytes = cipher.doFinal(decodedBytes);
return new String(decryptedBytes, "UTF-8");
}
// 示例:使用AES加密和解密
public static void main(String[] args) throws Exception {
SecretKey secretKey = getFixedKey();
System.out.println("secretKey: " + secretKey);
String originalData = "test@123";
String encryptedData = encrypt(originalData);
System.out.println("Encrypted: " + encryptedData);
String decryptedData = decrypt(encryptedData);
System.out.println("Decrypted: " + decryptedData);
}
}
2.创建应用程序上下文之前,添加或者修改环境配置 DecryptEnvironmentPostProcessor
。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.env.*;
import java.util.Properties;
public class DecryptEnvironmentPostProcessor implements EnvironmentPostProcessor {
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
Properties props = new Properties(); // 临时存储需要替换的配置
// 假设加密密码前缀为 "ENC(",后缀为 ")"
MutablePropertySources propertySources = environment.getPropertySources();
for (PropertySource<?> propertySource : propertySources) {
if (propertySource instanceof EnumerablePropertySource) {
EnumerablePropertySource<?> enumerablePropertySource = (EnumerablePropertySource<?>) propertySource;
String[] propertyNames = enumerablePropertySource.getPropertyNames();
// 遍历所有配置key:value
for (String propertyName : propertyNames) {
String propertyVal = environment.getProperty(propertyName);
// 根据自己写的规则来解析那些配置是需要解密的
if (propertyVal != null && propertyVal.startsWith("ENC(") && propertyVal.endsWith(")")) {
// 解析得到加密的数据
String encryptedValue = propertyVal.substring(4, propertyVal.length() - 1);
// 调用自定义工具类解密
String decryptedValue = null;
try {
decryptedValue = AESUtil.decrypt(encryptedValue);
} catch (Exception e) {
throw new RuntimeException(e);
}
// 保存需要替换的配置
props.put(propertyName, decryptedValue);
}
}
}
}
// 添加解密后的属性到环境中
if (!props.isEmpty()) {
PropertiesPropertySource pps = new PropertiesPropertySource("decryptedProperties", props);
environment.getPropertySources().addFirst(pps);
}
}
}
3.最后一定要在resources/META-INF/spring.factories中添加使之生效。
org.springframework.boot.env.EnvironmentPostProcessor=\
com.test.system.DecryptEnvironmentPostProcessor
4.配置文件 application.yml
。
password: ENC(加密后的密码)
小结
好使的话记得点赞+关注吧