Spring Cloud 2020之后版本针对nacos账号密码加密

nacos账号加密方式参考:https://blog.csdn.net/weixin_39418319/article/details/140544019?spm=1001.2014.3001.5502

但是,引入Spring Cloud 2020之后版本后,有些项目可能因为Spring Cloud不再默认支持bootstrap配置,把bootstrap配置文件去掉了,项目中所有配置都写在了application.yaml里,那上面加密方式就会在NacosConfigDataLocationResolver这个类中由于无法解密连接报错,针对这种情况,可以用下面这种方式,重写对应nacos配置类

解决方案

在项目中创建package com.alibaba.cloud.nacos,重写的类必须和nacos中的类放在相同路径下才能覆盖nacos本身的类

重写com.alibaba.cloud.nacos.NacosConfigProperties

nacos中原来的com.alibaba.cloud.nacos.NacosConfigProperties复制过来,修改overrideFromEnv这个方法,加上解密代码,解密代码自己实现就可以,我是使用了jasypt的PropertyValueEncryptionUtils

    private void overrideFromEnv() {
        if (environment == null) {
            return;
        }
        if (StringUtils.isEmpty(this.getServerAddr())) {
            String serverAddr = environment
                    .resolvePlaceholders("${spring.cloud.nacos.config.server-addr:}");
            if (StringUtils.isEmpty(serverAddr)) {
                serverAddr = environment.resolvePlaceholders(
                        "${spring.cloud.nacos.server-addr:127.0.0.1:8848}");
            }
            this.setServerAddr(serverAddr);
        }
		// 这里的加解密可以自己实现,我的项目是没有在nacos.config配置下加账号和密码的,所以取得都是spring.cloud.nacos.username和spring.cloud.nacos.password的值
        if (StringUtils.isEmpty(this.getUsername())) {
            this.setUsername(
                    environment.resolvePlaceholders("${spring.cloud.nacos.username:}"));
        }
        if (StringUtils.isEmpty(this.getPassword())) {
            this.setPassword(
                    environment.resolvePlaceholders("${spring.cloud.nacos.password:}"));
        }
        // 获取加密盐值
        try {
            String saltStr = environment.resolveRequiredPlaceholders("${spring.cloud.nacos.salt:}");
            this.setSalt(saltStr);
        } catch (IllegalArgumentException e) {
            log.warn("spring.cloud.nacos.salt is Illegal Argument or empty!" );
        }
        String saltStr = this.getSalt();
        // 如果加密盐值不为空且username符合加密格式,则进行账号解密处理
        if (StringUtils.isNotBlank(saltStr) && PropertyValueEncryptionUtils.isEncryptedValue(this.getUsername())) {
            this.setUsername(decrypt(this.getUsername(), saltStr));
        }
        // 如果加密盐值不为空且password符合加密格式,则进行密码解密处理
        if (StringUtils.isNotBlank(saltStr) && PropertyValueEncryptionUtils.isEncryptedValue(this.getPassword())) {
            this.setPassword(decrypt(this.getPassword(), saltStr));
        }
    }

重写com.alibaba.cloud.nacos.configdata.NacosConfigDataLocationResolver

一样的方式复制原本类的内容,修改loadProperties方法

protected NacosConfigProperties loadProperties(
            ConfigDataLocationResolverContext context) {
        Binder binder = context.getBinder();
        BindHandler bindHandler = getBindHandler(context);

        NacosConfigProperties nacosConfigProperties;
        if (context.getBootstrapContext().isRegistered(NacosConfigProperties.class)) {
            nacosConfigProperties = context.getBootstrapContext()
                    .get(NacosConfigProperties.class);
        }
        else {
            nacosConfigProperties = binder
                    .bind("spring.cloud.nacos", Bindable.of(NacosConfigProperties.class),
                            bindHandler)
                    .map(properties -> binder
                            .bind(NacosConfigProperties.PREFIX,
                                    Bindable.ofInstance(properties), bindHandler)
                            .orElse(properties))
                    .orElseGet(() -> binder
                            .bind(NacosConfigProperties.PREFIX,
                                    Bindable.of(NacosConfigProperties.class), bindHandler)
                            .orElseGet(NacosConfigProperties::new));
        }
        // 获取加密盐值
        String salt = nacosConfigProperties.getSalt();
        // 如果加密盐值不为空且username符合加密格式,则进行账号解密处理
        String username = nacosConfigProperties.getUsername();
        if (StringUtils.isNotBlank(salt) && StringUtils.isNotBlank(username) && PropertyValueEncryptionUtils.isEncryptedValue(username)) {
            nacosConfigProperties.setUsername(NacosConfigProperties.decrypt(username, salt));
        }
        // 如果加密盐值不为空且password符合加密格式,则进行密码解密处理
        String password = nacosConfigProperties.getPassword();
        if (StringUtils.isNotBlank(salt) && StringUtils.isNotBlank(password) && PropertyValueEncryptionUtils.isEncryptedValue(password)) {
            nacosConfigProperties.setPassword(NacosConfigProperties.decrypt(password, salt));
        }
        return nacosConfigProperties;
    }

重写com.alibaba.cloud.nacos.NacosDiscoveryProperties

修改overrideFromEnv方法

public void overrideFromEnv(Environment env) {

        if (StringUtils.isEmpty(this.getServerAddr())) {
            String serverAddr = env
                    .resolvePlaceholders("${spring.cloud.nacos.discovery.server-addr:}");
            if (StringUtils.isEmpty(serverAddr)) {
                serverAddr = env.resolvePlaceholders(
                        "${spring.cloud.nacos.server-addr:127.0.0.1:8848}");
            }
            this.setServerAddr(serverAddr);
        }
        if (StringUtils.isEmpty(this.getNamespace())) {
            this.setNamespace(env
                    .resolvePlaceholders("${spring.cloud.nacos.discovery.namespace:}"));
        }
        if (StringUtils.isEmpty(this.getAccessKey())) {
            this.setAccessKey(env
                    .resolvePlaceholders("${spring.cloud.nacos.discovery.access-key:}"));
        }
        if (StringUtils.isEmpty(this.getSecretKey())) {
            this.setSecretKey(env
                    .resolvePlaceholders("${spring.cloud.nacos.discovery.secret-key:}"));
        }
        if (StringUtils.isEmpty(this.getLogName())) {
            this.setLogName(
                    env.resolvePlaceholders("${spring.cloud.nacos.discovery.log-name:}"));
        }
        if (StringUtils.isEmpty(this.getClusterName())) {
            this.setClusterName(env.resolvePlaceholders(
                    "${spring.cloud.nacos.discovery.cluster-name:}"));
        }
        if (StringUtils.isEmpty(this.getEndpoint())) {
            this.setEndpoint(
                    env.resolvePlaceholders("${spring.cloud.nacos.discovery.endpoint:}"));
        }
        if (StringUtils.isEmpty(this.getGroup())) {
            this.setGroup(
                    env.resolvePlaceholders("${spring.cloud.nacos.discovery.group:}"));
        }
        if (StringUtils.isEmpty(this.getUsername())) {
            this.setUsername(env.resolvePlaceholders("${spring.cloud.nacos.username:}"));
        }
        if (StringUtils.isEmpty(this.getPassword())) {
            this.setPassword(env.resolvePlaceholders("${spring.cloud.nacos.password:}"));
        }

        // 获取账号加密的盐值
        String salt = StringUtils.EMPTY;
        try {
            salt = environment.resolveRequiredPlaceholders("${spring.cloud.nacos.salt:}");
        } catch (IllegalArgumentException e) {
            log.warn("spring.cloud.nacos.salt is Illegal Argument or empty!" );
        }
        // 如果加密盐值不为空且username符合加密格式,则进行账号解密处理
        if (StringUtils.isNotBlank(salt) && StringUtils.isNotBlank(this.getUsername()) && PropertyValueEncryptionUtils.isEncryptedValue(this.getUsername())) {
            this.setUsername(decrypt(this.getUsername(), salt));
        }
        // 如果加密盐值不为空且password符合加密格式,则进行密码解密处理
        if (StringUtils.isNotBlank(salt) && StringUtils.isNotBlank(this.getPassword()) && PropertyValueEncryptionUtils.isEncryptedValue(this.getPassword())) {
            this.setPassword(decrypt(this.getPassword(), salt));
        }
    }

application.yaml中配置

spring:
  main:
    allow-circular-references: true
  mvc:
    pathmatch:
      matching-strategy: ANT_PATH_MATCHER
  config:
    activate:
      on-profile: dev
  cloud:
    nacos:
      server-addr: ****
      # nacos账号加密
      # ENC是因为延用了jasypt里PropertyValueEncryptionUtils的方法,ENC()中间的才是加密后的账号和密码
      username: ENC(*****)
      password: ENC(*****)
      # 自己定义的加密盐值
      salt: *****

说明

1、之前试过重新注入NacosConfigProperties bean,来加解密代码的方式,一直解决不了,因为NacosConfigDataLocationResolver的bean优先级最高,总是最先加载,所以目前想到的方式只有重写NacosConfigDataLocationResolver;

2、如果nacos账号有两个位置配置
spring.cloud.nacos.config.username
spring.cloud.nacos.config.password

spring.cloud.nacos.username
spring.cloud.nacos.password
这两个位置有优先级,注意区分

3、重写上面三个类是因为发现项目启动时这三个类都读取了账号并连接nacos,读取配置顺序是NacosConfigDataLocationResolver(读取spring.cloud.nacos.config配置)、NacosConfigProperties(读取spring.cloud.nacos下配置)、NacosDiscoveryProperties(服务发现)

参考链接

https://blog.csdn.net/weixin_39418319/article/details/140544019?spm=1001.2014.3001.5502

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值