Я пытаюсь прослушать события приложения в Spring и расшифровать свойства приложения, которые зашифрованы (имеет префикс шифрования). Идея состоит в том, чтобы создать компонент Spring, который будет автоматически расшифровывать свойства Spring при загрузке среды, если значение свойства зашифровано.
Это необходимо для работы с унаследованными весенними приложениями (без весенней загрузки), в которых есть файлы application.env.properties, а также с более свежими весенними загрузочными приложениями, свойства которых определены в файлах yaml. Может иметь возможность дешифровать любое свойство пружины независимо от исходник и не должен зависеть от весенней загрузки и работать с любой весенней версией.
public class DecryptingPropertiesListener
implements ApplicationListener<ContextRefreshedEvent>, Ordered {
public static final String PREFIX_KEY = "{decrypt}";
private String prefix;
private Encrypter encrypter = Encrypter.defaultInstance();
@Override
public void onApplicationEvent(ContextRefreshedEvent event ) {
Environment environment = event.getApplicationContext().getEnvironment();
prefix = environment.getProperty(PREFIX_KEY, "{encrypted}");
final MutablePropertySources propertySources = ((ConfigurableEnvironment) environment).getPropertySources();
Set<String> encryptedKeys = getKeysOfEncryptedPropertyValues(environment, propertySources);
addDecryptedValues(environment, propertySources, encryptedKeys);
}
private Set<String> getKeysOfEncryptedPropertyValues(Environment environment, MutablePropertySources propertySources) {
return streamFromIterator(propertySources.iterator())
.filter(EnumerablePropertySource.class::isInstance)
.map(EnumerablePropertySource.class::cast)
.flatMap(source -> asList(source.getPropertyNames()).stream())
.filter(this::isNotEncryptionConfigProperty)
.filter(key -> isEncrypted(environment.getProperty(key)))
.collect(toSet());
}
private boolean isNotEncryptionConfigProperty(String key) {
return !PREFIX_KEY.equals(key);
}
private Stream<PropertySource<?>> streamFromIterator(Iterator<PropertySource<?>> iterator) {
Iterable<PropertySource<?>> iterable = () -> iterator;
return StreamSupport.stream(iterable.spliterator(), false);
}
private void addDecryptedValues(Environment environment, MutablePropertySources propertySources, Set<String> encryptedKeys) {
Map<String, Object> decryptedProperties = encryptedKeys.stream()
.collect(toMap(
key -> key,
key -> decryptPropertyValue(environment.getProperty(key))));
propertySources.addFirst(new MapPropertySource("decryptedValues", decryptedProperties));
}
private String decryptPropertyValue(String encryptedPropertyValue) {
try {
return encrypter.decryptIfEncrypted(encryptedPropertyValue);
}
catch (EncryptionException e) {
throw new RuntimeException("Unable to decrypt property value '" + encryptedPropertyValue + "'", e);
}
}
private boolean isEncrypted(Object propertyValue) {
return propertyValue != null && propertyValue instanceof String && ((String)propertyValue).startsWith(prefix);
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
Но проблема в том, что я не вижу свойств приложения, возвращаемых в этой строке ((среда ConfigurableEnvironment)) .getPropertySources ();
Я могу видеть свойства системы здесь, но не приложение. Любая идея, как я могу загрузить свойства приложения здесь и расшифровать их?
Спасибо
РЕДАКТИРОВАТЬ: Добавление примера файла свойств. Идея состоит в том, чтобы добавить этот универсальный jar-файл в зависимости от различных веб-приложений, как старых, так и новых.
Файл свойств ниже имеет формат myapp.env.properties, а для myapp.system.properties определен env. Но весенние загрузочные приложения используют файлы .yaml. Служебный и защитный пароль необходимо расшифровать, так как они имеют префикс.
base.url=http://localhost:8080/myapp
service.password={decrypt}123456789==
security.password={decrypt}abcdefgh==
help.email.address=support@gmail.com