springboot集成Jasypt实现配置文件启动时自动解密-ENC

SpringBoot本身并没有自动加解密的功能,平时项目启动时,自动解密配置文件里**ENC( )**包含的数据,原因是使用了Jasypt(Java Simplified Encryption)。

一、前置条件,maven引入依赖

XML 复制代码
<!-- Spring Boot集成Jasypt核心依赖 -->
<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>3.0.5</version> <!-- 适配Spring Boot版本 -->
</dependency>

二、配置文件中设置密码和算法

要想SpringBoot在启动的时候,自动创建加解密的Bean对象,必须同时满足两个条件

一个是引入集成的依赖,【jasypt-spring-boot-starter】

另一个就是配置文件里必须指定密码【jasypt.encryptor.password】

java 复制代码
jasypt:
  encryptor:
    # 加密/解密的密码(生产环境需安全存储,可以配置在环境变量里)
    # 这里的密码用来生成符合指定算法的标准密钥(比如AES256需要32位长度的密钥,AES128需要16位长度的密钥)
    password: UmrPassword1234

    # 指定加密算法 (默认是PBEWITHHMACSHA512ANDAES_256),jdk8有些小版本有可能不支持,所以降级,方便测试
    algorithm: PBEWITHHMACSHA512ANDAES_128

    # 默认配置,会调这两个生成随机的偏移量(iv)和盐值(salt)
#    iv-generator-classname: org.jasypt.iv.RandomIvGenerator
#    salt-generator-classname: org.jasypt.salt.RandomSaltGenerator

相关源码【JasyptEncryptorConfigurationProperties】

三、测试加解密

java 复制代码
import org.jasypt.encryption.StringEncryptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;

@RestController
public class DemoController {

    @Autowired
    private StringEncryptor jasyptStringEncryptor;

    @PostConstruct
    public void init() {
        String str = "admin123456Oracle";
        String encrypt = jasyptStringEncryptor.encrypt(str);
        System.out.println("加密之后的密文:"+ encrypt);
        String decrypt = jasyptStringEncryptor.decrypt(encrypt);
        System.out.println("解密之后的明文:"+decrypt);
    }
}

运行结果

四、配置文件设置 ENC(密文)

把之前得到的加密串,用 ENC(密文) 的格式放到配置文件中

运行结果

五、疑问

既然每次 偏移量IV 是通过RandomIvGenerator随机生成的,那加解密的时候如何保证是同一个IV和Salt?

Jasypt 不会让 IV 和密文分离,会把 IV 放入最终的加密字符串,而解密的第一步就是拆分加密字符串,拿到 准确的IV 和 Salt,再利用 IV 和 Salt,对加密串进行解密。

这样做,即便是相同的明文数据,因为IV随机生成,最终生成的加密串也会不同。

具体源码在StandardPBEByteEncryptor

Salt的目的是在于结合用户密码(jasypt.encryptor.password),进行一些操作之后,生成一个标准的密钥。因为AES对称加密算法,需要一个标准密钥(AES256需要的密钥长度是32位,AES128需要的密钥长度是16位),配置文件配的用户密码(jasypt.encryptor.password)肯定是随意写的,不符合要求。

六、使用Jasypt工具类进行解密

java 复制代码
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;

public class JasyptUtil {
    private static final String secretKey = "UmrPassword1234";
    private static final String algorithm = "PBEWITHHMACSHA512ANDAES_128";

    public static void main(String[] args) {
        String encrypt = "Fnk4mSyyaLvL5iQPPRRzwcz44zS7aXFsGC3BA0lWsH3fY4nCd89+fYaLsjfK3JsfoIFNXGTHPmjbRQwsPsIiuA==";
        StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        //加密算法
        config.setAlgorithm(algorithm);
        // 指定IV生成器
        config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
        // 指定SALT生成器
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
        encryptor.setConfig(config);
        //设置加密的密钥,一般是放在配置文件里
        encryptor.setPassword(secretKey);
        try{
            String decrypt = encryptor.decrypt(encrypt);
            System.out.println("解密的明文:" + decrypt);
        }catch (Exception e){
            e.printStackTrace();
        }

    }
}

运行结果如下

如果把 生成IV的给注释掉,就会出现以下错误,提示IV长度不够,因为加解密的时候,一个用了RandomSaltGenerator,一个没用,就会出现以下错误。

七、源码解析

SpringBoot在项目启动的时候,会调用EncryptablePropertyResolver去判断,是否包含ENC,如果包含 "ENC(密文) ",就会自动进行解密

isEncryted方法满足了,才会走到这里面,说明需要解密

isEncrypted方法会判断前缀是否包含"ENC(",后缀是否包含")"

具体加解密类,【StandardPBEStringEncryptor】

八、注意事项,启动的时候出现乱码问题

如果启动的时候,解密出来是乱码的。

可能是以下情况:

①工具类和Springboot启动后使用的加解密算法不一致

②工具类指定生成偏移量(iv)或盐值(salt)的类,跟SpringBoot启动时指定的不一样

九、扩展

前面提到过,SpringBoot在启动的时候,会自动创建一个名叫jasyptStringEncryptor的bean,因此,我们可以创建一个相同名字的Bean,然后重写它的加解密方法,这样启动的时候,就会调我们自己写的加解密方法,而不是Jasypt里的加解密方法

相关推荐
万少22 分钟前
AtomCode开发微信小程序《谁去呀》 全流程
前端·javascript·后端
GetcharZp23 分钟前
Epic、暴雪都在用的 C++ 界面利器:Dear ImGui 零基础全景指南
后端
C+++Python1 小时前
详细介绍一下Java泛型的通配符
java·windows·python
pixcarp1 小时前
知识库系统的内容资产闭环怎么设计
服务器·数据库·后端·golang
红尘散仙2 小时前
别再手动录屏了:用 VHS 给终端应用生成会动的文档素材
后端·rust
JosieBook2 小时前
【数据库】时序预测能力的分级进化:TimechoAI如何让每一类用户都能精准预见未来
java·开发语言·数据库
一生了无挂3 小时前
Java处理JSON技巧教学(从基础到高阶实战全覆盖)
java·开发语言·json
李白的天不白3 小时前
使用 SmartAdmin 进行前后端开发
java·前端
swordbob3 小时前
Spring 单例 Bean 是线程安全的吗?
java·开发语言
2601_951643774 小时前
Python第一,Java跌出前三,C语言杀回来了
java·c语言·python·编程语言排行·技术趋势