应用程序侦听器中的Spring Load应用程序属性 [英] Spring load application properties in Application listener

查看:56
本文介绍了应用程序侦听器中的Spring Load应用程序属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在Spring中侦听应用程序事件并解密已加密(具有加密前缀)的应用程序属性.这个想法是创建一个Spring组件,如果属性值被加密,则在加载环境时将自动解密spring属性.

I am trying to listen to application events in Spring and decrypt application properties which are encrypted(has an encrypt prefix). The idea is to create a Spring component that will automatically decrypt spring properties when the environment is loaded if the property value is encrypted.

这需要与具有application.env.properties文件的旧版Spring应用程序一起使用(不带Spring Boot),以及具有yaml文件中定义的属性的最新Spring Boot应用程序.源代码,不应依赖于Spring Boot并可以与任何Spring版本一起使用.

This needs to work with legacy spring apps(without spring boot) which has application.env.properties files and also the more recent spring boot apps which has properties defined in yaml files.Should be able to decrypt any spring property regardless of the source and should not depend on spring boot and work with any spring version.

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();我可以在此处看到系统属性,但不能看到应用程序.知道如何在这里加载应用程序属性并对其解密吗?谢谢

But the problem is, i don't see the application properties returned on this line, ((ConfigurableEnvironment) environment).getPropertySources(); I can see the system properties here, but not application. Any idea how can i load application properties here and decrypt them? Thanks

添加样本属性文件.想法是将此通用jar添加为各种Web应用程序的Maven依赖项,包括旧版和新版Spring Boot.以下属性文件的格式为myapp.env.properties,并且myapp.system.properties具有定义的env.但是spring boot应用程序使用.yaml文件.服务和安全密码必须具有前缀,因此需要解密.

Adding a sample properties file. The idea is to add this generic jar as a maven dependency on various webapps, both legacy and new spring boot ones. The below properties file is of format myapp.env.properties and myapp.system.properties has the env defined. But the spring boot apps use .yaml files. Service and security password needs to be decrypted as they have the prefix.

base.url=http://localhost:8080/myapp
service.password={decrypt}123456789==
security.password={decrypt}abcdefgh==
help.email.address=support@gmail.com

推荐答案

我结束了实现自定义ApplicationContextInitializer的过程,并重写了initialize()以从环境中解密属性并以高优先级插入它们,以便它们重写加密的值.>

I ended implementing a custom ApplicationContextInitializer and override the initialize() to decrypt properties from the environment and insert them with high priority so they override the encrypted values.

    public class PropertyContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {


       @Override
       public void initialize( ConfigurableApplicationContext applicationContext ) {
          ConfigurableEnvironment environment = applicationContext.getEnvironment();
          for ( PropertySource<?> propertySource : environment.getPropertySources() ) {
             Map<String, Object> propertyOverrides = new LinkedHashMap<>();
// call to decrypt method
             decryptProperty( propertySource, propertyOverrides );
             if ( !propertyOverrides.isEmpty() ) {
                PropertySource<?> decodedProperties = new MapPropertySource( "decrypt " + propertySource.getName(),
                      propertyOverrides );
                environment.getPropertySources().addBefore( propertySource.getName(), decodedProperties );
             }
          }
       }

这篇关于应用程序侦听器中的Spring Load应用程序属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆