Java配置敏感信息自动解密的关键是在Spring启动时、Bean初始化前的配置加载阶段完成,通过PropertySource层面透明解密ENC(...)密文,而非依赖拦截器;推荐使用Jasypt或自定义DecryptPropertySource实现。

Java 中配置文件敏感信息的自动解密,关键不是“拦截器”,而是在配置加载阶段完成解密还原——即 Spring 启动时、Bean 初始化前,把 enc(XXX) 这类密文替换成明文,让后续所有组件(DataSource、RestTemplate、FeignClient 等)拿到的是已解密的值。所谓“内存绑定阶段自动脱敏还原”,本质是 PropertySource 层面的透明解密,而非 HTTP 请求拦截或 Filter 拦截。
下面分三部分说明如何真正落地:
用 Jasypt 实现启动时自动解密(最常用、最稳妥)
Jasypt 是 Spring 生态中成熟度最高、集成最轻量的方案,它通过自定义 `PropertySource` 在 `Environment` 加载配置时就完成解密,全程对业务代码无感。-
引入依赖(Spring Boot 3.x 推荐
jasypt-spring-boot-starter):<dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> <version>3.0.5</version> </dependency>
-
配置加密密钥(不写死在代码里):
立即学习“Java免费学习笔记(深入)”;
# application.properties jasypt.encryptor.password=${JASYPT_KEY:changeit} # 优先取环境变量 JASYPT_KEY jasypt.encryptor.algorithm=PBEWithMD5AndDES jasypt.encryptor.iv-generator-classname=org.jasypt.iv.RandomIvGenerator -
加密配置项(用工具生成后填入):
spring.datasource.password=ENC(rQq2Zz9XgY1kLmNpQoRtSvUwXyZaBcD) spring.redis.password=ENC(jKlMnOpQrStUvWxYzA1B2C3D4E5F6G7H)
启动时自动生效:Spring 容器会识别
ENC(...)格式,在@Value、@ConfigurationProperties绑定前完成解密,DataSource 拿到的就是真实密码。
自定义 PropertySource 实现解密(适合需完全可控场景)
当不能引入第三方库,或需对接公司统一密钥中心(如 Vault、Apollo 加密插件)时,可手动扩展 `PropertySource`。-
编写解密 PropertySource:
public class DecryptPropertySource extends PropertySource<Properties> { private final Properties source; private final Decryptor decryptor; // 注入 AES/SM4 解密器,密钥从环境变量或配置中心拉取 public DecryptPropertySource(String name, Properties source, Decryptor decryptor) { super(name, source); this.source = source; this.decryptor = decryptor; } @Override public Object getProperty(String name) { String value = source.getProperty(name); if (value != null && value.startsWith("ENC(") && value.endsWith(")")) { try { return decryptor.decrypt(value.substring(4, value.length() - 1)); } catch (Exception e) { throw new RuntimeException("Decrypt failed for key: " + name, e); } } return value; } } -
注册到 Spring Environment(在
ApplicationContextInitializer或@Bean中):@Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer(); configurer.setIgnoreUnresolvablePlaceholders(true); return configurer; }
// 在 SpringApplication.run() 前注册
public class DecryptPropertySourceInitializer implements ApplicationContextInitializer
<H3>避免误用“拦截器”混淆解密时机</H3>
很多开发者尝试用 `HandlerInterceptor` 或 `Filter` 对配置项做解密,这是典型误区:
- 拦截器作用于 HTTP 请求链路,而配置加载发生在容器启动早期(远早于任何请求);
- `@Value("${db.password}")` 的赋值发生在 Bean 创建时,此时请求还没进来,拦截器根本没机会介入;
- 若强行在 Controller 层解密密码再传给 Service,会导致重复解密、线程安全风险、无法用于 DataSource 初始化等硬伤。
所以:
✅ 正确路径:`配置文件 → Environment → PropertySource 解密 → @Value/@ConfigurationProperties 绑定`
❌ 错误路径:`配置文件 → 明文或密文直接注入 → 请求来了再用拦截器解密 → 传参使用`
<p>核心就一点:解密必须发生在 Spring 解析占位符 `${...}` 的那一刻,而不是用户发起请求之后。只要抓住这个时机点,配置敏感信息的自动还原就不需要“拦截”,而是自然、透明、可靠地完成。</p>


















