提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
一、Jasypt介绍
前言
- 在大多数项目中,配置文件中的 mysql 数据库密码、redis 密码等其他敏感性密码都是以明文形式存在,这种配置本身没有任何问题,但是,在某些情况下,可能会对公司造成不可挽救的损失,比如:某一天,小明因为加班过度,头脑发昏,不小心把公司项目上传到自己的GitHub 仓库里面了,导致的后果就是,公司数据库用户名密码泄露,被某些大佬加以利用…
- 所以,基于上面这种情况,加入配置文件中数据库用户密码等其他敏感信息都是经过加密处理过的呢???是不是可以大概率避免这种情况。Jasypt因此应运而生。
什么是Jasypt?
- Jasypt 是一个 java 库,可以使开发者不需要太多操作来给 Java 项目添加基本加密功能,而且不需要知道加密原理。Jasypt为开发人员提供了一种简单易用加密功能,包括:密码认证、字符串加密等。
Jasypt 有哪些特点?
-
高安全性、基于标准的加密技术,适用于单向和双向加密。加密密码、文本、数字、二进制文件
-
文本加密与解密:Jasypt允许你加密字符串,并在需要时轻松解密回原始形式。这对于存储如数据库密码、API密钥等敏感信息非常有用。
-
密码器支持:它支持多种加密算法(如PBEWITHMD5ANDDES、PBEWITHSHA256AND256BITAES-CBC-BC等),并允许自定义加密策略。
-
配置文件加密:特别适用于Spring框架,Jasypt可以透明地解密在配置文件中加密的属性,比如数据库连接字符串中的密码。
-
环境感知:可以在不同的环境中(如开发、测试、生产)使用不同的加密策略和密钥,增强安全性。
-
无状态操作:Jasypt的加密操作不依赖于外部状态,使得它易于部署和使用。
-
集成友好:提供了与Spring框架的紧密集成,可以通过Spring Boot Starter轻松配置和使用。
哪些信息要加密呢?
一般来说,项目配置文件里,所有涉及信息安全的配置项(或字段)都应该做处理,典型的比如:
- 数据库密码,如mysql
- 第三方缓存中间件的密码,如 redis、mongodb
- 其他中间件,如消息中间件、zk、nacos等
- 各种第三方服务的 Access_Key
用途
- 安全存储配置信息:在配置文件中加密mysql、redis等数据库密码,防止明文泄露。
- 应用内加密逻辑:在应用内部对敏感数据进行加解密操作,例如用户密码的存储和验证。
- 日志安全:在记录包含敏感信息的日志前对其进行加密,确保日志安全。
- 数据交换安全:在不同系统间交换数据时,对数据进行加密传输,保障数据传输的安全性。
二、Springboot整合Jasypt
环境配置
- SpringBoot2.0以上
- Jasypt 3.0.3
- jdk8
2.1 添加依赖
创建一个 Springboot 项目,项目版本 2.0 以上,并添加 Jasypt 相关依赖。
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
2.2 添加Jasypt配置
jasypt:
encryptor:
# 盐值
password: 123
# 指定加密方式
algorithm: PBEWithMD5AndDES
iv-generator-classname: org.jasypt.iv.NoIvGenerator
property:
# 标识为加密属性的前缀
prefix: ENC(
# 标识为加密属性的后缀
suffix: )
2.3 编写加/解密工具类
public class JasyptUtil {
/**
* PBE 算法
*/
public static final String PBE_ALGORITHMS_MD5_DES = "PBEWITHMD5ANDDES";
public static final String PBE_ALGORITHMS_MD5_TRIPLEDES = "PBEWITHMD5ANDTRIPLEDES";
public static final String PBE_ALGORITHMS_SHA1_DESEDE = "PBEWITHSHA1ANDDESEDE";
public static final String PBE_ALGORITHMS_SHA1_RC2_40 = "PBEWITHSHA1ANDRC2_40";
private JasyptUtil() {
}
/**
* Jasypt 加密
*
* @param encryptedStr 加密字符串
* @param password 盐值
* @return
*/
public static String encrypt(String encryptedStr, String password) {
return encrypt(encryptedStr, PBE_ALGORITHMS_MD5_DES, password);
}
/**
* Jasypt 加密
*
* @param encryptedStr 加密字符串
* @param algorithm 加密算法
* PBE ALGORITHMS: [PBEWITHMD5ANDDES, PBEWITHMD5ANDTRIPLEDES, PBEWITHSHA1ANDDESEDE, PBEWITHSHA1ANDRC2_40]
* @param password 盐值
* @return
*/
public static String encrypt(String encryptedStr, String algorithm, String password) {
// StandardPBEStringEncryptor、StandardPBEBigDecimalEncryptor、StandardPBEBigIntegerEncryptor、StandardPBEByteEncryptor
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
EnvironmentPBEConfig config = new EnvironmentPBEConfig();
// 指定加密算法
config.setAlgorithm(algorithm);
// 加密盐值
config.setPassword(password);
//config.setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator");
encryptor.setConfig(config);
// 加密
return encryptor.encrypt(encryptedStr);
}
/**
* Jasypt 解密
*
* @param decryptStr 解密字符串
* @param password 盐值
* @return
*/
public static String decrypt(String decryptStr, String password) {
return decrypt(decryptStr, PBE_ALGORITHMS_MD5_DES, password);
}
/**
* Jasypt 解密
*
* @param decryptStr 解密字符串
* @param algorithm 指定解密算法:解密算法要与加密算法一一对应
* PBE ALGORITHMS: [PBEWITHMD5ANDDES, PBEWITHMD5ANDTRIPLEDES, PBEWITHSHA1ANDDESEDE, PBEWITHSHA1ANDRC2_40]
* @param password 盐值
* @return
*/
public static String decrypt(String decryptStr, String algorithm, String password) {
// StandardPBEStringEncryptor、StandardPBEBigDecimalEncryptor、StandardPBEBigIntegerEncryptor、StandardPBEByteEncryptor
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
EnvironmentPBEConfig config = new EnvironmentPBEConfig();
// 指定解密算法:解密算法要与加密算法一一对应
config.setAlgorithm(algorithm);
// 加密秘钥
config.setPassword(password);
//config.setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator");
encryptor.setConfig(config);
// 解密
return encryptor.decrypt(decryptStr);
}
public static void main(String[] args) {
String encryptedStr = "I am the string to be encrypted";
String algorithm = PBE_ALGORITHMS_SHA1_RC2_40;
String password = "salt";
String str = JasyptUtil.encrypt(encryptedStr, algorithm, password);
System.out.println("加密后的字符串:" + str);
System.out.println("解密后的字符串:" + JasyptUtil.decrypt(str, algorithm, password));
}
}
2.4 修改配置文件
2.5 自定义加密器
- 在上面的内容中,使用的是默认的加密规则,这一点会让当自定义加密盐 (jasypt.encryptor.password) 泄漏时可能变得不安全。那么如何进一步防止密码泄露安全呢?
2.5.1 自定义加密器
- 为了进一步防止密码泄露,我们可以自定义加密规则。
- 自定义加密规则非常简单,只需要提供自定义的加密器配置类,然后通过jasypt.encryptor.bean配置指定加密配置类即可。
/**
* 自定义加密器
*/
public class MyStringEncryptor implements StringEncryptor {
/**
* 加解密PBE 算法
*/
public static final String PBE_ALGORITHMS_MD5_DES = "PBEWITHMD5ANDDES";
public static final String PBE_ALGORITHMS_MD5_TRIPLEDES = "PBEWITHMD5ANDTRIPLEDES";
public static final String PBE_ALGORITHMS_SHA1_DESEDE = "PBEWITHSHA1ANDDESEDE";
public static final String PBE_ALGORITHMS_SHA1_RC2_40 = "PBEWITHSHA1ANDRC2_40";
/**
* 加解密盐值
*/
private String password;
/**
* 加解密算法
*/
private String algorithm = PBE_ALGORITHMS_MD5_DES;
public MyStringEncryptor(String password) {
this.password = password;
}
public MyStringEncryptor(String password, String algorithm) {
this.password = password;
this.algorithm = algorithm;
}
@Override
public String encrypt(String message) {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
// 加解密盐值
encryptor.setConfig(getConfig(this.password));
return encryptor.encrypt(message);
}
@Override
public String decrypt(String encryptedMessage) {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
encryptor.setConfig(getConfig(this.password));
return encryptor.decrypt(encryptedMessage);
}
public SimpleStringPBEConfig getConfig(String password) {
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
// 加密盐值
config.setPassword(password);
// 加解密算法
config.setAlgorithm(PBE_ALGORITHMS_MD5_DES);
// 设置密钥获取迭代次数
config.setKeyObtentionIterations(1000);
// 线程池大小:默认1
config.setPoolSize(1);
// 盐值生成器className
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
// iv(initialization vector,初始化向量) 生成器className
config.setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator");
// 设置字符串输出类型
config.setStringOutputType("base64");
return config;
}
}
将自定义加密器添加到 Spring IoC 容器中。
@Configuration
public class JasyptConfig {
/**
* 加解密盐值
*/
@Value("${jasypt.encryptor.password}")
private String password;
// @Bean("jasyptStringEncryptor")
@Bean("myStringEncryptor")
public StringEncryptor myStringEncryptor() {
return new MyStringEncryptor(password);
}
}
修改配置文件
jasypt:
encryptor:
# 指定加解密在spring ioc容器中bean的名称,默认 jasyptStringEncryptor
bean: myStringEncryptor
# 盐值
password: 123
注意:Jasypt默认加解密器beanName为jasyptStringEncryptor,如果不想在配置文件中指定自定义加密器名称,需将自定义加密器beanName设置为jasyptStringEncryptor,否则将不生效。