Spring配置文件中:密码明文改为密文处理方式(通用方法) ...

打印 上一主题 下一主题

主题 981|帖子 981|积分 2943

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
目录

一、配景    
二、思路
A) 普通方式
B) 得当bootstrap.properties方式
三、示例
A) 普通方式(毗连Redis集群)
A) 普通方式(毗连RocketMQ)
B) 得当bootstrap.properties方式
四、总结


一、配景    

  SpringBoot和SpringCloud中涉及多个配置文件,配置文件中对于密码默认是明文方式,这种方式在生产情况一样平常是不被答应的。为避免配置文件中出现明文,应当在配置文件中配置为密文,然后在启动时在程序内部完成解密。
    本文提供了通用的处理方式,可以适配以下几类配置文件:


  • 本地bootstrap.properties   在Spring的Bean创建之前的配置
  • 本地application.properties   在Spring的配置,包罗带profile情况的配置
  • 配置中心上的配置(比方nacos上的Data ID)   
   为了适应配置文件涉及密码由明文改为密文,需要分为两步:
①将配置文件中涉及密文的配置项配置为密笔墨符串(需本身加密计算得到);
②在Spring启动中读取密笔墨符串并解密还原。
二、思路

       对于以上第②步Spring启动时的处理,由于以上配置文件在Spring加载的机遇和生命周期不同,有两种处理方式:
A) 普通方式

      由于Spring中的对本地application.properties或者配置中心上的配置(比方nacos上的Data ID)在Spring Bean创建过程中,会有对应的配置Bean(通过注解@Configuration说明的Java类),Spring会自动根据读取分析配置文件并赋值给Bean。
      因此,若需要对密笔墨符串并解密还原,可以对配置Bean(通过注解@Configuration说明的Java类)进行继承,Override重写对应的set方法,完成解密。
B) 得当bootstrap.properties方式

      对于Spring Cloud,在bootstrap阶段还未创建Bean,所以以上Override重写对应的set方法并不实用。所以对于bootstrap.properties配置文件。可通过实现EnvironmentPostProcessor接口,来捕获Environment配置,解密后将配置新值设置到Environment中。
三、示例

A) 普通方式(毗连Redis集群)

      下面以毗连Redis集群为例进行说明,毗连Redis集群的配置项可以在本地application.properties或者配置中心上的配置(比方nacos上的Data ID),且此中spring.redis.password配置项值已经设置为密文。
      下面代码对配置Bean(通过注解@Configuration说明的Java类RedisProperties)进行继承,Override重写对应的set方法。Java代码如下:
  1. package 包指定忽略,请自定;
  2. import 忽略解密计算工具类SystemSecurityAlgorithm,请自定;
  3. import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.context.annotation.Primary;
  6. import org.springframework.util.StringUtils;
  7. /**
  8. * 连接Redis集群的配置类【通过@Configuration覆盖原Bean机制】:
  9. *   1、连接Redis的连接password不得出现明文,故需在properties配置文件中配置为加密密文(加密算法Java类为:SystemSecurityAlgorithm),然后在启动时通过本类解密
  10. *   2、贵金属应用服务采用多数据中心DataCenter部署。而每逻辑中心均有独立的Redis集群。 应用服务应连接同逻辑中心内的Redis集群,既北京的应用服务不应该连接合肥Redis集群
  11. *     既:对于同服务的不同实例,应根据服务实例所在逻辑中心(具体见枚举ServiceConstant.DataCenter定义的逻辑中心)连接相同逻辑中心下的Redis集群。
  12. *     因此:
  13. *        a).以Spring标准Redis连接配置为基础,对nodes值中各个IP端口配置,在各IP前增加一个大写字母:该IP所在DataCenter数据中心的英文代码
  14. *        b).以Spring标准Redis连接配置为基础,对password值改为可配多个密码,以逗号分隔,每个密码前增加一个大写字母,该密码是连接哪个Redis集群的DataCenter数据中心的英文代码
  15. * 为支持以上,定制化开发本类,实现处理最终还原至Spring标准连接Redis的配置,以供lettuce创建连接池。
  16. *  -----------------------------------------------------------
  17. * 机制适用性:
  18. * 除了通过@Configuration覆盖原Bean机制,还有通过实现EnvironmentPostProcessor接口机制。两种机制适用性说明如下:
  19. *   bootstrap.properties配置文件(bootstrap阶段,还未创建Bean) →→适合→→ 【实现EnvironmentPostProcessor接口机制】
  20. *   本地application.properties配置文件(正常SpringBoot启动,通过@Configuration注解的Bean) →→适合→→ 【实现EnvironmentPostProcessor接口机制】和【通过@Configuration覆盖原Bean机制】均可
  21. *   从Nacos等配置中心获取得到的配置文件 →→适合→→ 【通过@Configuration覆盖原Bean机制】
  22. *
  23. */
  24. @Configuration
  25. @Primary // 由于默认RedisProperties作为配置类会自动创建Bean。 为避免存在两个同类型(RedisProperties)Bean,所以本类通过注解Primary,使得只有本类生效。相当于替代默认RedisProperties
  26. public class GjsRedisProperties extends RedisProperties {
  27.     private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(GjsRedisProperties.class);
  28.     @Override
  29.     public void setPassword(String orginPassword) {
  30.         if(StringUtils.hasText(orginPassword)) {
  31.             // 对密文解密并设置
  32.             if (StringUtils.hasText(orginPassword) && orginPassword.length() >= 32 ) { // 如果满足密码密文的长度及大小写要求,视为密文,解密
  33.                 String padStr = SystemSecurityAlgorithm.decryptStr(orginPassword);
  34.                 log.debug("连接Redis配置项spring.redis.password: 解密前orginPassword=[{}], 解密后padStr=[{}]", orginPassword, padStr); //为避免密码泄露,仅debug才输出明文
  35.                 log.info("连接Redis配置项spring.redis.password: 对密文orginPassword=[{}]已完成解密", orginPassword);
  36.                 super.setPassword(padStr);
  37.             } else { // 不满足密码密文的长度及大小写要求(视为明文,不解密),保持不变
  38.                 log.warn("连接Redis配置项spring.redis.password的:orginPassword=[{}]不满足密码密文的长度及大小写要求(视为明文,不解密),保持不变", orginPassword);
  39.                 super.setPassword(orginPassword);
  40.             }
  41.         }
  42.     }
  43. }
复制代码
A) 普通方式(毗连RocketMQ)

      下面以毗连RocketMQ为例进行说明,毗连RocketMQ的配置项可以在本地application.properties或者配置中心上的配置(比方nacos上的Data ID),且此中rocketmq.producer.secret-keyrocketmq.consumer.secret-key配置项值已经设置为密文。
      下面代码对配置Bean(通过注解@Configuration说明的Java类RocketMQProperties)进行继承,Override重写对应的set方法。Java代码如下:
  1. package 包指定忽略,请自定;
  2. import 忽略解密计算工具类SystemSecurityAlgorithm,请自定;
  3. import org.apache.rocketmq.spring.autoconfigure.RocketMQProperties;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.context.ConfigurableApplicationContext;
  6. import org.springframework.context.annotation.Configuration;
  7. import org.springframework.context.annotation.Primary;
  8. import org.springframework.core.env.ConfigurableEnvironment;
  9. import org.springframework.core.env.MapPropertySource;
  10. import org.springframework.util.StringUtils;
  11. import java.util.HashMap;
  12. import java.util.Map;
  13. /**
  14. * 连接RocketMQ的配置类【通过@Configuration覆盖原Bean机制】:
  15. *   因连接RocketMQ的secret-key不得出现明文,故需在properties配置文件中配置为加密密文(加密算法Java类为:SystemSecurityAlgorithm),然后在启动时通过本类解密
  16. *  -----------------------------------------------------------
  17. * 机制适用性:
  18. * 除了通过@Configuration覆盖原Bean机制,还有通过实现EnvironmentPostProcessor接口机制。两种机制适用性说明如下:
  19. *   bootstrap.properties配置文件(bootstrap阶段,还未创建Bean) →→适合→→ 【实现EnvironmentPostProcessor接口机制】
  20. *   本地application.properties配置文件(正常SpringBoot启动,通过@Configuration注解的Bean) →→适合→→ 【实现EnvironmentPostProcessor接口机制】和【通过@Configuration覆盖原Bean机制】均可
  21. *   从Nacos等配置中心获取得到的配置文件 →→适合→→ 【通过@Configuration覆盖原Bean机制】
  22. *
  23. */
  24. @Configuration
  25. @Primary // 由于默认RocketMQProperties作为配置类会自动创建Bean。 为避免存在两个同类型(RocketMQProperties)Bean,所以本类通过注解Primary,使得只有本类生效。相当于替代默认RocketMQProperties
  26. public class GjsRocketMQProperties extends RocketMQProperties {
  27.     final private String KEYNAME_PRODUCER_SECRET = "rocketmq.producer.secret-key";
  28.     final private String KEYNAME_CONSUMER_SECRET = "rocketmq.consumer.secret-key";
  29.     @Autowired
  30.     ConfigurableApplicationContext springContext;
  31.     private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(GjsRocketMQProperties.class);
  32.     @Override
  33.     public void setProducer(Producer producer) {
  34.         final String orginSecretKey = producer.getSecretKey();
  35.         // 对密文解密并设置
  36.         if (StringUtils.hasText(orginSecretKey) && orginSecretKey.length() >= 32) { // 如果满足密码密文的长度及大小写要求,视为密文,解密
  37.             String padStr = SystemSecurityAlgorithm.decryptStr(orginSecretKey);
  38.             log.debug("连接RocketMQ配置项{}: 解密前orginSecretKey=[{}], 解密后padStr=[{}]", KEYNAME_PRODUCER_SECRET, orginSecretKey, padStr); //为避免密码泄露,仅debug才输出明文
  39.             log.info("连接RocketMQ配置项{}: 对密文orginSecretKey=[{}]已完成解密", KEYNAME_PRODUCER_SECRET, orginSecretKey);
  40.             producer.setSecretKey(padStr);
  41.             // 由于RocketMQ在构建DefaultRocketMQListenerContainer过程中,会从Spring的Environment中获取配置。
  42.             // 附调用关系简要说明如下:
  43.             //     org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer.afterPropertiesSet()
  44.             //       org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer.initRocketMQPushConsumer()
  45.             //         org.apache.rocketmq.spring.support.RocketMQUtil.getRPCHookByAkSk()
  46.             //           org.springframework.core.env.AbstractEnvironment.resolveRequiredPlaceholders()
  47.             //             ......
  48.             //               org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertyResolver.findPropertyValue()
  49.             // 因此一并修改环境中的值,使其能取得新值
  50.             modifyEnvironmentValue(springContext.getEnvironment(), KEYNAME_PRODUCER_SECRET, padStr);
  51.         } else { // 不满足密码密文的长度及大小写要求(视为明文,不解密),保持不变
  52.             log.warn("连接RocketMQ配置项rocketmq.producer.secret-key值=[{}]不满足密码密文的长度及大小写要求(视为明文,不解密),保持不变", orginSecretKey);
  53.         }
  54.         super.setProducer(producer);
  55.     }
  56.     @Override
  57.     public void setConsumer(PushConsumer pushConsumer) {
  58.         final String orginSecretKey = pushConsumer.getSecretKey();
  59.         // 对密文解密并设置
  60.         if (StringUtils.hasText(orginSecretKey) && orginSecretKey.length() >= 32 ) { // 如果满足密码密文的长度及大小写要求,视为密文,解密
  61.             String padStr = SystemSecurityAlgorithm.decryptStr(orginSecretKey);
  62.             log.debug("连接RocketMQ配置项{}: 解密前orginSecretKey=[{}], 解密后padStr=[{}]", KEYNAME_CONSUMER_SECRET, orginSecretKey, padStr); //为避免密码泄露,仅debug才输出明文
  63.             log.info("连接RocketMQ配置项{}: 对密文orginSecretKey=[{}]已完成解密", KEYNAME_CONSUMER_SECRET, orginSecretKey);
  64.             pushConsumer.setSecretKey(padStr);
  65.             // 由于RocketMQ在构建DefaultRocketMQListenerContainer过程中,会从Spring的Environment中获取配置。
  66.             // 附调用关系简要说明如下:
  67.             //     org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer.afterPropertiesSet()
  68.             //       org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer.initRocketMQPushConsumer()
  69.             //         org.apache.rocketmq.spring.support.RocketMQUtil.getRPCHookByAkSk()
  70.             //           org.springframework.core.env.AbstractEnvironment.resolveRequiredPlaceholders()
  71.             //             ......
  72.             //               org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertyResolver.findPropertyValue()
  73.             // 因此一并修改环境中的值,使其能取得新值
  74.             modifyEnvironmentValue(springContext.getEnvironment(), KEYNAME_CONSUMER_SECRET, padStr);
  75.         } else { // 不满足密码密文的长度及大小写要求(视为明文,不解密),保持不变
  76.             log.warn("连接RocketMQ配置项{}的值=[{}]不满足密码密文的长度及大小写要求(视为明文,不解密),保持不变", KEYNAME_CONSUMER_SECRET, orginSecretKey);
  77.         }
  78.         super.setConsumer(pushConsumer);
  79.     }
  80.     @Override
  81.     public void setPullConsumer(PullConsumer pullConsumer) {
  82.         final String orginSecretKey = pullConsumer.getSecretKey();
  83.         // 对密文解密并设置
  84.         if (StringUtils.hasText(orginSecretKey) && orginSecretKey.length() >= 32 ) { // 如果满足密码密文的长度及大小写要求,视为密文,解密
  85.             String padStr = SystemSecurityAlgorithm.decryptStr(orginSecretKey);
  86.             log.debug("连接RocketMQ配置项{}: 解密前orginSecretKey=[{}], 解密后padStr=[{}]", KEYNAME_CONSUMER_SECRET, orginSecretKey, padStr); //为避免密码泄露,仅debug才输出明文
  87.             log.info("连接RocketMQ配置项{}: 对密文orginSecretKey=[{}]已完成解密", KEYNAME_CONSUMER_SECRET, orginSecretKey);
  88.             pullConsumer.setSecretKey(padStr);
  89.             // 由于RocketMQ在构建DefaultRocketMQListenerContainer过程中,会从Spring的Environment中获取配置。
  90.             // 附调用关系简要说明如下:
  91.             //     org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer.afterPropertiesSet()
  92.             //       org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer.initRocketMQPushConsumer()
  93.             //         org.apache.rocketmq.spring.support.RocketMQUtil.getRPCHookByAkSk()
  94.             //           org.springframework.core.env.AbstractEnvironment.resolveRequiredPlaceholders()
  95.             //             ......
  96.             //               org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertyResolver.findPropertyValue()
  97.             // 因此一并修改环境中的值,使其能取得新值
  98.             modifyEnvironmentValue(springContext.getEnvironment(), KEYNAME_CONSUMER_SECRET, padStr);
  99.         } else { // 不满足密码密文的长度及大小写要求(视为明文,不解密),保持不变
  100.             log.warn("连接RocketMQ配置项{}的值=[{}]不满足密码密文的长度及大小写要求(视为明文,不解密),保持不变", KEYNAME_CONSUMER_SECRET, orginSecretKey);
  101.         }
  102.         super.setPullConsumer(pullConsumer);
  103.     }
  104.     /**
  105.      * 对Spring的Environment的配置项的值修改为新值
  106.      * @param environment Spring的Environment对象
  107.      * @param keyName 配置项名
  108.      * @param newValue 新值
  109.      */
  110.     private void modifyEnvironmentValue(ConfigurableEnvironment environment, final String keyName, String newValue) {
  111.         if(!environment.containsProperty(keyName)) {
  112.             log.warn("当前Spring的environment中不存在名为{}的配置项", keyName);
  113.             return;
  114.         }
  115.         if(environment.getProperty(keyName, "").equals(newValue)) {
  116.             log.debug("当前Spring的environment中配置项{}的值已与新值相同,无需修改", keyName);
  117.             return;
  118.         }
  119.         Map<String, Object> map = new HashMap<>(); //用于存放新值
  120.         map.put(keyName, newValue);
  121.         // 若有map有值,则把该map作为PropertySource加入列表中,以实现:把environment中对应key的value覆盖为新值
  122.         // 必须加到First并且不能存在两个相同的Name的MapPropertySource,值覆盖才能生效
  123.         environment.getPropertySources().addFirst(new MapPropertySource("modifyEnvironmentValue-"+keyName, map));
  124.         log.info("已对Spring的Environment的配置项{}的值修改为新值", keyName);
  125.     }
  126. }
复制代码
B) 得当bootstrap.properties方式

      下面以毗连Nacos配置中心为例进行说明,需要在本地bootstrap.properties配置文件中指定毗连Nacos配置中心的Nacos用户名、密码、服务端地址、Data ID等信息。bootstrap.properties配置文件有关毗连Nacos配置中心雷同如下:
  1. #Nacos配置中心及注册中心的authenticate鉴权用户名和密码(需Nacos服务端开启auth鉴权)
  2. spring.cloud.nacos.username=nacos
  3. spring.cloud.nacos.password=760dee29f9fc82af0cc1d6074879dc39
  4. #Nacos配置中心服务端的地址和端口(形式ip:port,ip:port,...) 。注:nacos-client1.x会按顺序选其中地址进行连接(前个连接失败则自动选后一个)。nacos-client2.x会随机选其中地址进行连接(若连接失败则自动另选)
  5. spring.cloud.nacos.config.server-addr=ip1:8848,ip2:8848,ip3:8848,ip4:8848
  6. #Data ID的前缀(如果不设置,则默认取 ${spring.application.name})
  7. #spring.cloud.nacos.config.prefix=
  8. #默认指定为开发环境
  9. #spring.profiles.active=
  10. #Nacos命名空间,此处不设置,保持默认
  11. #spring.cloud.nacos.config.namespace=
  12. #配置组(如果不设置,则默认为DEFAULT_GROUP)
  13. spring.cloud.nacos.config.group=G_CONFIG_GJS_SERVICE
  14. #指定文件后缀(如果不设置,则默认为properties)
  15. spring.cloud.nacos.config.file-extension=properties
  16. #以下为全局Data ID
  17. spring.cloud.nacos.config.shared-configs[0].data-id=NacosRegDiscoveryInfo.properties
  18. spring.cloud.nacos.config.shared-configs[0].group=G_CONFIG_GJS_GLOBALSHARED
  19. spring.cloud.nacos.config.shared-configs[0].refresh=true
  20. spring.cloud.nacos.config.shared-configs[1].data-id=XXXXX.properties
  21. spring.cloud.nacos.config.shared-configs[1].group=G_CONFIG_GJS_GLOBALSHARED
  22. spring.cloud.nacos.config.shared-configs[1].refresh=true
  23. spring.cloud.nacos.config.shared-configs[2].data-id=YYYYY.properties
  24. spring.cloud.nacos.config.shared-configs[2].group=G_CONFIG_GJS_GLOBALSHARED
  25. spring.cloud.nacos.config.shared-configs[2].refresh=true
复制代码
此中spring.cloud.nacos.password配置项值已经设置为密文。
      下面的代码通过实现EnvironmentPostProcessor接口,来捕获配置,并将配置新值设置到Environment中。Java代码如下:
  1. package 包指定忽略,请自定;
  2. import 忽略解密计算工具类SystemSecurityAlgorithm,请自定;
  3. import org.apache.commons.logging.Log;
  4. import org.springframework.boot.ConfigurableBootstrapContext;
  5. import org.springframework.boot.SpringApplication;
  6. import org.springframework.boot.env.EnvironmentPostProcessor;
  7. import org.springframework.boot.logging.DeferredLogFactory;
  8. import org.springframework.core.Ordered;
  9. import org.springframework.core.env.ConfigurableEnvironment;
  10. import org.springframework.core.env.MapPropertySource;
  11. import org.springframework.util.StringUtils;
  12. import java.util.HashMap;
  13. import java.util.Map;
  14. /**
  15. * 本类通过实现EnvironmentPostProcessor接口,实现在Spring启动过程中从environment中读取指定的key值,处理后,然后把environment中对应key的value覆盖为新值。
  16. * 通过本类已经实现对bootstrap阶段的配置文件处理:
  17. *   因连接Nacos的password不得出现明文,故bootstrap配置文件中为加密密文(加密算法Java类为:SystemSecurityAlgorithm),然后在启动时通过本类解密
  18. * -----------------------------------------------------------
  19. * 注意:
  20. *   a) 需要在META-INF下的spring.factories文件中配置本类后,本类才会生效(才被Spring扫描识别到)
  21. *   b) 因为本类是通过实现EnvironmentPostProcessor接口方式,所以本类在SpringCloud启动过程中会被调用两次:
  22. *         首先是在bootstrap配置文件加载后(SpringCloud为支持配置中心的bootstrap阶段)
  23. *         其次是在application配置文件加载后(SpringBoot的正常启动时加载配置文件阶段)
  24. * 机制适用性:
  25. * 除了通过实现EnvironmentPostProcessor接口机制,还有通过@Configuration覆盖原Bean机制。两种机制适用性说明如下:
  26. *   bootstrap.properties配置文件(bootstrap阶段,还未创建Bean) →→适合→→ 【实现EnvironmentPostProcessor接口机制】
  27. *   本地application.properties配置文件(正常SpringBoot启动,通过@Configuration注解的Bean) →→适合→→ 【实现EnvironmentPostProcessor接口机制】和【通过@Configuration覆盖原Bean机制】均可
  28. *   从Nacos等配置中心获取得到的配置文件 →→适合→→ 【通过@Configuration覆盖原Bean机制】
  29. *
  30. */
  31. public class GjsEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
  32.     /**
  33.      * The default order for the processor.  值越小,优先级越高
  34.      * 因bootstrap配置文件是通过{@link org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor}完成加载处理
  35.      * 由于本EnvironmentPostProcessor类需等待SpringCloud对bootstrap配置文件后才能执行,所以本EnvironmentPostProcessor类优先级需更低
  36.      */
  37.     public static final int ORDER = Ordered.HIGHEST_PRECEDENCE + 50;
  38.     private final DeferredLogFactory logFactory;
  39.     private final Log logger;
  40.     public GjsEnvironmentPostProcessor(DeferredLogFactory logFactory,
  41.                                        ConfigurableBootstrapContext bootstrapContext) {
  42.         this.logFactory = logFactory;
  43.         this.logger = logFactory.getLog(getClass());
  44.     }
  45.     @Override
  46.     public int getOrder() {
  47.         return ORDER;
  48.     }
  49.     /**
  50.      * 从environment中读取指定的key,并进行解密,解密后的结果放入map对象中
  51.      * @param environment 已经有的Spring环境
  52.      * @param keyName 指定的key名
  53.      * @param map 若完成解密,则将解密后的结果放入map对象
  54.      */
  55.     private void decodePwd(ConfigurableEnvironment environment, String keyName, Map<String, Object> map ) {
  56.         if(!environment.containsProperty(keyName)) {
  57.             this.logger.debug("EnvironmentPostProcessor 当前Spring的environment中不存在名为"+keyName+"的配置项");
  58.             return;
  59.         }
  60.         final String origalValue = environment.getProperty(keyName);
  61.         // 对密文解密并设置
  62.         if (StringUtils.hasText(origalValue) && origalValue.length() >= 32) { // 如果满足密码密文的长度及大小写要求,视为密文,解密
  63.             String padStr = SystemSecurityAlgorithm.decryptStr(origalValue);
  64.             this.logger.debug("EnvironmentPostProcessor 配置项"+keyName+"原值=["+origalValue+"], 解密后值=["+padStr+"]"); //为避免在日志中密码泄露,仅debug才输出明文
  65.             this.logger.info("EnvironmentPostProcessor 配置项"+keyName+"原值=["+origalValue+"]已完成解密");
  66.             map.put(keyName, padStr);
  67.         }else {
  68.             this.logger.warn("EnvironmentPostProcessor 配置项"+keyName+"值=["+origalValue+"]不满足密码密文的长度及大小写要求(视为明文,不解密),保持不变");
  69.         }
  70.     }
  71.     @Override
  72.     public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
  73.         this.logger.debug("EnvironmentPostProcessor before PropertySources size=" + environment.getPropertySources().size());
  74.         this.logger.debug("EnvironmentPostProcessor before PropertySources : " + environment.getPropertySources());
  75.         Map<String, Object> map = new HashMap<>(); //用于存放新值
  76.         decodePwd(environment, "spring.cloud.nacos.password", map);
  77.         if(!map.isEmpty()) {
  78.             // 若有map有值,则把该map作为PropertySource加入列表中,以实现:把environment中对应key的value覆盖为新值
  79.             // 必须加到First并且不能存在两个相同的Name的MapPropertySource,值覆盖才能生效
  80.             environment.getPropertySources().addFirst(new MapPropertySource("afterDecodePassword", map));
  81.         }
  82.         this.logger.debug("EnvironmentPostProcessor after PropertySources size=" + environment.getPropertySources().size());
  83.         this.logger.debug("EnvironmentPostProcessor after PropertySources : " + environment.getPropertySources());
  84.     }
  85. }
复制代码
四、总结

      通过以上两种方式,可解决Spring各类配置文件对配置密文的适配和处理。
      同时不但仅用于密文,凡是需对配置文件的内容在启动时进行改变情况都可以按以上方式进行处理。比方启动时对配置项值中多个IP进举措态使用等情形。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

涛声依旧在

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表