Spring Boot 集成 Jasypt 实现配置文件数据库密码加密(避坑指南 + 算法详解)

  • Spring Boot 集成 Jasypt 实现配置文件数据库密码加密(避坑指南 + 算法详解)
    • 📌 一、为什么需要加密配置文件?
    • 🔐 一、Jasypt 是什么?
    • 🧩 二、核心原理
    • 🚀 三、集成步骤(以 Druid 数据源为例)
      • 1. 添加依赖(Maven)
      • 2. 加密数据库密码(推荐代码方式)
      • 3. 配置 application.yml
    • 🔐 四、Jasypt 支持的加密算法详解
      • 1. 如何在代码中设置算法?
      • 2. 常见可选算法列表
      • 3. 如何查看当前 JDK 支持哪些 PBE 算法?
    • 💡五、启动项目
      • 🚀 一、本地开发 / 测试环境启动方式
        • **方式 1:通过环境变量(推荐)**
        • 方式 2:通过 JVM 系统属性
        • 方式 3:通过 Spring Boot 命令行参数
      • 🐳 二、Docker 容器中启动
        • 1. Dockerfile(不硬编码密钥!)
        • 2. 启动容器时传入环境变量
      • ☸️ 三、Kubernetes 中启动(生产推荐)
        • 1. 创建 Secret
        • 2. 在 Deployment 中引用
      • 💡 四、IDE 中运行(如 IntelliJ IDEA)
      • 🛠️ 五、验证是否生效
    • ❌ 六、常见问题 & 解决方案
      • 问题 1:启动报错 `Failed to bind properties under 'spring.datasource.password'`
      • 问题 2:`EncryptionOperationNotPossibleException`
      • 问题 3:IDEA 环境变量未生效
      • 问题 4:Druid 路径 `spring.datasource.druid.password` 无法解密
    • ✅ 七、生产环境建议
    • 📚 八、总结
    • 📌 补充:如果使用的是druid连接池
      • ✅ 解决方案1.显式指定算法
      • ✅ 推荐做法:使用标准 spring.datasource.password + Druid 配置复用

Spring Boot 集成 Jasypt 实现配置文件数据库密码加密(避坑指南 + 算法详解)

项目中直接明文存储数据库密码存在安全隐患。本文详细记录在 Spring Boot + MyBatis + Druid 项目中集成 Jasyptapplication.yml 中数据库密码进行加密的完整流程,并总结开发过程中遇到的典型问题、解决方案,以及 加密算法选择与 JDK 支持情况查询方法,助你安全、高效地落地配置加密!


📌 一、为什么需要加密配置文件?

application.yml 中直接写数据库密码:

spring:
  datasource:
    password: root123456  # ❌ 明文暴露,不安全!

一旦代码泄露或配置文件被查看,数据库将面临风险。
Jasypt(Java Simplified Encryption) 是一个轻量级 Java 加解密库,配合 Spring Boot 可实现配置文件中敏感信息的自动加解密。


🔐 一、Jasypt 是什么?

Jasypt(Java Simplified Encryption)是一个开源的 Java 加密库,支持对配置文件中的敏感信息进行加密。

配合 jasypt-spring-boot 扩展,可以在 Spring Boot 启动时自动解密以 ENC(…) 格式包裹的密文。

官网:http://www.jasypt.org/

GitHub(Spring Boot 集成):https://github.com/ulisesbocchio/jasypt-spring-boot

🧩 二、核心原理

  • 加密阶段:使用一个加密密钥(password)对明文(如数据库密码)进行对称加密(默认 PBEWithMD5AndDES,可配置为 AES)。
  • 存储阶段:将加密后的字符串写入配置文件,格式为 ENC(加密后的内容)。
  • 运行阶段
    • Spring Boot 启动时,jasypt-spring-boot 会扫描所有 ENC(…) 配置项。
    • 使用启动时传入的密钥(不能硬编码!)进行解密。
    • 将解密后的明文注入到对应的配置属性中(如spring.datasource.password)。

整个过程对业务代码透明。

🚀 三、集成步骤(以 Druid 数据源为例)

1. 添加依赖(Maven)

<!-- Jasypt Spring Boot Starter -->
<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>3.0.5</version>
</dependency>

<!-- Druid 数据源(可选) -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.20</version>
</dependency>

⚠️ 必须使用 jasypt-spring-boot-starter,仅引入 jasypt 核心包无法自动解密!
⚠️注意:3.x 版本要求 Java 8+,Spring Boot 2.4+。如用 Spring Boot 3,请确认兼容性(目前 3.0.5 支持到 Spring Boot 2.7,Spring Boot 3 需用 4.x 快照版或等正式版)。


2. 加密数据库密码(推荐代码方式)

你可以通过以下任一方式生成密文:

方式 A:写一个临时测试类(推荐)

@SpringBootTest
public class JasyptEncryptTest {

    @Autowired
    private StringEncryptor stringEncryptor;

    @Test
    void encryptDbPassword() {
     	stringEncryptor.setPassword("myStrongPassword123!"); // 这是你的加密密钥(不能泄露!)
     	// 可选:指定算法(推荐使用强算法)
        stringEncryptor.setAlgorithm("PBEWITHHMACSHA512ANDAES_256");
 		encryptor.setIvGenerator(new RandomIvGenerator());
        String rawPassword = "你的数据库真实密码"; // 如:root123456
        String encrypted = stringEncryptor.encrypt(rawPassword);
        System.out.println("✅ 加密结果:");
        System.out.println("ENC(" + encrypted + ")");
    }
}

运行后输出类似:

Encrypted: 8F3xK9qLmN2pR7sT== 

💡 该方式使用项目当前配置的算法和密码,100% 保证加解密环境一致!
🔒 重要:myStrongPassword123! 是加密密钥,不是数据库密码!这个密钥必须安全保管。

方式 B:使用命令行(需下载 Jasypt CLI)

import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;

public class JasyptEncryptor {
    public static void main(String[] args) {
        StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
        encryptor.setPassword("myStrongPassword123!"); // 这是你的加密密钥(不能泄露!)
        // 可选:指定算法(推荐使用强算法)
        encryptor.setAlgorithm("PBEWITHHMACSHA512ANDAES_256");
        
        String plainText = "your_real_db_password"; // 真实数据库密码
        String encrypted = encryptor.encrypt(plainText);
        System.out.println("Encrypted: " + encrypted);
    }
}

3. 配置 application.yml

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/sky_take_out
    username: root
    password: ENC(8fGhT9xK3mQzLp2vRn7aEw==)
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource

jasypt:
  encryptor:
    password: ${JASYPT_ENCRYPTOR_PASSWORD}
    algorithm: PBEWITHHMACSHA512ANDAES_256  # ← 显式指定算法
    iv-generator-classname: org.jasypt.iv.RandomIvGenerator

✅ 关键:使用标准路径 spring.datasource.password,避免 Druid 自定义前缀导致解密失败。


🔐 四、Jasypt 支持的加密算法详解

1. 如何在代码中设置算法?

如果你通过 Java 配置自定义 StringEncryptor,可以这样设置:

@Bean
public StringEncryptor stringEncryptor() {
    PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
    SimpleStringPBEConfig config = new SimpleStringPBEConfig();
    config.setPassword("your_master_password");
    config.setAlgorithm("PBEWITHHMACSHA512ANDAES_256"); // ← 指定算法
    config.setKeyObtentionIterations("1000");
    config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
    config.setPoolSize("1");
    config.setProviderName("SunJCE");
    config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
    config.setStringOutputType("base64");
    encryptor.setConfig(config);
    return encryptor;
}

2. 常见可选算法列表

算法名称 安全性 说明
PBEWithMD5AndDES ⚠️ 低(已过时) Jasypt 1.x 默认算法,不推荐
PBEWithSHA1AndDESede 3DES 加密,较旧
PBEWITHHMACSHA512ANDAES_256 ✅ 高 Jasypt 3.x 默认算法,推荐使用
PBEWITHHMACSHA256ANDAES_128 ✅ 高 AES-128,性能略优
PBEWithSHA256And256BitAES-CBC-BC ✅ 高 需 Bouncy Castle 提供者

📌 推荐使用 PBEWITHHMACSHA512ANDAES_256:安全性高、兼容 JDK 8+、无需额外依赖。


3. 如何查看当前 JDK 支持哪些 PBE 算法?

你可以通过以下 Java 代码动态列出所有支持的 PBE 算法

import javax.crypto.Cipher;
import java.security.Provider;
import java.security.Security;
import java.util.HashSet;
import java.util.Set;

public class ListPBEAlgorithms {
    public static void main(String[] args) {
        Set<String> pbeAlgorithms = new HashSet<>();
        for (Provider provider : Security.getProviders()) {
            provider.getServices().stream()
                .filter(service -> "Cipher".equals(service.getType()))
                .map(Provider.Service::getAlgorithm)
                .filter(algo -> algo.startsWith("PBE"))
                .forEach(pbeAlgorithms::add);
        }
        System.out.println("✅ 当前 JDK 支持的 PBE 算法:");
        pbeAlgorithms.stream().sorted().forEach(System.out::println);
    }
}

示例输出(JDK 17):

PBEWithHmacSHA1AndAES_128
PBEWithHmacSHA1AndAES_256
PBEWithHmacSHA224AndAES_128
PBEWithHmacSHA256AndAES_128
PBEWithHmacSHA384AndAES_256
PBEWithHmacSHA512AndAES_256   ← 推荐!
PBEWithMD5AndDES
PBEWithSHA1AndDESede
...

💡 注意:部分算法(如 AES_256)在 JDK 8 中需要安装 JCE 无限强度策略文件(JDK 9+ 默认支持)。
📌 重要补充说明

  1. IV(初始化向量)
  • 使用 AES 时,必须使用 IV 以保证相同明文每次加密结果不同。
  • Jasypt 默认使用 NoIvGenerator(不安全!),务必显式设置为 RandomIvGenerator。
  • 在 Spring Boot 配置中通过 iv-generator-classname 指定。
  1. JDK 加密强度限制
  • JDK 8u161 之前:默认只允许 128 位 AES,需手动安装 JCE 无限制策略文件。
  • JDK 8u161+ / JDK 11+:默认支持 256 位 AES,无需额外操作。
  1. 算法命名规范
  • 不同 JDK 厂商(Oracle、OpenJDK、IBM)可能略有差异,但主流都支持PBEWITHHMACSHAANDAES_ 系列。

💡五、启动项目

✅ 核心原则

  • 密钥不能写在代码或配置文件中!
  • 必须通过 外部安全方式 注入,如:
  • 环境变量(最常用)
  • JVM 系统属性
  • 命令行参数
  • K8s Secret / Docker secrets(生产环境)

🚀 一、本地开发 / 测试环境启动方式

方式 1:通过环境变量(推荐)
# Linux / macOS
export JASYPT_ENCRYPTOR_PASSWORD=your_master_password
java -jar your-app.jar

# Windows (PowerShell)
$env:JASYPT_ENCRYPTOR_PASSWORD="your_master_password"
java -jar your-app.jar

# Windows (CMD)
set JASYPT_ENCRYPTOR_PASSWORD=your_master_password
java -jar your-app.jar

✅ 优点:简单、安全(不会出现在进程命令中)、IDE 可配置。

方式 2:通过 JVM 系统属性
java -Djasypt.encryptor.password=your_master_password -jar your-app.jar

⚠️ 注意:这种方式会在 ps 命令中暴露密码(不推荐用于生产)。

方式 3:通过 Spring Boot 命令行参数
java -jar your-app.jar --jasypt.encryptor.password=your_master_password

⚠️ 同样可能被 ps 或日志泄露,仅用于临时测试。

🐳 二、Docker 容器中启动

1. Dockerfile(不硬编码密钥!)
FROM openjdk:17
COPY your-app.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
2. 启动容器时传入环境变量
docker run -d \
  -e JASYPT_ENCRYPTOR_PASSWORD=your_master_password \
  --name myapp \
  your-image-name

✅ 安全:密钥通过 -e 注入,不会写入镜像。

☸️ 三、Kubernetes 中启动(生产推荐)

1. 创建 Secret
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: app-secrets
type: Opaque
data:
  # 注意:value 需要 base64 编码
  jasypt-password: eW91cl9tYXN0ZXJfcGFzc3dvcmQ=  # echo -n "your_master_password" | base64

应用:

kubectl apply -f secret.yaml
2. 在 Deployment 中引用
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  template:
    spec:
      containers:
      - name: app
        image: your-image
        env:
        - name: JASYPT_ENCRYPTOR_PASSWORD
          valueFrom:
            secretKeyRef:
              name: app-secrets
              key: jasypt-password

✅ 安全:密钥由 K8s Secret 管理,RBAC 控制访问。

💡 四、IDE 中运行(如 IntelliJ IDEA)

  • 打开 Run/Debug Configurations
  • 在 Environment variables 中添加:
JASYPT_ENCRYPTOR_PASSWORD = your_master_password
  • 点击运行

✅ 开发时最方便的方式。

🛠️ 五、验证是否生效

启动成功后,检查日志是否有类似:

INFO  o.j.s.b.c.StringEncryptablePropertyResolver - Decrypting property: spring.datasource.password

如果启动失败,常见错误:

Decryption of Properties failed → 密钥错误或未提供
EncryptionOperationNotPossibleException → 算法/JCE 问题(见前文)

❌ 六、常见问题 & 解决方案

问题 1:启动报错 Failed to bind properties under 'spring.datasource.password'

原因:Jasypt 未生效,ENC(...) 被当作普通字符串。

解决

  • 确认依赖为 jasypt-spring-boot-starter
  • 密码写在 spring.datasource.password
  • 临时硬编码 jasypt.encryptor.password 测试

问题 2:EncryptionOperationNotPossibleException

原因:密码、算法、密文三者不一致。

解决

  • 用项目内 StringEncryptor 重新加密
  • 打印环境变量确认主密码传入
  • 显式指定 algorithm 保持一致

问题 3:IDEA 环境变量未生效

验证方法

public static void main(String[] args) {
    System.out.println("JASYPT password: " + System.getenv("JASYPT_ENCRYPTOR_PASSWORD"));
    SpringApplication.run(App.class, args);
}

正确设置:Run → Edit Configurations → Environment variables → 添加键值对。


问题 4:Druid 路径 spring.datasource.druid.password 无法解密

解决:改用标准路径 spring.datasource.password,Druid 会自动继承。


✅ 七、生产环境建议

  • 主密码通过 环境变量 / 配置中心 / KMS 注入
  • 使用 PBEWITHHMACSHA512ANDAES_256 等强算法
  • 定期轮换密码
  • 避免在 Git 中提交含密文的配置(可配合 .gitignore 或配置模板)

📚 八、总结

关键点 说明
依赖 必须用 jasypt-spring-boot-starter
路径 spring.datasource.password
算法 推荐 PBEWITHHMACSHA512ANDAES_256
主密码 通过环境变量传入,务必验证
加密方式 用项目内 StringEncryptor 加密,确保一致性

安全无小事,一个 ENC(...) 背后是严谨的加解密流程。掌握算法选择与环境一致性,才能真正用好 Jasypt!


📌 补充:如果使用的是druid连接池

Jasypt 默认只拦截 spring.datasource.password,但你用的是 spring.datasource.druid.password(Druid 自定义前缀)。

🔑 关键问题:Jasypt 默认不自动解密 spring.datasource.druid.password

因为 druid是 Alibaba 的扩展,属性路径变了,Jasypt 默认的拦截器可能不会扫描 druid下的 password

✅ 解决方案1.显式指定算法

application.yml:

jasypt:
  encryptor:
    password: ${JASYPT_ENCRYPTOR_PASSWORD}
  # 启用对所有属性的解密(包括自定义前缀如 druid)
  property:
    prefix: ENC(
    suffix: )
    # 关键:启用解密所有属性(默认可能只解密部分)

⚠️ 注意:jasypt.encryptor.password 不要写在这里!

✅ 推荐做法:使用标准 spring.datasource.password + Druid 配置复用

Druid 支持从标准 spring.datasource 自动继承属性。你可以这样写:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/sky_take_out
    username: root
    password: ENC(xxx...)  # ← 使用标准路径
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource  # 指定使用 Druid
    druid:
      initial-size: 5
      min-idle: 5
      max-active: 20
      # 其他 Druid 特有配置...

✅ 这样 password 就在 spring.datasource.password 下,Jasypt 能自动识别并解密!

只要你通过上述任一方式在启动时提供了正确的 JASYPT_ENCRYPTOR_PASSWORD,Spring Boot 就能自动解密 ENC(…) 内容,应用正常启动。

适用技术栈:Spring Boot 2.7+ / JDK 8+ / MyBatis / Druid / MySQL

欢迎点赞、收藏、评论交流!
如果你觉得这篇文章对你有帮助,不妨分享给更多开发者 👇


作者:不会写程序的未来程序员
首发于 CSDN
版权声明:本文为原创文章,转载请注明出处。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐