Spring Properties Decryption

时光毁灭记忆、已成空白 提交于 2021-02-07 11:44:05

问题


We have mix of some legacy spring apps which are not yet migrated to spring-boot or spring cloud and also spring boot apps. I am working on creating a Spring component that will automatically decrypt spring properties when the environment is loaded if the property value is encrypted and has a prefix. The properties can be in .properties files(for legacy apps) or in .yaml files(newer spring boot apps).

The component should be able to decrypt any spring property regardless of the source, and should work with any spring version and not tied to spring boot.The component should also transparently decrypt properties. It should read passphrase from a property file, so the passphrase file needs to be loaded in the beginning.

We have our own ecrypt/decrypt and don't want to use jaspyt.

Things tried so far:

I liked this approach of creating an ApplicationListener, but this is tied up with spring boot(ApplicationEnvironmentPreparedEvent). With Spring events like ContextRefreshed or ContextStart , i don't see how can i get ConfigurableApplicationContext/ConfigurableEnvironment. Anyone created a Listener for encrypt/decrypt withouth spring boot/cloud?

I also created a custom ApplicationContextInitializer, and added it to web.xml's context-param, but this doesn't seems to be working. When i debug into it, i don't think it is loading/reading properties from my app.properties file.

       @Component
    public class DecryptingPropertyContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

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

        private void decodePasswords(PropertySource<?> source, Map<String, Object> propertyOverrides) {
          if ( source instanceof EnumerablePropertySource ) {
             EnumerablePropertySource<?> enumerablePropertySource = (EnumerablePropertySource<?>) source;
             for ( String key : enumerablePropertySource.getPropertyNames() ) {
                Object rawValue = source.getProperty( key );
                if ( rawValue instanceof String ) {
                   //decrypt logic here
propertyOverrides.put( key, decryptedValue );
                }
             }
          }
        }
    }

Does anyone had to do something similar or has any better ideas ? Is there a way i can listen to application events and then process? Appreciate your help


回答1:


You can write your own PropertiesFactoryBean and override createProperties to decrypt encrypted values:

public class DecryptingPropertiesFactoryBean extends PropertiesFactoryBean {
  @Override
  protected Properties createProperties() throws IOException {
    final Properties encryptedProperties = super.createProperties();
    final Properties decryptedProperties = decrypt(encryptedProperties);
    return decryptedProperties;
  }
}

and a PropertySourcesPlaceholderConfigurer bean using these properties:

@Configuration
public class PropertiesConfiguration {

  @Bean
  public static DecryptingPropertiesFactoryBean propertyFactory() {
    final DecryptingPropertiesFactoryBean factory = new DecryptingPropertiesFactoryBean();
    final Resource[] propertyLocations = new Resource[] {
        new FileSystemResource(new File("path/to/file.properties"))
    };
    factory.setLocations(propertyLocations);
    return factory;
  }

  @Bean
  public static Properties properties() throws Exception {
    return propertyFactory().getObject();
  }

  @Bean
  public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
    final PropertySourcesPlaceholderConfigurer bean = new PropertySourcesPlaceholderConfigurer();
    bean.setIgnoreResourceNotFound(true);
    bean.setIgnoreUnresolvablePlaceholders(false);
    bean.setProperties(properties());
    return bean;
  }
}


来源:https://stackoverflow.com/questions/55996663/spring-properties-decryption

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!