springboot配置文件密码类型配置项加密

DAY DAY UP 2021年09月01日 264次浏览

springboot配置文件密码类型配置项加密

实现EnvironmentPostProcessor接口,可以在项目启动初期对配置进行修改。
如下代码先获取配置文件的mysql、redis、mong等密码,然后在进行解密,最后将解密后的密码放回环境变量。
Ps:只取优先级高的配置

在resources/META-INF文件夹下新增spring.factories文件,内容如下

org.springframework.boot.env.EnvironmentPostProcessor=\
  com.linewell.zhzf.api.gateway.framework.security.SafetyEncryptProcessor

新增类 SafetyEncryptProcessor

public class SafetyEncryptProcessor implements EnvironmentPostProcessor {

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        String symmetricKey = null;
        String symmetricEncryptType = null;
        HashMap<String, Object> map = new HashMap<>();
        Boolean encryptValue = null;

        // 根据配置判断配置文件密码是否加密
        // 循环各配置文件
        for (PropertySource<?> ps : environment.getPropertySources()) {
            if (ps instanceof OriginTrackedMapPropertySource) {
                // 配置文件都为OriginTrackedMapPropertySource类型
                OriginTrackedMapPropertySource source = (OriginTrackedMapPropertySource) ps;
                // 循环单个文件的配置项
                for (String name : source.getPropertyNames()) {
                    if (encryptValue == null && StringUtils.equalsIgnoreCase("security.is-password-encrypt", name)) {
                        Object value = source.getProperty(name);
                        encryptValue = (Boolean) value;
                        continue;
                    }
                    if (StringUtils.isEmpty(symmetricKey) && StringUtils.equalsIgnoreCase("security.symmetric-key", name)) {
                        Object value = source.getProperty(name);
                        symmetricKey = (String) value;
                        continue;
                    }
                    if (StringUtils.isEmpty(symmetricEncryptType) && StringUtils.equalsIgnoreCase("security.symmetric-encrypt-type", name)) {
                        Object value = source.getProperty(name);
                        symmetricEncryptType = (String) value;
                        continue;
                    }
                    if (this.isEncryption(name, map)) {
                        Object value = source.getProperty(name);
                        String str = (String) value;
                        map.put(name, str);
                    }
                }
            }
        }
        if (!encryptValue) {
            // 配置文件密码非加密,直接返回
            return;
        }
        // 将处理的数据放入环境变量,并处于第一优先级上 (这里一定要注意,覆盖其他配置)
        if (!map.isEmpty()) {
            for (Map.Entry<String, Object> m : map.entrySet()) {
                map.put(m.getKey(), SecurityEncryptUtils.symmetricDecryption(String.valueOf(m.getValue()), symmetricKey, symmetricEncryptType));
            }
            environment.getPropertySources().addFirst(new MapPropertySource("prefixer", map));
        }
    }

    private boolean isEncryption(String name, HashMap<String, Object> map) {
        // 配置文件的密码需要经SM4Utils.encrypt 加密处理
        if (!map.containsKey("spring.datasource.password") && StringUtils.equalsIgnoreCase("spring.datasource.password", name)) {
            return true;
        }
        if (!map.containsKey("spring.datasource.password") && StringUtils.equalsIgnoreCase("spring.redis.password", name)) {
            return true;
        }
        if (!map.containsKey("spring.datasource.password") && StringUtils.equalsIgnoreCase("spring.data.mongodb.password", name)) {
            return true;
        }
        if (!map.containsKey("spring.datasource.password") && StringUtils.equalsIgnoreCase("dubbo.admin.root.password", name)) {
            return true;
        }
        if (!map.containsKey("dubbo.admin.guest.password") && StringUtils.equalsIgnoreCase("dubbo.admin.guest.password", name)) {
            return true;
        }
        return false;
    }
}