Springboot自定义配置解密处理器

org.springframework.boot.env.EnvironmentPostProcessor是一个"环境后处理器",让你有机会在应用启动的早期阶段,动态地添加、修改或删除环境中的属性(Properties),比如来自配置文件 (application.yml)、系统属性、命令行参数等的值。

一、创建一个类实现 EnvironmentPostProcessor 接口

java 复制代码
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;

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

/**
 * 系统环境后置处理器
 */
@Slf4j
public class DecryptEnvPostProcessor implements EnvironmentPostProcessor {

    private static final Set<String> ENCRYPTED_KEYS = Set.of(
            "spring.datasource.password"
    );

    private static final AES aes = SecureUtil.aes("Encrypt-20251106".getBytes());

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment env, SpringApplication application) {
        Map<String, Object> decryptedValues = new HashMap<>();
        for (PropertySource<?> source : env.getPropertySources()) {
            if (!(source instanceof EnumerablePropertySource<?> eps)) {
                continue;
            }
            for (String keyName : eps.getPropertyNames()) {
                if (!ENCRYPTED_KEYS.contains(keyName)) {
                    continue;
                }
                Object value = eps.getProperty(keyName);
                if (!(value instanceof String strValue)) {
                    continue;
                }
                //判断是否为加密值(用ENC()包裹)
                if (!strValue.startsWith("ENC(") || !strValue.endsWith(")")) {
                    continue;
                }
                String cipherText = strValue.substring(4, strValue.length() - 1);
                try {
                    //解密
                    String plainText = aes.decryptStr(cipherText);
                    decryptedValues.put(keyName, plainText);
                } catch (Exception e) {
                    log.error("解密配置项 [" + keyName + "] 失败,保持原密文: " + e.getMessage());
                }
            }
        }
        //将解密后的值添加到最高优先级的PropertySource中
        if (!decryptedValues.isEmpty()) {
            MapPropertySource decryptedPropertySource = new MapPropertySource("decryptedProperties", decryptedValues);
            env.getPropertySources().addFirst(decryptedPropertySource);
        }
    }
}

二、在 src/main/resources/META-INF/spring.factories 文件中进行声明

java 复制代码
org.springframework.boot.env.EnvironmentPostProcessor=com.**.config.DecryptEnvPostProcessor

三、生成密码

java 复制代码
    @Test
    public void test() {
        AES aes = SecureUtil.aes("Encrypt-20251106".getBytes());
        //加密
        String encryptHex = aes.encryptHex("123456");
        log.info("加密后 (Hex): " + encryptHex);
        //解密
        String decryptStr = aes.decryptStr(encryptHex);
        log.info("解密后: " + decryptStr);
    }

四、在配置文件中应用

相关推荐
每天一道题5 分钟前
CAP、Raft 与多数派:分布式系统如何达成一致?
分布式·后端·微服务
前端的日常26 分钟前
一个人+AI做情侣食谱小程序,0 费用的服务器
前端·后端
IT_陈寒1 小时前
Vue的v-for里用了个临时变量,页面直接挂了
前端·人工智能·后端
步行cgn2 小时前
@ResponseBody 详解:Spring MVC 中把返回值直接写入响应体
java·spring·mvc
ServBay2 小时前
本地模型已经跑起来了,Copilot Fusion 为什么还要联网?
后端·ai编程·github copilot
武子康2 小时前
H3-World 的动作没按时发生,先检查时间线变成了什么
人工智能·后端·agent
苍何2 小时前
腾讯 Buddy One 来了,办公全家桶一键打通WorkBuddy(附教程)
后端
jason成都3 小时前
RTKLIB 的 Java 移植版来了:rtklib-java v3.3.0 功能全景
java·gnss·rtklib·rtklib_java
LazyHunter93 小时前
JDK 28:Java 下一步方向解析与新特性展望
java·jdk
m0_639906943 小时前
Java 重写 Override 与重载 Overload 区别、访问修饰符、static 关键字
java·开发语言