1 对配置文件的解密
1.1 解密主体流程:
- 1 先在启动的时候注入一个PostProcessor
- 2 在PostProcessor中进行将普通的PropertySource转换成EncryptPropertySource
- 3 在EncryptPropertySource getProperty的时候 其中代理了PropertySource,进行获取源加密属性值,解密返回
2 将普通的PropertySource转换成EncryptPropertySource 加密属性资源类
2.1 转换EncryptPropertySource的步骤总结
- PostProcessor中获取MutablePropertySource
- 对MutablePropertySource中非EncryptPropertySource进行转换替换
2.2 转换EncryptPropertySource的 源码分析
- 在jaspcry-spring-boot-starter的jar包中找到自动装配的入口:spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.ulisesbocchio.jasyptspringboot.JasyptSpringBootAutoConfiguration
-
入口自动装配类 JasyptSpringBootAutoConfiguration
- Import 注册进来的配置类 EnableEncryptablePropertiesConfiguration
@Configuration @Import({EnableEncryptablePropertiesConfiguration.class}) public class JasyptSpringBootAutoConfiguration { public JasyptSpringBootAutoConfiguration() { } }
-
EnableEncryptablePropertiesConfiguration配置类中做了三个操作
- 引入两个配置类EncryptablePropertyResolverConfiguration和CachingConfiguration
- 注册了一个开启加密的Bean工厂后置处理EnableEncryptablePropertiesBeanFactoryPostProcessor
@Configuration @Import({EncryptablePropertyResolverConfiguration.class, CachingConfiguration.class}) @Slf4j public class EnableEncryptablePropertiesConfiguration { @Bean public static EnableEncryptablePropertiesBeanFactoryPostProcessor enableEncryptablePropertySourcesPostProcessor(final ConfigurableEnvironment environment, EncryptablePropertySourceConverter converter) { return new EnableEncryptablePropertiesBeanFactoryPostProcessor(environment, converter); } }
-
主要操作流程在EnableEncryptablePropertiesBeanFactoryPostProcessor中处理
- EncryptablePropertySourceConverter.convertPropertySources(propSources)转换包装类型
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { LOG.info("Post-processing PropertySource instances"); // 从environment中获取要处理的资源配置MutablePropertySources MutablePropertySources propSources = environment.getPropertySources(); // 将MutablePropertySources 中的所有的资源配置转换成加密PropertySource converter.convertPropertySources(propSources); }
-
EncryptablePropertySourceConverter
-
filter(ps -> !(ps instanceof EncryptablePropertySource)) 过滤获取非EncryptablePropertySource的PropertySources
-
将所有的非EncryptablePropertySource的PropertySource转换成EncryptablePropertySource
-
将转换之后的EncryptablePropertySource替换到MutablePropertySources中
-
处理完之后MutablePropertySources中全部都是EncryptablePropertySource(
EncryptableSystemEnvironmentPropertySourceWrapper,EncryptableMapPropertySourceWrapper,EncryptableEnumerablePropertySourceWrapper,EncryptablePropertySourceWrapper
)
-
public void convertPropertySources(MutablePropertySources propSources) {
StreamSupport.stream(propSources.spliterator(), false)
.filter(ps -> !(ps instanceof EncryptablePropertySource))
.map(this::makeEncryptable)
.collect(toList())
.forEach(ps -> propSources.replace(ps.getName(), ps));
}
转换EncryptablePropertySource实现类(EncryptableSystemEnvironmentPropertySourceWrapper,EncryptableMapPropertySourceWrapper,EncryptableEnumerablePropertySourceWrapper,EncryptablePropertySourceWrapper)的源码
public <T> PropertySource<T> makeEncryptable(PropertySource<T> propertySource) {
if (propertySource instanceof EncryptablePropertySource || skipPropertySourceClasses.stream().anyMatch(skipClass -> skipClass.equals(propertySource.getClass()))) {
log.info("Skipping PropertySource {} [{}", propertySource.getName(), propertySource.getClass());
return propertySource;
}
// 进行转换EncryptablePropertySource
PropertySource<T> encryptablePropertySource = convertPropertySource(propertySource);
log.info("Converting PropertySource {} [{}] to {}", propertySource.getName(), propertySource.getClass().getName(),
AopUtils.isAopProxy(encryptablePropertySource) ? "AOP Proxy" : encryptablePropertySource.getClass().getSimpleName());
return encryptablePropertySource;
}
进行实际转换的源码:
private <T> PropertySource<T> instantiatePropertySource(PropertySource<T> propertySource) {
PropertySource<T> encryptablePropertySource;
if (needsProxyAnyway(propertySource)) {
encryptablePropertySource = proxyPropertySource(propertySource);
} else if (propertySource instanceof SystemEnvironmentPropertySource) {
encryptablePropertySource = (PropertySource<T>) new EncryptableSystemEnvironmentPropertySourceWrapper((SystemEnvironmentPropertySource) propertySource, propertyResolver, propertyFilter);
} else if (propertySource instanceof MapPropertySource) {
encryptablePropertySource = (PropertySource<T>) new EncryptableMapPropertySourceWrapper((MapPropertySource) propertySource, propertyResolver, propertyFilter);
} else if (propertySource instanceof EnumerablePropertySource) {
encryptablePropertySource = new EncryptableEnumerablePropertySourceWrapper<>((EnumerablePropertySource) propertySource, propertyResolver, propertyFilter);
} else {
encryptablePropertySource = new EncryptablePropertySourceWrapper<>(propertySource, propertyResolver, propertyFilter);
}
return encryptablePropertySource;
}
在该处将所有的PropertySource都转换成了EncryptablePropertySource
3 解密配置文件依赖的EncryptPropertySource的加密实现类中的getProperty
3.1 解密流程
- 从Eviroment中获取属性值,依赖于EncryptPropertySource的getProperty
每个EncryptPropertySource实现类中都代理了CachingDelegateEncryptablePropertySource - CachingDelegateEncryptablePropertySource中代理了PropertySource
- CachingDelegateEncryptablePropertySource.getProperty 实现从PropertySource中获取加密密文,解密密文,返回解密值得解密流程
3.2 解密源码
挑选其中一个实现类EncryptableSystemEnvironmentPropertySourceWrapper,其他的实现类实现都一样
-
EncryptableSystemEnvironmentPropertySourceWrapper
- 构造方法中代理CachingDelegateEncryptablePropertySource
public class EncryptableSystemEnvironmentPropertySourceWrapper extends SystemEnvironmentPropertySource implements EncryptablePropertySource<Map<String, Object>> {
private final EncryptablePropertySource<Map<String, Object>> encryptableDelegate;
//1 注入了CachingDelegateEncryptablePropertySource代理类
public EncryptableSystemEnvironmentPropertySourceWrapper(SystemEnvironmentPropertySource delegate, EncryptablePropertyResolver resolver, EncryptablePropertyFilter filter) {
super(delegate.getName(), delegate.getSource());
encryptableDelegate = new CachingDelegateEncryptablePropertySource<>(delegate, resolver, filter);
}
@Override
public void refresh() {
encryptableDelegate.refresh();
}
//2 从代理的CachingDelegateEncryptablePropertySource中获取属性值
@Override
public Object getProperty(String name) {
return encryptableDelegate.getProperty(name);
}
@Override
public PropertySource<Map<String, Object>> getDelegate() {
return encryptableDelegate.getDelegate();
}
}
- CachingDelegateEncryptablePropertySource
- 注入PropertySource代理类
- getProperty 获取PropertySource中密文进行解密
public class CachingDelegateEncryptablePropertySource<T> extends PropertySource<T> implements EncryptablePropertySource<T> {
private final PropertySource<T> delegate;
private final EncryptablePropertyResolver resolver;
private final EncryptablePropertyFilter filter;
private final Map<String, Object> cache;
public CachingDelegateEncryptablePropertySource(PropertySource<T> delegate, EncryptablePropertyResolver resolver, EncryptablePropertyFilter filter) {
super(delegate.getName(), delegate.getSource());
Assert.notNull(delegate, "PropertySource delegate cannot be null");
Assert.notNull(resolver, "EncryptablePropertyResolver cannot be null");
Assert.notNull(filter, "EncryptablePropertyFilter cannot be null");
this.delegate = delegate;
this.resolver = resolver;
this.filter = filter;
this.cache = new HashMap<>();
}
@Override
public PropertySource<T> getDelegate() {
return delegate;
}
// 该处将获取属性进行了一步缓存,防止重复获取和解密
@Override
public Object getProperty(String name) {
// Can be called recursively, so, we cannot use computeIfAbsent.
if (cache.containsKey(name)) {
return cache.get(name);
}
synchronized (this) {
if (!cache.containsKey(name)) {
// 获取明文
Object resolved = getProperty(resolver, filter, delegate, name);
if (resolved != null) {
cache.put(name, resolved);
}
}
return cache.get(name);
}
}
@Override
public void refresh() {
cache.clear();
}
}
public interface EncryptablePropertySource<T> {
PropertySource<T> getDelegate();
Object getProperty(String name);
void refresh();
default Object getProperty(EncryptablePropertyResolver resolver, EncryptablePropertyFilter filter, PropertySource<T> source, String name) {
Object value = source.getProperty(name);
if (filter.shouldInclude(source, name) && value instanceof String) {
String stringValue = String.valueOf(value);
// 进行解密
return resolver.resolvePropertyValue(stringValue);
}
return value;
}
}
DefaultPropertyResolver 进行实际解密的位置
@Override
public String resolvePropertyValue(String value) {
return Optional.ofNullable(value)
.map(environment::resolvePlaceholders)
.filter(detector::isEncrypted)
.map(resolvedValue -> {
try {
String unwrappedProperty = detector.unwrapEncryptedValue(resolvedValue.trim());
String resolvedProperty = environment.resolvePlaceholders(unwrappedProperty);
//进行解密
return encryptor.decrypt(resolvedProperty);
} catch (EncryptionOperationNotPossibleException e) {
throw new DecryptionException("Unable to decrypt: " + value + ". Decryption of Properties failed, make sure encryption/decryption " +
"passwords match", e);
}
})
.orElse(value);
}