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

在Spring Boot项目开发中,我们通常会在application.ymlapplication.properties中配置各种敏感信息,包括:

  • 数据库连接密码

  • Redis连接密码

  • 第三方API密钥

  • 邮箱服务密码

  • 各种中间件认证信息

安全风险:如果这些敏感信息以明文形式存储在配置文件中,一旦代码仓库泄露或配置文件被非法获取,将直接导致系统安全漏洞,可能造成数据泄露、服务被入侵等严重后果。

解决方案:使用Jasypt(Java Simplified Encryption)对配置文件中的敏感信息进行加密处理。

在这里插入图片描述

二、Jasypt简介

Jasypt是一个Java加密库,提供了简单易用的加密/解密功能,主要特点包括:

  • 支持单向和双向加密

  • 与Spring Boot无缝集成

  • 支持多种加密算法

  • 配置简单,开箱即用

  • 支持自定义加密器

三、Spring Boot集成Jasypt完整步骤

3.1 引入依赖

pom.xml中添加Jasypt Spring Boot Starter依赖:

<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>3.0.4</version>
</dependency>

版本说明:3.0.4是目前最稳定的版本,支持Spring Boot 2.x和3.x系列。

3.2 配置加密密钥

application.yml中配置Jasypt加密密钥:

jasypt:
  encryptor:
    # 加密密钥(生产环境建议通过环境变量或启动参数传入)
    password: your-secret-key-here
    # 加密算法
    algorithm: PBEWithMD5AndDES
    # 密钥获取迭代次数
    iv-generator-classname: org.jasypt.iv.NoIvGenerator

重要提示:加密密钥是整个加密体系的核心,千万不要硬编码在配置文件中!生产环境建议通过以下方式传入:

  • 启动参数:--jasypt.encryptor.password=your-key

  • 环境变量:JASYPT_ENCRYPTOR_PASSWORD=your-key

  • 系统属性:-Djasypt.encryptor.password=your-key

3.3 生成加密密码

有多种方式可以生成加密后的密码,这里介绍两种最常用的方法:

方法一:使用Java代码生成

import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;

public class EncryptUtil {
    public static void main(String[] args) {
        StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
        encryptor.setPassword("your-secret-key-here"); // 加密密钥
        encryptor.setAlgorithm("PBEWithMD5AndDES");

        // 加密数据库密码
        String dbPassword = encryptor.encrypt("123456");
        System.out.println("数据库加密密码: ENC(" + dbPassword + ")");

        // 加密Redis密码
        String redisPassword = encryptor.encrypt("redis123");
        System.out.println("Redis加密密码: ENC(" + redisPassword + ")");
    }
}

方法二:使用Maven插件生成

mvn jasypt:encrypt-value -Djasypt.encryptor.password=your-secret-key -Djasypt.plugin.value=123456

四、数据库密码加密实战

4.1 加密前的配置(明文)

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test_db
    username: root
    password: 123456  # 明文密码,不安全!
    driver-class-name: com.mysql.cj.jdbc.Driver

4.2 加密后的配置

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test_db
    username: root
    password: ENC(9Lm3nQpR7sT2vW8xY4zA6bC9dE1fG5hJ)  # 加密后的密码
    driver-class-name: com.mysql.cj.jdbc.Driver

jasypt:
  encryptor:
    password: ${JASYPT_ENCRYPTOR_PASSWORD:}  # 从环境变量读取密钥
    algorithm: PBEWithMD5AndDES
    iv-generator-classname: org.jasypt.iv.NoIvGenerator

格式说明:加密后的密码需要用ENC()包裹,Jasypt会自动识别并解密。

五、Redis密码加密实战

5.1 加密前的Redis配置

spring:
  redis:
    host: localhost
    port: 6379
    password: redis123  # 明文密码
    database: 0
    timeout: 3000ms

5.2 加密后的Redis配置

spring:
  redis:
    host: localhost
    port: 6379
    password: ENC(KjH8gF6dS4aD2fG1hJ3kL5mN7bV9cX2z)  # 加密后的密码
    database: 0
    timeout: 3000ms

六、其他常见加密场景

6.1 邮箱服务密码加密

spring:
  mail:
    host: smtp.qq.com
    port: 587
    username: your-email@qq.com
    password: ENC(MnQ8pR2sT4wY6aZ8cB0dE2fG4hJ6kL8m)  # 邮箱授权码加密
    properties:
      mail:
        smtp:
          auth: true
          starttls:
            enable: true

6.2 第三方API密钥加密

# 阿里云OSS配置
aliyun:
  oss:
    endpoint: oss-cn-beijing.aliyuncs.com
    access-key-id: ENC(AaS1dF2gH3jK4lM5nO6pQ7rS8tU9vW0x)
    access-key-secret: ENC(ZxQ9wE8rT7yU6iO5pA4sD3fG2hJ1kL0m)
    bucket-name: your-bucket-name

6.3 自定义配置项加密

# 自定义业务配置
app:
  security:
    jwt-secret: ENC(JwT2sE4cR6eT8kE0yN2oW4l6d8f0g2h4)
    admin-password: ENC(AdM1iN3pA5sS7wO9rD2k4e6y8)

七、高级配置与自定义

7.1 使用更强的加密算法

jasypt:
  encryptor:
    password: ${JASYPT_ENCRYPTOR_PASSWORD}
    algorithm: PBEWithHMACSHA512AndAES_256
    iv-generator-classname: org.jasypt.iv.RandomIvGenerator
    pool-size: 2
    salt-generator-classname: org.jasypt.salt.RandomSaltGenerator
    string-output-type: base64

7.2 自定义加密前缀和后缀

如果不想使用默认的ENC()格式,可以自定义:

jasypt:
  encryptor:
    password: ${JASYPT_ENCRYPTOR_PASSWORD}
    property:
      prefix: "DEC["
      suffix: "]"

然后配置文件中使用:

spring:
  datasource:
    password: DEC[加密后的密码字符串]

7.3 自定义加密器Bean

import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JasyptConfig {

    @Bean("jasyptStringEncryptor")
    public StringEncryptor stringEncryptor() {
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();

        config.setPassword(System.getenv("JASYPT_ENCRYPTOR_PASSWORD"));
        config.setAlgorithm("PBEWithMD5AndDES");
        config.setKeyObtentionIterations("1000");
        config.setPoolSize("1");
        config.setProviderName("SunJCE");
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
        config.setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator");
        config.setStringOutputType("base64");

        encryptor.setConfig(config);
        return encryptor;
    }
}

八、JDK版本与加密能力兼容性

Jasypt加密能力与JDK版本密切相关,不同版本的JDK对加密算法的支持程度存在显著差异。这是很多开发者在实际使用中容易踩坑的地方。

8.1 JDK版本加密能力差异

JDK版本 默认加密能力 是否需要JCE
JDK 8u151及更早 仅支持128位加密 ✅ 必须安装JCE才能支持256位
JDK 8u161+ / 8u171+ 默认支持256位加密 ❌ 无需额外配置
JDK 9 及以上 默认支持256位加密 ❌ 无需额外配置

关键区别:JDK 8u151及更早版本由于美国出口限制政策,默认禁用了256位高强度加密算法,必须手动安装JCE(Java Cryptography Extension)无限制权限策略文件才能使用。

8.2 各JDK版本推荐算法选择

低版本JDK(8u151及更早,未安装JCE)

只能使用128位及以下的加密算法:

jasypt:
  encryptor:
    # 安全兼容的算法(无需JCE)
    algorithm: PBEWithMD5AndDES
    iv-generator-classname: org.jasypt.iv.NoIvGenerator
    # 或使用PBEWithMD5AndTripleDES(168位,部分JDK默认支持)

高版本JDK(8u161+ / 9+,或已安装JCE)

推荐使用更强的256位加密算法:

jasypt:
  encryptor:
    # 推荐:AES-256高强度加密
    algorithm: PBEWithHMACSHA512AndAES_256
    iv-generator-classname: org.jasypt.iv.RandomIvGenerator
    salt-generator-classname: org.jasypt.salt.RandomSaltGenerator

    # 备选方案
    # algorithm: PBEWithSHA256AndAES_128
    # algorithm: PBEWithSHA1AndDESede

8.3 JCE无限制权限策略文件安装步骤

步骤1:下载JCE文件

官方下载地址

  • JDK 8:https://www.oracle.com/java/technologies/javase-jce8-downloads.html

  • JDK 7:https://www.oracle.com/java/technologies/javase-jce7-downloads.html

下载文件:UnlimitedJCEPolicyJDK8.zip

步骤2:解压并放置文件

Windows系统

# 1. 找到JDK安装目录(示例)
cd C:\Program Files\Java\jdk1.8.0_144\jre\lib\security

# 2. 备份原文件
copy local_policy.jar local_policy.jar.bak
copy US_export_policy.jar US_export_policy.jar.bak

# 3. 将解压后的两个jar文件复制到security目录,覆盖原文件

Linux/Mac系统

# 1. 找到JDK安装目录
cd $JAVA_HOME/jre/lib/security

# 2. 备份原文件
cp local_policy.jar local_policy.jar.bak
cp US_export_policy.jar US_export_policy.jar.bak

# 3. 复制新文件(假设解压到~/Downloads/jce/)
cp ~/Downloads/jce/UnlimitedJCEPolicy/*.jar .

步骤3:验证JCE安装成功

创建验证Java程序:

import javax.crypto.Cipher;

public class JceCheck {
    public static void main(String[] args) {
        try {
            int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
            System.out.println("AES最大密钥长度: " + maxKeyLen);

            if (maxKeyLen >= 256) {
                System.out.println("✅ JCE无限制权限已启用!支持256位加密");
            } else {
                System.out.println("❌ JCE未安装,仅支持" + maxKeyLen + "位加密");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

运行验证:

javac JceCheck.java && java JceCheck

成功输出

AES最大密钥长度: 2147483647
✅ JCE无限制权限已启用!支持256位加密

8.4 常见JCE相关错误及解决方案

错误1:EncryptionOperationNotPossibleException

错误信息

org.jasypt.exceptions.EncryptionOperationNotPossibleException: 
    Encryption raised an exception. A possible cause is you are using strong encryption 
    algorithms and you have not installed the Java Cryptography Extension (JCE) 
    Unlimited Strength Jurisdiction Policy Files in this Java Virtual Machine

原因:使用了需要256位支持的加密算法,但JDK未安装JCE

解决方案

  1. 安装JCE无限制权限策略文件(见8.3节)

  2. 或降级使用兼容算法:PBEWithMD5AndDES

错误2:Illegal key size or default parameters

错误信息

java.security.InvalidKeyException: Illegal key size or default parameters

原因:密钥长度超过JDK默认限制(通常是尝试使用256位密钥)

解决方案

  1. 安装JCE(推荐)

  2. 或在Java启动参数中添加:

    java -Dcrypto.policy=unlimited -jar your-app.jar
    

错误3:BadPaddingException / GeneralSecurityException

错误信息

javax.crypto.BadPaddingException: Given final block not properly padded
java.security.GeneralSecurityException: javax.crypto.BadPaddingException

可能原因

  • 加密和解密使用的JDK环境不一致(一个装了JCE一个没装)

  • 加密时用了256位算法,解密时JDK不支持

  • IV(初始化向量)配置不匹配

解决方案

  1. 确保所有环境(开发/测试/生产)都安装JCE

  2. 统一加密算法配置,特别是iv-generator-classname

  3. 使用NoIvGenerator提高兼容性:

    jasypt:
      encryptor:
        iv-generator-classname: org.jasypt.iv.NoIvGenerator
    

8.5 Docker容器JCE配置方案

如果应用运行在Docker容器中,可在Dockerfile中预装JCE:

FROM openjdk:8-jdk-alpine

# 安装JCE无限制权限(针对8u151之前的镜像)
RUN wget -q --no-check-certificate --no-cookies \
    --header "Cookie: oraclelicense=accept-securebackup-cookie" \
    "https://download.oracle.com/otn-pub/java/jce/8/jce_policy-8.zip" -O /tmp/jce.zip \
    && unzip /tmp/jce.zip -d /tmp/ \
    && cp /tmp/UnlimitedJCEPolicyJDK8/*.jar $JAVA_HOME/jre/lib/security/ \
    && rm -rf /tmp/jce.zip /tmp/UnlimitedJCEPolicyJDK8

# 或者对于较新镜像,直接设置系统属性
ENV JAVA_OPTS="$JAVA_OPTS -Dcrypto.policy=unlimited"

COPY target/your-app.jar /app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

最佳实践建议

  1. 优先升级到JDK 8u161+或JDK 11/17,默认支持无限制加密

  2. 如必须使用旧JDK,务必在所有环境统一安装JCE

  3. 使用PBEWithMD5AndDES算法获得最大兼容性

  4. 部署前务必运行JCE验证程序确认配置正确

九、常见问题与解决方案

9.1 问题一:解密失败,提示"Unable to decrypt property"

原因

  • 加密密钥不匹配

  • 加密算法配置不一致

  • 加密字符串格式错误

解决方案

# 1. 确保加密和解密使用相同的密钥
# 2. 确保算法配置一致
jasypt:
  encryptor:
    algorithm: PBEWithMD5AndDES
    iv-generator-classname: org.jasypt.iv.NoIvGenerator

# 3. 检查ENC()格式是否正确,不要有多余空格

9.2 问题二:Spring Boot 3.x兼容性问题

原因:Spring Boot 3.x使用Jakarta EE,部分旧版本Jasypt不兼容。

解决方案:使用3.0.4及以上版本

<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>3.0.4</version>
</dependency>

9.3 问题三:单元测试时如何处理加密配置

解决方案:在测试配置中指定密钥

@SpringBootTest(properties = "jasypt.encryptor.password=test-key")
public class ApplicationTests {
    @Test
    void contextLoads() {
    }
}

9.4 问题四:如何在开发环境禁用加密

解决方案:使用profile区分环境

# 开发环境使用明文
jasypt:
  encryptor:
    bootstrap: false  # 禁用Jasypt自动配置

十、生产环境最佳实践

10.1 密钥安全管理

绝对禁止将加密密钥提交到代码仓库!

推荐方案

  1. 环境变量方式(最推荐)

    # Linux/Mac
    export JASYPT_ENCRYPTOR_PASSWORD="your-production-key"
    
    # Windows
    set JASYPT_ENCRYPTOR_PASSWORD=your-production-key
    
    # Docker
    docker run -e JASYPT_ENCRYPTOR_PASSWORD=your-production-key your-image
    
  2. 启动参数方式

    java -jar your-app.jar --jasypt.encryptor.password=your-production-key
    
  3. K8s Secret方式

    env:
    - name: JASYPT_ENCRYPTOR_PASSWORD
      valueFrom:
        secretKeyRef:
          name: app-secrets
          key: jasypt-password
    

10.2 多环境配置策略

环境 配置方式 说明
开发环境 明文或简单加密 便于开发调试
测试环境 完整加密 验证加密流程
生产环境 强加密+环境变量密钥 最高安全级别

10.3 日志安全配置

防止配置信息被打印到日志:

logging:
  level:
    com.ulisesbocchio.jasyptspringboot: WARN
    org.jasypt: WARN

10.4 定期轮换密钥

建议每3-6个月轮换一次加密密钥:

  1. 使用旧密钥解密所有配置项

  2. 使用新密钥重新加密

  3. 更新环境变量中的密钥

  4. 重启应用验证

十一、完整示例项目结构

spring-boot-encryption-demo/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/
│   │   │       └── example/
│   │   │           ├── Application.java
│   │   │           ├── config/
│   │   │           │   └── JasyptConfig.java
│   │   │           └── util/
│   │   │               └── EncryptUtil.java
│   │   └── resources/
│   │       ├── application.yml
│   │       ├── application-dev.yml
│   │       ├── application-test.yml
│   │       └── application-prod.yml
│   └── test/
│       └── java/
│           └── com/
│               └── example/
│                   └── EncryptTest.java
└── pom.xml

十二、总结

通过Jasypt实现Spring Boot配置加密是保护系统敏感信息的有效手段。核心要点:

  1. 集成简单:只需引入starter依赖,几行配置即可使用

  2. 密钥安全:生产环境务必使用环境变量传递密钥,禁止硬编码

  3. 覆盖全面:支持数据库、Redis、邮箱、第三方API等所有配置项

  4. 环境隔离:使用Spring Profile实现多环境差异化配置

  5. 定期维护:定期轮换密钥,保持系统安全性

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐