解决配置明文问题

本文探讨如何在Spring Boot应用中通过3DES加密技术保护MySQL和Redis的账号信息,包括配置文件加密解密策略、使用DESedeUtil工具类和环境后置处理器实现自动解密处理,确保敏感数据的安全性。
摘要由CSDN通过智能技术生成

我们把MySQL数据的账号信息,Redis的账号信息等都写在属性文件中,有信息暴露的风险,要保证账号密码的安全我们可以通过MD5或者3DES等加密方式来处理,那么怎么来实现呢?

解决思路

其实这个问题的解决思路还是比较清晰,就是在Spring注入DataSource对象或者RedisClient对象之前解密密文信息,并且覆盖掉之前的配置信息。

3DES的工具类

package com.alex;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;


/**
 * 3DES加密算法,主要用于加密用户id,身份证号等敏感信息,防止破解
 */
public class DESedeUtil {

    //秘钥
    public static final String  KEY = "~@#$y1a2n.&@+n@$%*(1)";
    //秘钥长度
    private static final int secretKeyLength = 24;
    //加密算法
    private static final String  ALGORITHM = "DESede";
    //编码
    private static final String CHARSET = "UTF-8";

    /**
     * 转换成十六进制字符串
     * @param key
     * @return
     */
    public static byte[] getHex(String key){
        byte[] secretKeyByte = new byte[24];
        try {
            byte[] hexByte;
            hexByte = new String(DigestUtils.md5Hex(key)).getBytes(CHARSET);
            //秘钥长度固定为24位
            System.arraycopy(hexByte,0,secretKeyByte,0,secretKeyLength);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return secretKeyByte;
    }

    /**
     * 生成密钥,返回加密串
     * @param key 密钥
     * @param encodeStr 将加密的字符串
     * @return
     */
    public static String  encode3DES(String key,String encodeStr){
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(getHex(key), ALGORITHM));
            return Base64.encodeBase64String(cipher.doFinal(encodeStr.getBytes(CHARSET)));
        }catch(Exception e){
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 生成密钥,解密,并返回字符串
     * @param key 密钥
     * @param decodeStr 需要解密的字符串
     * @return
     */
    public static String decode3DES(String key, String decodeStr){
        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(getHex(key),ALGORITHM));
            return new String(cipher.doFinal(new Base64().decode(decodeStr)),CHARSET);
        } catch(Exception e){
            e.printStackTrace();
        }
        return null;
    }


    public static void main(String[] args) {
        String userId = "root";
        String encode = DESedeUtil.encode3DES(KEY, userId);
        String decode = DESedeUtil.decode3DES(KEY, encode);
        System.out.println("用户id>>>"+userId);
        System.out.println("用户id加密>>>"+encode);
        System.out.println("用户id解密>>>"+decode);
    }

}

配置信息

spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/flowable_learn?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
spring.datasource.username=root
# 对通过3DES对密码加密
spring.datasource.password=vxiPSdZfapc=

在SpringBoot项目启动的时候在在刷新Spring容器之前执行的,所以我们要做的就是在加载完环境配置信息后,获取到配置的spring.datasource.password=vxiPSdZfapc=这个信息,然后解密并修改覆盖就可以了。

然后在属性文件的逻辑其实是通过发布事件触发对应的监听器来实现的

第一种就是写监听器然后监听之后去进行修改数据

第二种就是写后置处理器去修改数据

声明后置处理器(

  1. 用Stream流可以处理简单,但是他是java8之后的特性
  2. 不止一个加密的时候可以多个获取解密塞进去,参考:Spring Boot 配置文件加解密原理就这么简单 - 知乎)
package com.alex;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;

import java.util.HashMap;
import java.util.Map;

/**
 * @Auther: alex
 * @Date: 2022/3/26 23:19
 * @Description:
 */
public class SafetyEncryptProcessor implements EnvironmentPostProcessor {
    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        environment.getPropertySources().stream()
                .filter(m -> m instanceof OriginTrackedMapPropertySource)
                .forEach(m -> {
                    OriginTrackedMapPropertySource source = (OriginTrackedMapPropertySource) m;
                    for (String propertyName : source.getPropertyNames()) {
                        if ("spring.datasource.password".equals(propertyName)) {
                            Map<String, Object> map = new HashMap<>();
                            // 做解密处理
                            String property = (String) source.getProperty(propertyName);
                            String s = DESedeUtil.decode3DES(DESedeUtil.KEY, property);
                            System.out.println("密文:" + property);
                            System.out.println("解密后的:" + s);
                            map.put(propertyName, s);

                            // 注意要添加到前面,覆盖
                            environment.getPropertySources().addFirst(new MapPropertySource(propertyName, map));
                        }
                    }
                });
    }
}

然后在META-INF/spring.factories文件中注册

org.springframework.boot.env.EnvironmentPostProcessor=com.alex.SafetyEncryptProcessor

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值