配置文件中的敏感信息,如密碼,賬號這些都應該是秘文的,在程式獲取時,再將它們動態解密,這樣保證了配置信息的安全;在springboot中,有個resources\META-INF\spring.factories文件,他幫我們完成了自動裝配,開發過starter包的同學應該不會陌生,而在這個文件里, ...
配置文件中的敏感信息,如密碼,賬號這些都應該是秘文的,在程式獲取時,再將它們動態解密,這樣保證了配置信息的安全;在springboot中,有個resources\META-INF\spring.factories
文件,他幫我們完成了自動裝配,開發過starter包的同學應該不會陌生,而在這個文件里,我們也可以添加自定義的環境攔截器,對環境變數,配置信息等進行處理。
執行時機
EnvironmentPostProcessor
的實現類在 Spring Boot 應用程式啟動過程中的早期階段被載入和執行。具體來說,它們在 Spring Boot 的應用程式上下文創建之前執行。
載入 EnvironmentPostProcessor
的實現類的過程如下:
-
Spring Boot 應用程式啟動時,首先會載入並創建一個初始的環境(
ConfigurableEnvironment
)。 -
在初始化環境後,Spring Boot 會掃描 classpath 中的
META-INF/spring.factories
文件,以查找並載入配置在其中的EnvironmentPostProcessor
實現類。 -
一旦找到這些實現類,它們將被實例化和執行。在這個階段,你可以在應用程式環境載入之前進行一些自定義的配置或修改。
這使得 EnvironmentPostProcessor
成為一個非常早期的擴展點,允許你在應用程式環境初始化之前介入,並根據需要修改屬性源、配置屬性等。這對於在應用程式啟動時執行高級的自定義配置非常有用。
starter中的註冊
spring.factories
是 Spring Boot 中的一個特殊配置文件,用於自動裝配(auto-configuration)和其他 Spring Boot 特性的配置。在 spring.factories
文件中,你可以指定各種 Spring Boot 自動配置和其他擴展的類,包括 EnvironmentPostProcessor
。
EnvironmentPostProcessor
是 Spring Boot 的一個擴展點,用於在 Spring 應用程式的環境(Environment
)載入之後進行額外的自定義配置。具體來說,EnvironmentPostProcessor
允許你在 Spring Boot 應用程式啟動時修改環境屬性,這對於一些高級配置需求非常有用。
通過在 spring.factories
中配置 EnvironmentPostProcessor
,你可以實現一些高級的環境配置,例如根據特定條件動態修改屬性值,或者載入外部配置源。這為應用程式提供了更大的靈活性,允許你在應用程式啟動之前對環境進行精細的調整。
# Auto Configure
org.springframework.boot.env.EnvironmentPostProcessor=\
com.lind.common.env.MpwEnvironmentPostProcessor
自定義EnvironmentPostProcessor類,對敏感字元進行解密
/**
* 處理配置中的敏感信息,讀配置時完成解密操作.
*
* @author lind
* @date 2023/10/9 8:33
* @since 1.0.0
*/
public class EnvironmentPostProcessorDemo implements EnvironmentPostProcessor {
static final String MPW = "mpw.key";
static Logger logger = LoggerFactory.getLogger(EnvironmentPostProcessorDemo.class);
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
String mpwKey = null;
for (PropertySource<?> ps : (Iterable<PropertySource<?>>) environment.getPropertySources()) {
if (ps instanceof SimpleCommandLinePropertySource) { // jvm啟動時命令行參數
SimpleCommandLinePropertySource source = (SimpleCommandLinePropertySource) ps;
mpwKey = source.getProperty(MPW);
break;
}
if (ps instanceof OriginTrackedMapPropertySource) {// application.yml
OriginTrackedMapPropertySource source = (OriginTrackedMapPropertySource) ps;
if (source.containsProperty(MPW))
mpwKey = source.getProperty(MPW).toString();
break;
}
}
if (StringUtils.isNotBlank(mpwKey)) {
HashMap<String, Object> map = new HashMap<>();
for (PropertySource<?> ps : (Iterable<PropertySource<?>>) environment.getPropertySources()) {
if (ps instanceof OriginTrackedMapPropertySource) {
OriginTrackedMapPropertySource source = (OriginTrackedMapPropertySource) ps;
for (String name : source.getPropertyNames()) {
Object value = source.getProperty(name);
if (value instanceof String) {
String str = (String) value;
if (str.startsWith("mpw:")) {
String decrypt = AESNetUtils.decrypt(str.substring(4), mpwKey);
map.put(name,decrypt );
}
}
}
}
}
if (MapUtils.isNotEmpty(map))
environment.getPropertySources()
.addFirst((PropertySource) new MapPropertySource("custom-encrypt", map));
}
}
}
使用
- application.yml
mpw:
key: lind123456123456
author:
name: mpw:vpTzfVrH5eEbsFmSJO9bSw==
nationality: mpw:vFLIjoQXy4Pzo1/hOm8hWw==
- 單元測試代碼
@Test
public void mpwTest() {
// AESNetUtils.encrypt("中國人", "lind123456123456");//vFLIjoQXy4Pzo1/hOm8hWw==
System.out.println(SpringContextUtils.getEnvironment().getProperty("author.name"));
System.out.println(SpringContextUtils.getEnvironment().getProperty("author.nationality"));
}
- 測試結果
作者:倉儲大叔,張占嶺,
榮譽:微軟MVP
QQ:853066980
支付寶掃一掃,為大叔打賞!