Spring Boot 扩展点学习二 EnvironmentPostProcessor配置项解密

226 阅读1分钟

有时为了数据安全,需要对相关配置文件中某些属性进行加密,例如数据库连接、账号密码,及其他相关加密秘钥等

EnvironmentPostProcessor

EnvironmentPostProcessorConfigurableEnvironment被完全初始化之前修改环境的配置

下面使用EnvironmentPostProcessor进行相关配置项解密

1.创建 MyEnvironmentPostProcessor实现EnvironmentPostProcessor接口

import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;

import java.util.HashMap;
import java.util.Map;


public class MyEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {

        MutablePropertySources propertySources = environment.getPropertySources();
        for (PropertySource<?> propertySource : propertySources) {
            // 获取YML、Properties类型属性源文件
            if (propertySource instanceof OriginTrackedMapPropertySource) {
                Map<String,Object> propertySourceMap = new HashMap<>();
                OriginTrackedMapPropertySource source = (OriginTrackedMapPropertySource) propertySource;
                for (String propertyName : source.getPropertyNames()) {
                    Object sourceValue = source.getProperty(propertyName);
                    // 查找带有指定前缀的配置项
                    if (sourceValue instanceof String && sourceValue.toString().startsWith("{'abcd'}")) {
                        String value = (String) sourceValue;
                        // 模拟解密
                        value = value.replace("{'abcd'}","");
                        propertySourceMap.put(propertyName,value);
                    }
                }

                // addFirst,添加到最高优先级
                if (!propertySourceMap.isEmpty()) {
                    propertySources.addFirst(new OriginTrackedMapPropertySource(propertySource.getName(),propertySourceMap));
                }

            }
        }

    }

    // 优先级最高
    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}

2.注册EnvironmentPostProcessor

src/main/resources/META-INF/spring.factories文件中添加以下行:

org.springframework.boot.env.EnvironmentPostProcessor=\
  com.cpu.mem.cpumemory.beans.MyEnvironmentPostProcessor

注意事项

  • EnvironmentPostProcessorApplicationEnvironmentPreparedEvent事件之后调用,这意味着在此阶段Environment已经包含了从application.propertiesapplication.yml文件中读取的属性,以及其他来源的配置。
  • EnvironmentPostProcessor的顺序很重要,Spring Boot允许注册多个EnvironmentPostProcessor,它们将按照在spring.factories文件中声明的顺序执行。因此,如果你想覆盖其他处理器的行为,需要考虑Ordered接口的实现来控制执行顺序。