配置文件加密实践

2018/08/26 Spring

背景

最近开展的项目,审查方要求配置文件不得出现敏感信息的明文信息,比如数据库密码就是敏感信息。由于需要审查的项目都是基于Spring框架实现的业务需求。传统的SpringWeb项目 与 SpringBoot 项目。所以接下来介绍这两种项目的如何实现加密方案。

SrpingWeb 项目

基于Spring项目,我们的项目加载配置文件时是如下方式:

<bean
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:config.properties</value>
            </list>
        </property>
    </bean>

其实读取配置文件的实现类是均是 PropertyPlaceholderConfigurer 如果想对配置文件的读取值做处理,可以继承 PropertyPlaceholderConfigurer 类并覆写 convertProperties 方法。

public class ConvertPwdPropertyConfigurer extends PropertyPlaceholderConfigurer{
	@Override
	protected String convertProperty(String propertyName, String propertyValue) {

    //所有值开头以 encrypt: 开始的,则进行解密
		if(propertyValue.contains("encrypt:")){
			try {
        //解密工具类
				return DecryptConfigUtil.getDecryptShareString(propertyValue, false);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
    //无需解密
		return propertyValue;
	}
}

并且把上述配置更改为如下即可:

<bean
        class="xxx.config.ConvertPwdPropertyConfigurer">
        <property name="locations">
            <list>
                <value>classpath:config.properties</value>
            </list>
        </property>
    </bean>

具体的加解密方案自己定即可。

SpringBoot 项目

对于此框架的配置加密实现,是依赖于 jasypt 的。

pom 依赖

<dependency>
			<groupId>com.github.ulisesbocchio</groupId>
			<artifactId>jasypt-spring-boot-starter</artifactId>
			<version>2.0.0</version>
		</dependency>

注入 EncryptablePropertyResolver

注入一个默认约定名称的 bean ,此实例需继承 EncryptablePropertyResolver

@Configuration
@Slf4j
public class EncryptionPropertyConfig {

    @Bean(name="encryptablePropertyResolver")
    public EncryptablePropertyResolver encryptablePropertyResolver() {
        return new EncryptionPropertyResolver();
    }
}

EncryptionPropertyResolver 实现:

public class EncryptionPropertyResolver implements EncryptablePropertyResolver {

        @Override
        public String resolvePropertyValue(String value) {
            if(StringUtils.isBlank(value)) {
                return value;
            }
            if(value.startsWith("encrypt:")) {
                 log.debug("密文信息配置"+value);
                return resolveDESValue(value);
            }
            // 不需要解密的值直接返回
            log.debug("明文信息配置"+value);
            return value;
        }
        //解密实现
        private String resolveDESValue(String value) {
            String decryptShareString ="";
            try{
                decryptShareString = DecryptConfigUtil.getDecryptShareString(value, true);
            }catch (Exception e){
                e.printStackTrace();
            }
            return decryptShareString;
        }
    }

结束语

综上是基于Spring框架两种情况的配置文件 加密预处理实现。具体如何实现加密解密逻辑需自己定义,建议:可以使用RSA公钥加密私钥解密的方案,公钥公开出去对需加密的内容进行加密,私钥写进代码里,启动时进行如上操作的解密。(私钥如何管理不做过多探讨)

update

好多项目都以来的Druid连接池,有些情况对数据库密码的加密依赖于Druid的实现。我是不推荐的,其实质时使用随机生成的私钥对密码进行加密,然后使用公钥解密,公钥于密文信息配置到配置文件中,也就意味着对方拿到配置文件也就可以对密文进行解密,所以不知意义何在。

参考:https://yq.aliyun.com/articles/182720

Search

    Table of Contents