java - Spring属性解密

标签 java spring spring-boot encryption properties

我们混合了一些尚未迁移到 spring-boot 或 spring cloud 的遗留 spring 应用程序以及 spring boot 应用程序。我正在创建一个 Spring 组件,如果属性值被加密并具有前缀,它将在加载环境时自动解密 spring 属性。这些属性可以在 .properties 文件中(对于遗留应用程序)或在 .yaml 文件中(较新的 spring boot 应用程序)。

无论来源如何,该组件都应该能够解密任何 spring 属性,并且应该与任何 spring 版本一起工作,而不是绑定(bind)到 spring boot。该组件还应该透明地解密属性。它应该从属性文件中读取密码,因此需要在开始时加载密码文件。

我们有自己的加密/解密,不想使用 jaspyt。

到目前为止尝试过的事情:

我喜欢 this创建 ApplicationListener 的方法,但这与 spring boot(ApplicationEnvironmentPreparedEvent) 相关联。对于 ContextRefreshed 或 ContextStart 之类的 Spring 事件,我不知道如何获取 ConfigurableApplicationContext/ConfigurableEnvironment。有人在没有 spring boot/cloud 的情况下创建了用于加密/解密的监听器吗?

我还创建了一个自定义的 ApplicationContextInitializer,并将其添加到 web.xml 的上下文参数中,但这似乎不起作用。当我调试它时,我不认为它正在从我的 app.properties 文件中加载/读取属性。

       @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 );
                }
             }
          }
        }
    }

有没有人必须做类似的事情或有更好的想法?有没有办法可以监听应用程序事件然后进行处理? 感谢您的帮助

最佳答案

您可以编写自己的 PropertiesFactoryBean 并覆盖 createProperties 以解密加密值:

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

和一个使用这些属性的 PropertySourcesPlaceholderConfigurer bean:

@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;
  }
}

关于java - Spring属性解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55996663/

相关文章:

java - 如何在 Java 中将文件输入分段

java - 新文件被识别为文件夹

java - 来自java的R,没有图形: is it worth moving to JRI

尝试管理多个共享公共(public)基类的类时出现 Spring 错误?

spring - spring-boot webapp 准备好后自动启动浏览器

java - 如何制作 Stream 的副本,以便在使用它时使用 Java 8 中的副本?

java - Spring security antMatcher 不起作用

java - Hibernate通过非主键获取实体并更新它+ Spring mvc

java - 如何通过maven导入多个Spring应用程序,其中每个依赖项位于自己的类路径上(以避免依赖项冲突)?

java - Spring REST api OAuth2 验证来自外部授权服务器的 token