springboot集成jasypt 遇到 String Encryptor custom Bean not found with name ‘xxxEncryptor‘

一。问题场景

使用了 springboot 集成 jasypt 版本使用的最新版本 3.0.5
其他的环境如下
spring cloud 2021.0.5
spring cloud alibaba 2021.0.5.0
spring boot 2.6.13

并且使用到jasypt 的自定义加解密 具体的报错信息如下

java.lang.IllegalStateException: String Encryptor custom Bean not found with name 'sm4Encryptor'
	at com.ulisesbocchio.jasyptspringboot.encryptor.DefaultLazyEncryptor.lambda$new$2(DefaultLazyEncryptor.java:44)
	at java.base/java.util.Optional.orElseGet(Optional.java:364)
	at com.ulisesbocchio.jasyptspringboot.encryptor.DefaultLazyEncryptor.lambda$new$3(DefaultLazyEncryptor.java:42)
	at com.ulisesbocchio.jasyptspringboot.util.Singleton.lambda$new$6(Singleton.java:97)
	at com.ulisesbocchio.jasyptspringboot.util.Singleton.get(Singleton.java:109)
	at com.ulisesbocchio.jasyptspringboot.encryptor.DefaultLazyEncryptor.decrypt(DefaultLazyEncryptor.java:73)
	at com.ulisesbocchio.jasyptspringboot.resolver.DefaultPropertyResolver.lambda$resolvePropertyValue$0(DefaultPropertyResolver.java:61)
	at java.base/java.util.Optional.map(Optional.java:260)
	at com.ulisesbocchio.jasyptspringboot.resolver.DefaultPropertyResolver.resolvePropertyValue(DefaultPropertyResolver.java:57)
	at com.ulisesbocchio.jasyptspringboot.resolver.DefaultLazyPropertyResolver.resolvePropertyValue(DefaultLazyPropertyResolver.java:69)
	at com.ulisesbocchio.jasyptspringboot.caching.CachingDelegateEncryptablePropertySource.getProperty(CachingDelegateEncryptablePropertySource.java:74)
	at com.ulisesbocchio.jasyptspringboot.wrapper.EncryptableMapPropertySourceWrapper.getProperty(EncryptableMapPropertySourceWrapper.java:40)
	at org.springframework.core.env.PropertySourcesPropertyResolver.getProperty(PropertySourcesPropertyResolver.java:85)
	at org.springframework.core.env.PropertySourcesPropertyResolver.getPropertyAsRawString(PropertySourcesPropertyResolver.java:74)
	at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:153)
	at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
	at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:239)
	at org.springframework.core.env.AbstractPropertyResolver.resolvePlaceholders(AbstractPropertyResolver.java:202)
	at org.springframework.core.env.AbstractEnvironment.resolvePlaceholders(AbstractEnvironment.java:625)
	at java.base/java.util.Optional.map(Optional.java:260)
	at com.ulisesbocchio.jasyptspringboot.resolver.DefaultPropertyResolver.resolvePropertyValue(DefaultPropertyResolver.java:55)
	at com.ulisesbocchio.jasyptspringboot.resolver.DefaultLazyPropertyResolver.resolvePropertyValue(DefaultLazyPropertyResolver.java:69)
	at com.ulisesbocchio.jasyptspringboot.caching.CachingDelegateEncryptablePropertySource.getProperty(CachingDelegateEncryptablePropertySource.java:74)
	at com.ulisesbocchio.jasyptspringboot.wrapper.EncryptableMapPropertySourceWrapper.getProperty(EncryptableMapPropertySourceWrapper.java:40)
	at org.springframework.cloud.bootstrap.encrypt.AbstractEnvironmentDecrypt.merge(AbstractEnvironmentDecrypt.java:103)
	at org.springframework.cloud.bootstrap.encrypt.AbstractEnvironmentDecrypt.merge(AbstractEnvironmentDecrypt.java:81)
	at org.springframework.cloud.bootstrap.encrypt.AbstractEnvironmentDecrypt.decrypt(AbstractEnvironmentDecrypt.java:69)
	at org.springframework.cloud.bootstrap.encrypt.EnvironmentDecryptApplicationInitializer.initialize(EnvironmentDecryptApplicationInitializer.java:95)
	at org.springframework.cloud.bootstrap.BootstrapApplicationListener$DelegatingEnvironmentDecryptApplicationInitializer.initialize(BootstrapApplicationListener.java:409)

二。问题定位

从报错信息来看 提示String Encryptor 自定义的bean没有 bean是新定义的 bean的名称也确认无误 使用配置方法如下

/**
 * @author leon
 * @date 2023-08-19 15:58:42
 */
@Slf4j
@Configuration
public class JasyptConfig {

    @Bean("sm4Encryptor")
    public StringEncryptor stringEncryptor() {
        log.info("JasyptConfig 初始化:{}", "sm4Encryptor");
        return new Sm4Encryptor();
    }
}    

bean名称无误 ,注册方式没问题。 那就是需要获取bean的时间段内 bean还没有初始化,导致这个时间段无法获取成功,那解决的办法就是让这个bean提前加载

三。解决

(1) 去除之前的自定义配置JasyptConfig
(2)首先实现自定义的加密工具 需要实现 StringEncryptor 即可 我们这是用的国密4的对称加密算法 同时使用了 hutool的工具类 (已经完成)

import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.SM4;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.StopWatch;
import org.jasypt.encryption.StringEncryptor;

import java.nio.charset.StandardCharsets;

/**
 * @author leon
 * @date 2023-08-19 10:54:32
 */
@Slf4j
public class Sm4Encryptor implements StringEncryptor {

    private static final SM4 SM_4;


    static {
        byte[] key = "1234567891234560".getBytes();
        byte[] iv = "1234567891234560".getBytes();
        SM_4 = new SM4(Mode.CBC, Padding.PKCS5Padding, key, iv);
    }

    @Override
    public String encrypt(String message) {
      	return SM_4.encryptHex(message);
    }

    @Override
    public String decrypt(String encryptedMessage) {
      	return SM_4.decryptStr(encryptedMessage);
    }

    public static void main(String[] args) {
       
        String originalValue = "123456";
        String encrypted = SM_4.encryptHex(originalValue);
        String decrypted = SM_4.decryptStr(encrypted);
        log.info("Original Value: {}" , originalValue);
        log.info("Encrypted Value: {}" , encrypted);
        log.info("Decrypted Value: {}", decrypted);
    }


}

(3)注册该bean 这需要使用特殊的方式注册bean,我们希望在 Spring Boot 应用程序启动期间提前将自定义的加解密类添加到 Spring 的应用程序上下文中,以便在配置文件加载之前,加解密类已经可用。这样可以确保配置文件中的加密属性能够在加载时使用正确的自定义加解密逻辑进行解密

新建初始化类

import com.stlye.encryptor.Sm4Encryptor;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * @date 2023-08-21 13:57:20
 * @author leon
 */
public class CustomContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        applicationContext.getBeanFactory().registerSingleton("sm4Encryptor", new Sm4Encryptor());
    }
}

(4)其次在resource 下新建 META_INF文件夹 并新建 spring.factories 文件

org.springframework.context.ApplicationContextInitializer=com.style.order.config.CustomContextInitializer

重点是这里 因为我们希望在 Spring Boot 应用程序启动期间提前将自定义的加解密类添加到 Spring 的应用程序上下文中,以便在配置文件加载之前,加解密类已经可用。这样可以确保配置文件中的加密属性能够在加载时使用正确的自定义加解密逻辑进行解密 ,所以我们需要如上方式提前注册bean。

再次启动发现 可以正常启动了 无这个错误

你可能感兴趣的:(java,spring,boot,spring,cloud,jasypt)