nacos&apollo配置中心自动化解密

本文介绍了如何在项目中同时使用Nacos和Apollo配置中心时,利用Jasypt框架对数据库用户名、密码等敏感信息进行自动化解密,包括添加依赖、创建工具类以及在Apollo和Nacos中的应用和配置调整。
摘要由CSDN通过智能技术生成

背景

配置中心中的配置往往存在需要加密的配置,比如数据库用户名、密码等。由于项目中同时使用nacos&apollo,所以需要实现一下两种配置中心的自动化解密

1.封装jaspyt

1.1引用jar包

以jaspyt作为解密框架,这里jaspyt没有使用starter的原因是可能各项目springboot版本不同,可能存在兼容性问题。如果是新项目可以考虑使用统一版本的starter实现自动化解密

  <dependency>
      <groupId>org.jasypt</groupId>
      <artifactId>jasypt</artifactId>
      <version>1.9.3</version>
 </dependency>

1.2增加工具类

从网上找一个简单的工具类:

 /**
     * 需解密的标记头
     */
    private static final String ENCRYPTED_VALUE_PREFIX = "ENC(";

    /**
     * 需解密的标记尾
     */
    private static final String ENCRYPTED_VALUE_SUFFIX = ")";

    /**
     *  解密密码
     */
    public static final String JASYPT_PASSWORD = "xxx";


    /**
     * 判断是否是 prefixes/suffixes 包裹的属性
     *
     * @param value
     * @return
     */
    public static boolean isEncryptedValue(final String value) {
        if (value == null) {
            return false;
        }
        final String trimmedValue = value.trim();
        return (trimmedValue.startsWith(ENCRYPTED_VALUE_PREFIX) &&
                trimmedValue.endsWith(ENCRYPTED_VALUE_SUFFIX));
    }

    /**
     * 如果通过 prefixes/suffixes 包裹的属性,那么返回密文的值;如果没有被包裹,返回原生的值。
     *
     * @param value
     * @return
     */
    private static String getInnerEncryptedValue(final String value) {
        return value.substring(
                ENCRYPTED_VALUE_PREFIX.length(),
                (value.length() - ENCRYPTED_VALUE_SUFFIX.length()));
    }


    /**
     * Jasypt生成加密结果
     *
     * @param password 配置文件中设定的加密密码 jasypt.encryptor.password
     * @param value    待加密值
     * @return
     */
    public static String encryptPwd(String password, String value) {
        PooledPBEStringEncryptor encryptOr = new PooledPBEStringEncryptor();
        encryptOr.setConfig(cryptOr(password));
        return encryptOr.encrypt(value);
    }

    /**
     * 解密
     *
     * @param password 配置文件中设定的加密密码 jasypt.encryptor.password
     * @param value    待解密密文
     * @return
     */
    public static String decyptPwd(String password, String value) {
        PooledPBEStringEncryptor encryptOr = new PooledPBEStringEncryptor();
        encryptOr.setConfig(cryptOr(password));
        return encryptOr.decrypt(isEncryptedValue(value) ? getInnerEncryptedValue(value) : value);
    }

    /**
     * @param password salt
     * @return
     */
    public static SimpleStringPBEConfig cryptOr(String password) {
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        config.setPassword(password);
        config.setAlgorithm(StandardPBEByteEncryptor.DEFAULT_ALGORITHM);
        config.setKeyObtentionIterations("1000");
        config.setPoolSize("1");
        config.setProviderName(null);
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
        config.setStringOutputType("base64");
        return config;
    }

2.apollo

2.1 引用jar包

使用了apollo的1.3的客户端:

 <dependency>
      <groupId>com.ctrip.framework.apollo</groupId>
      <artifactId>apollo-client</artifactId>
      <version>1.3.0</version>
 </dependency>
2.2 增加自动化解密功能

经过断点调试,发现apollo更新配置时都会经过这个方法:

修改如下,使用了jaspyt包中的加解密方法,实现了配置在同步后的自动化解密:

    Set<Object> keys = newConfigProperties.keySet();
        for (Object k : keys) {
            String key = k.toString();
            String value = newConfigProperties.getProperty(key);
            //判断是否是规则密文
            if (JasyptUtils.isEncryptedValue(value)) {
                try {
                    // 解密然后重新赋值
                    String decyptVal = JasyptUtils.decyptPwd(JasyptUtils.JASYPT_PASSWORD, value);
                    newConfigProperties.setProperty(key, decyptVal);
                } catch (Exception e) {
                    logger.error("错误信息是:{}, 错误堆栈是:{}", ExceptionUtil.getMessage(e),
                            ExceptionUtil.stacktraceToString(e));
                }
            }
        }
2.3 在apollo中装配自定义模块

需要替换下面的模块实现配置自动解密:

新建一个相同的类,覆盖掉这个工厂类即可。最后通过apollo提供的spi接口com.ctrip.framework.apollo.internals.Injector替换掉这个模块装配器

3.nacos

3.1 引用jar包
<dependency>
     <groupId>com.alibaba.cloud</groupId>
     <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
     <version>2021.1</version>
</dependency>
3.2增加自动化解密功能

经过断点调试,发现nacos同步配置时都会经过这个方法:

该类是在这个配置器中自动装配的:

经过分析源码得知,这个配置器是通过springcloud上下文启动的,并且没有加@ConditionalOnMissingBean注解,在spring上下文中替换比较麻烦。所以最简便的方法是增加一个同名包和同名bean:

修改方法loadNacosDataIfPresent:

private void loadNacosDataIfPresent(final CompositePropertySource composite,
                                        final String dataId, final String group, String fileExtension,
                                        boolean isRefreshable) {
        if (null == dataId || dataId.trim().length() < 1) {
            return;
        }
        if (null == group || group.trim().length() < 1) {
            return;
        }
        NacosPropertySource propertySource = this.loadNacosPropertySource(dataId, group, fileExtension, isRefreshable);
        Map<String, Object> source = propertySource.getSource();
        for (String key : source.keySet()) {
            String value = source.get(key).toString();
            if (JasyptUtils.isEncryptedValue(value)) {
                try {
                    String decryptValue = JasyptUtils.decyptPwd(JasyptUtils.JASYPT_PASSWORD, value);
                    source.put(key, decryptValue);
                } catch (Exception e) {
                    log.error("nacos解密失败!请检察是否包含正确的密文:错误信息是:{}, 错误堆栈是:{}", ExceptionUtil.getMessage(e),
                            ExceptionUtil.stacktraceToString(e));
                }
            }

        }
        this.addFirstPropertySource(composite, propertySource, false);
    }

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值