Bootstrap

Springboot项目使用jasypt加密配置文件中的敏感信息

目录

目录

项目背景

需求

jasypt简介

使用

0,版本对应关系

1,引入依赖

 2,启用加密

2.1,在启动类上配置注解

2.2,启用注解扫描和@Configuration配置

2.3,只针对指定的配置文件生效

3,配置加密属性

4,使用-在配置文件里将明文改成密文

4.1,根据上面配置的算法,将所需要的明文转换为对应的密文

4.2,将密文配置到配置文件里

其它

常见错误

算法

附录

项目背景

        Spring Boot 2.0.8

        jasypt-spring-boot-starter 即jasypt-1.9.3.jar

需求

        在项目中,经常需要在配置文件里配置一些敏感信息,比如数据库用户名和密码,redis、mq的连接信息等。如果直接写明文,很容易造成密码泄露等安全问题。

jasypt简介

Jasypt 是一个 Java 库,它允许开发者以最小的努力为他/她的项目添加基本的加密功能,而且不需要对密码学的工作原理有深刻的了解。

  • 高安全性、基于标准的加密技术,既可用于单向加密也可用于双向加密。加密密码、文本、数字、二进制文件...
  • 与Hibernate的透明集成。
  • 适合集成到基于Spring的应用程序中,也可与Spring Security透明地集成。
  • 对应用程序的配置(即数据源)进行加密的综合能力。
  • 在多处理器/多核系统中具有高性能加密的特殊功能。
  • 开放的API,可与任何JCE供应商一起使用。
  • 配置相关加密信息,就能够实现在项目运行的时候,自动把配置文件中已经加密的信息解密成明文,供程序使用

可以加密所有的Spring环境配置信息,比如系统变量、环境变量、命令行变量、application.properties、yaml配置等

 (This means any system property, environment property, command line argument, application.properties, application-*.properties, yaml properties, and any other property sources can contain encrypted properties)

使用

0,版本对应关系

Releases · ulisesbocchio/jasypt-spring-boot (github.com)

jasypt-spring-boot

spring boot

3.0.5

支持3

3.0.4

支持2.5.4,不支持2.0.X

3.0.2

支持2.0.X、2.1.X

3.0.0

1.5.X以上版本,支持2.1.X

2.1.2

支持2.0.X

2.0.0

支持2.0.X

1,引入依赖

maven方式:

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

 2,启用加密

几种方式:引入的pom有区别

2.1,在启动类上配置注解

@SpringBootApplication
@EnableEncryptableProperties
public class MyApplication {
    ...
}

2.2,启用注解扫描和@Configuration配置

启动类:

@SpringBootApplication
@EnableAutoConfiguration
public class MyApplication {
    ...
}

配置类:

@Configuration
@EnableEncryptableProperties
public class MyApplicationConfig {
    ...
}

2.3,只针对指定的配置文件生效

配置类:支持单个或多个配置文件:

@Configuration
@EncryptablePropertySource(name = "EncryptedProperties", value = "classpath:encrypted.properties")
public class MyApplicationConfig {
	...
}
@Configuration
@EncryptablePropertySources({@EncryptablePropertySource("classpath:encrypted.properties"),
    @EncryptablePropertySource("classpath:encrypted2.properties")})
public class MyApplicationConfig {
	...
}

3,配置加密属性

方式一:在application配置文件里配置jasypt的属性:

StringEncryptor

KeyRequiredDefault Value
jasypt.encryptor.passwordTrue-
jasypt.encryptor.algorithmFalsePBEWITHHMACSHA512ANDAES_256
jasypt.encryptor.key-obtention-iterationsFalse1000
jasypt.encryptor.pool-sizeFalse1
jasypt.encryptor.provider-nameFalseSunJCE
jasypt.encryptor.provider-class-nameFalsenull
jasypt.encryptor.salt-generator-classnameFalseorg.jasypt.salt.RandomSaltGenerator
jasypt.encryptor.iv-generator-classnameFalseorg.jasypt.iv.RandomIvGenerator
jasypt.encryptor.string-output-typeFalsebase64
jasypt.encryptor.proxy-property-sourcesFalsefalse
jasypt.encryptor.skip-property-sourcesFalseempty list

默认的加密算法是PBEWithHMACSHA512AndAES_256,对应的加解码器是AES256TextEncryptor

配置例子:application.yml

jasypt:
  encryptor:
    password: myJasyptPassword

项目实例里,一般来说password不在配置文件里写成明文的方式,而是配置成环境变量,启动应用的时候传递进去。

jasypt:
    encryptor:
        password: ${JASYPT_ENCRYPTOR_PASSWORD:}

设置环境变量:

# 打开/etc/profile文件 vim /etc/profile # 文件末尾插入

export JASYPT_PASSWORD = myJasyptPassword

启动:

JASYPT_ENCRYPTOR_PASSWORD=${JASYPT_PASSWORD} java -jar my-applicaiton-SNAPSHOT.jar

或者配置属性,直接在启动的时候设置:

	java -jar my-applicaiton-SNAPSHOT.jar --jasypt.encryptor.password=myJasyptPassword

方式二:自定义对象

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

特别注意:算法和IV生成器要匹配,比如上面的PBEWITHHMACSHA512ANDAES_256和org.jasypt.iv.RandomIvGenerator

4,使用-在配置文件里将明文改成密文

4.1,根据上面配置的算法,将所需要的明文转换为对应的密文

方式有很多,可以写工具类,或者提供一个controller服务生成,或者用mvn插件,或者用批处理生成

下面的测试类就提供了3种方式:


import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.jasypt.util.text.AES256TextEncryptor;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;

@SpringBootTest
@RunWith(SpringRunner.class)
public class JasyptTests {

    @Resource(name = "jasyptStringEncryptor")
    StringEncryptor encryptor;

    /**
     * 直接使用项目里的加密器,可以保证加密和解密用的加密器是同一个,生成的密文不会有问题
     * 测试jasypt加密、解密,生成密文
     */
    @Test
    public void testJasypt() {
        String myEncryptedText = encryptor.encrypt("root");
        System.out.println("加密后:"+myEncryptedText);
        String plainText = encryptor.decrypt(myEncryptedText);
        System.out.println("解密后:"+plainText);
    }

    public static void main(String[] args) {
        // 直接使用加密算法对应的加密器类
        AES256TextEncryptor textEncryptor = new AES256TextEncryptor();
        textEncryptor.setPassword("myJasyptPassword");
        String myEncryptedText = textEncryptor.encrypt("root");
        System.out.println("加密后:"+myEncryptedText);
        String plainText = textEncryptor.decrypt(myEncryptedText);
        System.out.println("解密后:"+plainText);

        // 根据配置的加密器配置类生成加密器对象
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        config.setPassword("myJasyptPassword");
        config.setAlgorithm("PBEWITHHMACSHA512ANDAES_256");
        config.setKeyObtentionIterations("1000");
        config.setPoolSize("1");
        config.setProviderName("SunJCE");
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
        config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
        config.setStringOutputType("base64");
        encryptor.setConfig(config);

        String myEncryptedText1 = encryptor.encrypt("root");
        System.out.println("加密后:"+myEncryptedText1);
        String plainText1 = encryptor.decrypt(myEncryptedText1);
        System.out.println("解密后:"+plainText1);
    }
}

命令行方式:

放到jasypt-1.9.3.jar包的路径下myJasyptEncrypt.bat

@echo off
 set input=root
 set password=myJasyptPassword
 set algorithm=PBEWithHMACSHA512AndAES_256
 set ivGeneratorClassName=org.jasypt.iv.RandomIvGenerator
 echo 加密中......
 java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input=%input% password=%password% algorithm=%algorithm% ivGeneratorClassName=%ivGeneratorClassName%
 pause

4.2,将密文配置到配置文件里

默认的前后缀是ENC(),括号里是密文,如:

spring:
  datasource:
    driverClassName: com.mysql.cj.jdbc.Driver
    username: ENC(l8KWjRLCqT/x/PLjgKYzhgMTI2uOeTsicN8WExG/gAfak+bDCDPnDN3foKQrTlqO)
    password: ENC(vig6aKnn+B5IOAD/AHr5McuvNyFCggfibS8EyvrJpZK1llOyFvHAEMwXkVdX6BsB)

注:前后缀是可以修改的,比如修改成ENC@[]

在jasypt配置属性的地方设置,比如application.yml

jasypt:
  encryptor:
    property:
      prefix: "ENC@["
      suffix: "]"

其它

常见错误

项目启动失败,日志信息:

org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'spring.datasource.password' to java.lang.String

错误信息是无法将spring.datasource.password转换成String类型,在我们的配置文件里,spring.datasource.password是用jasypt加密的,那么导致错误的:解密spring.datasource.password的值失败

spring:
  datasource:
    password: ENC(1A1K90zmmz12mxbEFLLuzOvbJ4SBqWZX5RPLwv1bxqrXAdpEo23hhZc+7zUc6cFf)

导致解密失败的原因有很多,基本都是加密和解密用的配置信息不一样,比如加密password、加密算法、iv-generator-classname等:

1.加密时使用的加密password的值和程序运行时使用的加密password值不一样

2.加密时使用的算法algorithm的值和程序运行时使用的算法algorithm不一样

3.spring.datasource.password配置的值格式有问题,比如拼写错误、更改了加密语法的前后缀,值却还是ENC(...),应该改成ENC@[...]

jasypt:
  encryptor:
    property:
      prefix: "ENC@["
      suffix: "]"

算法

下载jasypt-1.9.3-dist.zip,在命令行执行listAlgorithms.bat脚本

下载地址:github中的README.md里的Download distributable

jasypt/jasypt: Jasypt (Java Simplified Encryption) is a java library which allows the developer to add basic encryption capabilities to his/her projects with minimum effort, and without the need of having deep knowledge on how cryptography works. (github.com)https://github.com/jasypt/jasypt

DIGEST ALGORITHMS:   [MD2, MD5, SHA, SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256]

PBE ALGORITHMS:      [PBEWITHHMACSHA1ANDAES_128, PBEWITHHMACSHA1ANDAES_256, PBEWITHHMACSHA224ANDAES_128, PBEWITHHMACSHA224ANDAES_256, PBEWITHHMACSHA256ANDAES_128, PBEWITHHMACSHA256ANDAES_256, PBEWITHHMACSHA384ANDAES_128, PBEWITHHMACSHA384ANDAES_256, PBEWITHHMACSHA512ANDAES_128, PBEWITHHMACSHA512ANDAES_256, PBEWITHMD5ANDDES, PBEWITHMD5ANDTRIPLEDES, PBEWITHSHA1ANDDESEDE, PBEWITHSHA1ANDRC2_128, PBEWITHSHA1ANDRC2_40, PBEWITHSHA1ANDRC4_128, PBEWITHSHA1ANDRC4_40]

附录

 官网:

ulisesbocchio/jasypt-spring-boot: Jasypt integration for Spring boot (github.com)Jasypt: Java simplified encryption - Jasypt: Java simplified encryption - Encrypting textsulisesbocchio/jasypt-spring-boot: Jasypt integration for Spring boot (github.com)

例子 ulisesbocchio/jasypt-spring-boot-samples: Sample apps using jasypt-spring-boot (github.com)

;