在现代分布式系统或微服务架构中,Spring Boot 已成为后端开发的主力框架。在日常开发或部署过程中,我们不可避免地需要在配置文件中存储各种重要信息,例如数据库连接地址、账号密码、第三方 API 密钥、OAuth token、邮箱服务认证信息等。
默认情况下,这些信息大多以明文方式保存在配置文件中(如 application.yml 或 application.properties)。这种做法虽然简单直观,但也存在极大的安全隐患。
一、现实中的问题:明文配置带来的安全漏洞
来看下面这样一段真实的 application.yml 配置片段:
spring:
datasource:
url: jdbc:mysql://192.168.1.101:3306/production_db?useSSL=false&serverTimezone=UTC
username: admin_user
password: admin_password123
这段配置泄露的信息包括:
- 数据库连接地址(含 IP 和端口)
- 数据库名称
- 用户名和密码
问题是:
- 一旦配置文件被上传至 GitHub、Gitee、代码审查平台,或者因打包上传到制品库被他人下载;
- 一旦运维误将配置文件放在可被访问的 Nginx 静态路径;
- 一旦日志或错误堆栈无意中输出了配置内容;
那么这些敏感信息就极有可能直接暴露给攻击者,造成数据库被连接、敏感数据泄露、甚至整站瘫痪等重大安全事故。
结论:明文保存敏感信息在生产环境中是绝对不被允许的!
二、安全改造目标:如何加密配置文件
我们希望做到:
- 所有涉及敏感信息的配置项都不再明文暴露;
- 系统在启动和运行过程中自动完成解密,无需手动处理;
- 整体使用成本低,对 Spring Boot 兼容性强;
- 加密密钥必须脱离代码本体,由外部注入;
- 加密过程安全、不可逆、难以破解。
三、方案选择:使用 Jasypt 实现配置加密
在 Spring Boot 生态中,最常用的敏感信息加密方案是:
Jasypt(Java Simplified Encryption)是一个专门用于加密 Java 应用程序中的敏感数据的库,它提供了:
- 多种加密算法支持(如 PBEWithMD5AndDES、AES、SHA 等);
- 与 Spring Boot 配置系统完美集成;
- 使用 ENC(…) 包裹加密字段,解密过程完全透明;
- 加密内容即使重复加密也会产生不同密文,提高安全性。
四、实战演练:基于 Jasypt 实现配置加密全过程
Step 1:引入 Jasypt 依赖
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
Step 2:准备你的原始配置文件
举个例子:
spring:
datasource:
url: jdbc:mysql://192.168.1.101:3306/prod_db
username: admin
password: mySecret123
Step 3:生成加密字符串
我们可以通过写一个 JUnit 单元测试类生成加密后的内容:
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.junit.jupiter.api.Test;
public class EncryptTest {
@Test
public void generateEncryptedString() {
String key = "MyInternalEncryptKey"; // 用于加密的密钥
String rawPassword = "mySecret123"; // 明文密码
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
encryptor.setPassword(key);
encryptor.setAlgorithm("PBEWithMD5AndDES");
String encrypted = encryptor.encrypt(rawPassword);
System.out.println("加密后密文:" + encrypted);
}
}
注意:每次加密得到的密文都不一样,这是安全特性(引入随机 salt)
Step 4:替换配置文件内容
将原始配置改为:
spring:
datasource:
url: ENC(vO3A+asW1zdfg321==)
username: ENC(Vz3FtYWxz123==)
password: ENC(YWxzZXJrZXkz==)
使用
ENC(...)是 Jasypt 的约定,代表这是一个加密字段。
Step 5:指定解密密钥(加密密钥)
Jasypt 解密过程需要知道密钥,在运行时通过 VM 参数传入:
-Djasypt.encryptor.password=MyInternalEncryptKey
支持以下方式传参:
- IDEA 配置 VM options;
- Spring Boot 的
application.properties(不推荐); - Linux 启动脚本加
-D参数; - 环境变量方式。
Step 6:验证加密是否生效
写一个简单的测试类来验证配置是否能成功解析为明文:
@Component
public class ShowInfo implements ApplicationRunner {
@Value("${spring.datasource.password}")
private String password;
@Override
public void run(ApplicationArguments args) {
System.out.println("数据库密码为:" + password);
}
}
运行后将看到打印出来的是明文密码而非密文,说明加密解密流程已经打通。
五、解密失败怎么办?调试建议
如果运行时报错提示类似如下:
org.jasypt.exceptions.EncryptionOperationNotPossibleException: null
说明你没有正确设置解密密钥,或者 ENC(...) 包裹的数据不是合法密文。此时请检查:
- 启动参数
-Djasypt.encryptor.password是否正确; - 是否将明文误放入了
ENC(...)中; - 加密算法是否匹配(默认 PBEWithMD5AndDES);
- 密钥是否一致(加密和解密必须同一个)。
六、关于密钥管理的额外安全建议
虽然我们避免了明文配置,但密钥本身依然是系统最重要的安全门槛,必须妥善管理。
推荐方案:
| 场景 | 推荐密钥存储方式 |
|---|---|
| 本地开发 | 使用本地环境变量 .env |
| 容器部署(Docker) | 使用 Docker Secrets |
| K8s 环境 | 使用 Kubernetes Secret |
| 云环境 | 使用 AWS Secrets Manager / 阿里云 KMS 等 |
七、总结与最佳实践
通过今天的学习,我们实现了一个完整的敏感配置加密流程。来回顾下关键知识点:
| 操作 | 说明 |
|---|---|
| 明文配置的风险 | 配置被泄露将导致系统完全失控 |
| Jasypt 工具选型 | 轻量级、开箱即用、与 Spring Boot 无缝集成 |
| 加密内容写入方式 | 使用 ENC(…) 包裹密文 |
| 加密过程如何实现 | 使用 JUnit 工具类 + 加密密钥生成 |
| 密钥如何注入 | 启动时通过 JVM 参数注入,不能硬编码 |
| 加密字符串为何每次不同 | 引入 salt 提高破解难度,避免字典攻击 |
| 解密失败如何排查 | 重点关注密钥是否一致、启动参数是否传入 |
| 密钥的存储管理建议 | 使用环境变量或安全组件(如 KMS、Secrets Manager) |
八、尾声:保护配置文件,从你我做起
安全无小事。配置文件加密只是第一步,更重要的是建立安全意识与规范。
- 不上传配置文件到代码仓库;
- 配置文件中避免出现 hardcode 密钥;
- 定期更换密钥和加密算法;
- 加强团队对于安全配置的审查。
希望本篇详解能帮你将配置加密从“知道”变为“实战”,真正保护你的生产系统与数据安全。

3万+

被折叠的 条评论
为什么被折叠?



