目录
目录
项目背景
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
Key | Required | Default Value |
jasypt.encryptor.password | True | - |
jasypt.encryptor.algorithm | False | PBEWITHHMACSHA512ANDAES_256 |
jasypt.encryptor.key-obtention-iterations | False | 1000 |
jasypt.encryptor.pool-size | False | 1 |
jasypt.encryptor.provider-name | False | SunJCE |
jasypt.encryptor.provider-class-name | False | null |
jasypt.encryptor.salt-generator-classname | False | org.jasypt.salt.RandomSaltGenerator |
jasypt.encryptor.iv-generator-classname | False | org.jasypt.iv.RandomIvGenerator |
jasypt.encryptor.string-output-type | False | base64 |
jasypt.encryptor.proxy-property-sources | False | false |
jasypt.encryptor.skip-property-sources | False | empty 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
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)