zoukankan      html  css  js  c++  java
  • SpringBoot:整合jasypt

    整合SpringBoot

    官方文档:https://github.com/ulisesbocchio/jasypt-spring-boot

    据官方文档介绍有三种方式可以引入jasypt

    第一种

    直接引入jasypt的starter

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

    第二种

    引入

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

    然后添加@EnableEncryptableProperties在你的配置类上

    第三种

    引入

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

    然后在配置类上配置如下:

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

    同时支持多个@EncryptablePropertySource注解,如下:

    @Configuration
    @EncryptablePropertySources({@EncryptablePropertySource("classpath:encrypted.properties"),
                                 @EncryptablePropertySource("classpath:encrypted2.properties")})
    public class MyApplication {
    
    }
    

    1.8以后,配置文件支持yaml格式。

    自定义环境

    我们可以这样配置自己的环境。此方法对于早期访问springboot引导的加密属性的非常有用。

    new SpringApplicationBuilder()
        .environment(new StandardEncryptableServletEnvironment())
        .sources(YourApplicationClass.class).run(args);
    

    此外,我们可以配置StandardEncryptableServletEnvironment

    StandardEncryptableServletEnvironment env = StandardEncryptableServletEnvironment
        .builder()
        .encryptor(new StandardPBEStringEncryptor())
        .build();
    
    new SpringApplicationBuilder()
        .environment(env)
        .sources(BootJasyptApplication.class).run(args);
    

    基于密码的加密配置

    所有的配置项都在JasyptEncryptorConfigurationProperties类属性中,我们直需要在yml中配置属性,就可以达到重写的目的。

    Jasypt使用StringEncryptor来解密属性。对于上述所有3个配置方法,如果在Spring上下文中找不到自定义StringEncryptor(有关详细信息,请参阅自定义Encryptor部分),则会自动创建一个,可以通过以下属性(系统、属性文件、命令行参数、环境变量等)进行配置:

    image-20210507101847493

    唯一需要的属性是加密密码,其余的可以使用默认值。虽然所有这些属性都可以在属性文件中声明,但加密程序密码不应该存储在属性文件中,而应该作为系统属性、命令行参数或环境变量传递,只要它的名称是jasypt.encryptor.password,它就可以工作。

    最后一个属性jasypt.encryptor.proxyPropertySources用于指示jasyp spring boot如何拦截属性值进行解密。默认值false使用PropertySource、EnumerablePropertySource和MapPropertySource的自定义包装器实现。当为此属性指定true时,拦截机制将在每个特定的PropertySource实现上使用CGLib代理。在某些必须保留原始PropertySource类型的场景中,这可能很有用。

    自定义加密

    默认情况下,bean容器会配置LazyJasyptStringEncryptor

    对于加密程序和加密程序密码源的自定义配置,您始终可以在Spring上下文中定义自己的StringEncryptor bean,默认的加密程序将被忽略

      @Bean("jasyptStringEncryptor")
    public StringEncryptor stringEncryptor() {
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        config.setPassword("password");
        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;
    }
    

    注意,bean名称是必需的,因为jasypt-spring-boot从版本1.5开始按名称检测自定义字符串jasyptStringEncryptor

    自定义属性探测器、前缀、后缀和/或解析器

    从jasypt-spring-boot-1.10开始,有新的可扩展点。EncryptablePropertySource现在使用EncryptablePropertyResolver解析所有属性

    public interface EncryptablePropertyResolver {
        String resolvePropertyValue(String value);
    }
    

    这个接口的实现负责检测和解密属性。默认实现DefaultPropertyResolver使用前面提到的StringEncryptor和新的EncryptablePropertyDetector

    自定义属性探测器

    您可以通过提供一个名为EncryptablePropertyDetector的EncryptablePropertyDetector类型的Bean来覆盖默认实现,或者如果您想提供自己的Bean名称,请覆盖属性jasypt.encryptor.property.detector-Bean并指定您想给Bean的名称。当提供这个时,您将负责检测加密属性。例子:

        @Bean(name = "encryptablePropertyDetector")
        public EncryptablePropertyDetector encryptablePropertyDetector() {
            return new MyEncryptablePropertyDetector();
        }
    
        private static class MyEncryptablePropertyDetector implements EncryptablePropertyDetector {
            @Override
            public boolean isEncrypted(String value) {
                if (value != null) {
                    return value.startsWith("ENC@");
                }
                return false;
            }
    
            @Override
            public String unwrapEncryptedValue(String value) {
                return value.substring("ENC@".length());
            }
        }
    

    提供自定义的加密属性前缀和后缀

    如果您只想为加密属性设置不同的前缀/后缀,则可以继续使用所有默认实现,只需覆盖application.properties(或application.yml)中的以下属性

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

    提供自定义EncryptablePropertyResolver

    您可以通过提供一个名为encryptablePropertyResolver的EncryptablePropertyResolver类型的Bean来覆盖默认实现,或者如果您想提供自己的Bean名称,请覆盖属性jasypt.encryptor.property.resolver-Bean并指定您想给Bean的名称。当提供这个时,您将负责检测和解密加密的属性。例子

    class MyEncryptablePropertyResolver implements EncryptablePropertyResolver {
    
    
        private final PooledPBEStringEncryptor encryptor;
    
        public MyEncryptablePropertyResolver(char[] password) {
            this.encryptor = new PooledPBEStringEncryptor();
            SimpleStringPBEConfig config = new SimpleStringPBEConfig();
            config.setPasswordCharArray(password);
            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);
        }
    
        @Override
        public String resolvePropertyValue(String value) {
            if (value != null && value.startsWith("{cipher}")) {
                return encryptor.decrypt(value.substring("{cipher}".length()));
            }
            return value;
        }
    }
    
    @Bean(name="encryptablePropertyResolver")
    EncryptablePropertyResolver encryptablePropertyResolver(@Value("${jasypt.encryptor.password}") String password) {
        return new MyEncryptablePropertyResolver(password.toCharArray());
    }
    

    请注意,通过重写EncryptablePropertyResolver,您对前缀、后缀、EncryptablePropertyDetector和StringEncryptor的任何其他配置或重写都将停止工作,因为使用它们的是默认解析程序

    因为,对加密属性的检测和解密是MyEncryptablePropertyResolver内部的

    过滤器

    在jasypt-spring-boot:2.1.0版本引入了一个过滤器的新特性。

    filter允许您确定要考虑哪些属性或属性源进行解密。这是,甚至在检查要搜索或尝试解密的实际属性值之前。例如,默认情况下,名称以jasypt.encryptor开头的所有属性都将从检查中排除。这是为了在配置库bean时避免在加载时循环依赖。

    默认DefaultPropertyFilter

    image-20210507112557922

    该类的所有属性都是从JasyptEncryptorConfigurationProperties.PropertyConfigurationProperties.FilterConfigurationProperties类中读取

    该类只配置了以jasypt.encryptor名字开头的会被排除,其他都是没有配置的

    image-20210507112646430

    自定义EncryptablePropertyFilter

    您可以通过提供一个名为EncryptablePropertyFilter的EncryptablePropertyFilter类型的Bean来覆盖默认实现,或者如果您想提供自己的Bean名称,请覆盖属性jasypt.encryptor.property.filter-Bean并指定您想给Bean的名称。当提供这个时,您将负责检测您想要考虑解密的属性和/或属性源

        class MyEncryptablePropertyFilter implements EncryptablePropertyFilter {
        
            public boolean shouldInclude(PropertySource<?> source, String name) {
                return name.startsWith('encrypted.');
            }
        }
        @Bean(name="encryptablePropertyFilter")
            EncryptablePropertyFilter encryptablePropertyFilter() {
                return new MyEncryptablePropertyFilter();
            }
    

    请注意,要使此机制正常工作,不应提供自定义的EncryptablePropertyResolver,而应使用默认的解析器。如果您提供自定义EncryptablePropertyResolver,那么您将负责检测和解密属性的整个过程。

    测试

    配置:我这里自己注入了一个StringEncryptor,并自定义了MyEncryptablePropertyDetector,没有使用默认的解密探测器。

    /**
     * @author wen.jie
     * @date 2021/5/7 10:30
     */
    @Configuration
    public class MyConfig {
    
        @Bean("jasyptStringEncryptor")
        public StringEncryptor stringEncryptor() {
            PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
            SimpleStringPBEConfig config = new SimpleStringPBEConfig();
            config.setPassword("password");
            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;
        }
    
        @Bean(name = "encryptablePropertyDetector")
        public EncryptablePropertyDetector encryptablePropertyDetector() {
            return new MyEncryptablePropertyDetector();
        }
    
        private static class MyEncryptablePropertyDetector implements EncryptablePropertyDetector {
            @Override
            public boolean isEncrypted(String value) {
                if (value != null) {
                    return value.startsWith("ENC@");
                }
                return false;
            }
    
            @Override
            public String unwrapEncryptedValue(String value) {
                return value.substring("ENC@".length());
            }
        }
    }
    

    测试代码:

        @Autowired
        @Qualifier("jasyptStringEncryptor")
        StringEncryptor stringEncryptor;
    
        @Test
        void contextLoads() {
            String wj = stringEncryptor.encrypt("wj");
            System.out.println(wj);
        }
    

    测试结果:

    image-20210507121948586

    我们只需要在字符串前面加上ENC@,就可以解密:配置yml

    my:
      wj: ENC@8rwL/sEZlOr9hI9ifQj6GtjTjLKKFVfj992j6QZKs6ohPN676yvnHr02vycSiwwO
    

    测试:

        @Value("${my.wj}")
        private String myWj;
    
        @Test
        void test(){
            System.out.println(myWj);
        }
    

    image-20210507122121971

  • 相关阅读:
    Nginx 部署多个 web 项目(虚拟主机)
    Nginx 配置文件
    Linux 安装 nginx
    Linux 安装 tomcat
    Linux 安装 Mysql 5.7.23
    Linux 安装 jdk8
    Linux 安装 lrzsz,使用 rz、sz 上传下载文件
    springMVC 拦截器
    spring 事务
    基于Aspectj 注解实现 spring AOP
  • 原文地址:https://www.cnblogs.com/wwjj4811/p/14738704.html
Copyright © 2011-2022 走看看