我的任务是混淆配置文件中的密码。虽然我认为这不是正确的方法,但管理人员不同意…
因此,我正在研究的项目基于Spring Boot,我们正在使用YAML配置文件。当前密码为纯文本:
spring: datasource: url: jdbc:sqlserver://DatabaseServer driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver username: ele password: NotTheRealPassword
这个想法是要有一些特殊的语法来支持模糊或加密的密码:
spring: datasource: url: jdbc:sqlserver://DatabaseServer driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver username: ele password: password(Tm90VGhlUmVhbFBhc3N3b3Jk)
为了使其正常工作,我想使用正则表达式解析属性值,如果匹配,则用反混淆/解密后的值替换该值。
但是,如何截获该属性值?
如果最终使它起作用。(主要感谢github上的stephane-deraco)
解决方案的关键是要实现的类ApplicationContextInitializer<ConfigurableApplicationContext>。我叫它PropertyPasswordDecodingContextInitializer。
ApplicationContextInitializer<ConfigurableApplicationContext>
PropertyPasswordDecodingContextInitializer
主要的问题是让弹簧来使用它ApplicationContextInitializer。重要信息可以在参考资料中找到。我使用 META-INF / spring.factories选择 了以下内容的方法:
ApplicationContextInitializer
org.springframework.context.ApplicationContextInitializer=ch.mycompany.myproject.PropertyPasswordDecodingContextInitializer
在PropertyPasswordDecodingContextInitializer使用PropertyPasswordDecoder和实现类,目前为简单起见Base64PropertyPasswordDecoder。
PropertyPasswordDecoder
Base64PropertyPasswordDecoder
PropertyPasswordDecodingContextInitializer.java
package ch.mycompany.myproject; import java.util.LinkedHashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.EnumerablePropertySource; import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.PropertySource; import org.springframework.stereotype.Component; @Component public class PropertyPasswordDecodingContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { private static final Pattern decodePasswordPattern = Pattern.compile("password\\((.*?)\\)"); private PropertyPasswordDecoder passwordDecoder = new Base64PropertyPasswordDecoder(); @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) { String decodedValue = decodePasswordsInString((String) rawValue); propertyOverrides.put(key, decodedValue); } } } } private String decodePasswordsInString(String input) { if (input == null) return null; StringBuffer output = new StringBuffer(); Matcher matcher = decodePasswordPattern.matcher(input); while (matcher.find()) { String replacement = passwordDecoder.decodePassword(matcher.group(1)); matcher.appendReplacement(output, replacement); } matcher.appendTail(output); return output.toString(); } }
PropertyPasswordDecoder.java
package ch.mycompany.myproject; public interface PropertyPasswordDecoder { public String decodePassword(String encodedPassword); }
Base64PropertyPasswordDecoder.java
package ch.mycompany.myproject; import java.io.UnsupportedEncodingException; import org.apache.commons.codec.binary.Base64; public class Base64PropertyPasswordDecoder implements PropertyPasswordDecoder { @Override public String decodePassword(String encodedPassword) { try { byte[] decodedData = Base64.decodeBase64(encodedPassword); String decodedString = new String(decodedData, "UTF-8"); return decodedString; } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } }
请注意,ApplicationContext在此阶段尚未完成初始化,因此自动装配或任何其他与Bean相关的机制将无法正常工作。