1. 程式人生 > 實用技巧 >springboot 配置引數加密——jasypt

springboot 配置引數加密——jasypt

一、方法說明

Jasypt Spring Boot為Spring Boot應用程式中的屬性源提供了加密支援。
有3種方式整合jasypt-spring-boot到您的專案中:

  • jasypt-spring-boot-starter如果使用@SpringBootApplication@EnableAutoConfiguration將在整個Spring Environment中啟用可加密的屬性,只需將starter jar新增到您的類路徑中
  • 新增jasypt-spring-boot到類路徑並新增@EnableEncryptableProperties到主Configuration類,以在整個Spring環境中啟用可加密屬性
  • 新增jasypt-spring-boot到您的類路徑並宣告單個可加密屬性源@EncrytablePropertySource

  1、如果您的Spring Boot應用程式使用@SpringBootApplication@EnableAutoConfiguration且可加密屬性將在整個Spring Environment中啟用,則只需將starter jar依賴項新增到您的專案中(這意味著任何系統屬性,環境屬性,命令列引數,application.properties,yaml屬性以及任何其他自定義屬性源可以包含加密屬性):

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

  2、如果您不使用@SpringBootApplication@EnableAutoConfiguration自動配置批註,則將此依賴項新增到您的專案中:

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

  然後新增@EnableEncryptableProperties

到您的Configuration類。例如:

@Configuration
@EnableEncryptableProperties
public class MyApplication {
    ...
}

  並且可加密屬性將在整個Spring環境中啟用(這意味著任何系統屬性,環境屬性,命令列引數,application.properties,yaml屬性以及任何其他自定義屬性源都可以包含加密屬性)

  3、如果您不使用@SpringBootApplication@EnableAutoConfiguration自動配置批註,並且不想在整個Spring Environment中啟用可加密屬性,則還有第三個選項。首先將以下依賴項新增到您的專案中:

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

  然後@EncryptablePropertySource在配置檔案中新增所需數量的註釋。就像您使用Spring的@PropertySource註釋一樣。例如:  

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

  方便地,還有一種@EncryptablePropertySources註釋可以用來對如下型別的註釋進行分組@EncryptablePropertySource

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

二、基於密碼的加密配置

Jasypt使用StringEncryptor解密屬性。對於所有這三種方法,如果在Spring Context中未找到自定義項StringEncryptor有關詳細資訊,請參見“自定義加密器”部分),則會自動建立一個可通過以下屬性(系統,屬性檔案,命令列引數,環境變數等)進行配置的方法。 ):

需要 預設值
jasypt.encryptor.password 真正 --
jasypt.encryptor.algorithm PBEWITHHMACSHA512ANDAES_256
jasypt.encryptor.key-obtention-iterations 1000
jasypt.encryptor.pool-size 1個
jasypt.encryptor.provider-name SunJCE
jasypt.encryptor.provider-class-name 空值
jasypt.encryptor.salt-generator-classname org.jasypt.salt.RandomSaltGenerator
jasypt.encryptor.iv-generator-classname org.jasypt.iv.RandomIvGenerator
jasypt.encryptor.string-output-type base64
jasypt.encryptor.proxy-property-sources
jasypt.encryptor.skip-property-sources 空清單

  唯一需要的屬性是加密密碼,其餘的可以保留為使用預設值。雖然所有這些特性可以在屬性檔案中宣告,加密密碼不應該被存放在一個屬性檔案,它應該是為系統屬性,命令列引數或環境變數傳遞並儘可能它的名字是jasypt.encryptor.password它會工作。

  最後一個屬性jasypt.encryptor.proxyPropertySources用於指示jasyp-spring-boot如何擷取屬性值以進行解密。預設值,false使用的自定義包裝的實現PropertySourceEnumerablePropertySourceMapPropertySourcetrue為此屬性指定時,攔截機制將在每個特定PropertySource實現上使用CGLib代理在某些PropertySource必須保留原件型別的情況下,這可能很有用

三、使用您自己的自定義加密器

  對於加密器的自定義配置和加密器密碼的來源,您始終可以在Spring Context中定義自己的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按version開頭的名稱檢測自定義字串Encyptors1.5預設的bean名稱是:

  jasyptStringEncryptor

  但也可以通過定義屬性來覆蓋此屬性:

  jasypt.encryptor.bean

  因此,例如,如果定義,jasypt.encryptor.bean=encryptorBean則可以使用該名稱定義自定義加密器:

   @Bean("encryptorBean")
    public StringEncryptor stringEncryptor() {
        ...
    }

四、自定義屬性檢測器,字首,字尾和/或解析器

  截至jasypt-spring-boot-1.10目前,已有新的擴充套件點。EncryptablePropertySource現在用於EncryptablePropertyResolver解析所有屬性:

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

  此介面的實現負責檢測解密屬性。預設實現DefaultPropertyResolver使用前述StringEncryptor和newEncryptablePropertyDetector

提供自定義EncryptablePropertyDetector

  您可以通過提供EncryptablePropertyDetector帶有名稱的型別的Bean來覆蓋預設實現,encryptablePropertyDetector或者如果您想提供自己的Bean名稱,覆蓋屬性jasypt.encryptor.property.detector-bean並指定您想要給Bean的名稱,則可以覆蓋預設實現提供此功能時,您將負責檢測加密的屬性。例:

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());
    }
}
@Bean(name = "encryptablePropertyDetector") public EncryptablePropertyDetector encryptablePropertyDetector() { return new MyEncryptablePropertyDetector(); }

提供自定義加密屬性,prefixsuffix

如果您要做的就是為加密屬性使用不同的字首/字尾,則可以繼續使用所有預設實現,而只需在application.properties(或application.yml)中覆蓋以下屬性

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

提供自定義EncryptablePropertyResolver

您可以通過提供EncryptablePropertyResolver帶有名稱的型別的Bean來覆蓋預設實現,encryptablePropertyResolver或者如果您想提供自己的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將停止工作,因為預設解析器使用它們。您必須自己連線所有這些東西。幸運的是,在大多數情況下,您不必重寫此bean,前面的選項就足夠了。

但是如您在實施中所見,加密屬性的檢測和解密是內部的MyEncryptablePropertyResolve

四、使用過濾器

jasypt-spring-boot:2.1.0引入了一項新功能來指定屬性過濾器。篩選器是EncryptablePropertyResolverAPI的一部分,可讓您確定要考慮解密的屬性或屬性源。這是在甚至檢查實際屬性值以搜尋或嘗試對其進行解密之前。例如,預設情況下,所有以名稱開頭的屬性jasypt.encryptor均不包括在內。這是為了避免在配置庫bean時在載入時產生迴圈依賴性。

DefaultPropertyFilter屬性

預設情況下,DefaultPropertyResolverusesDefaultPropertyFilter允許您指定以下字串模式列表:

  • jasypt.encryptor.property.filter.include-sources:指定要包括在解密中的屬性源名稱模式
  • jasypt.encryptor.property.filter.exclude-sources:指定要排除以解密的屬性源名稱模式
  • jasypt.encryptor.property.filter.include-names:指定要包括在解密中的屬性名稱模式
  • jasypt.encryptor.property.filter.exclude-names:指定要排除用於解密的屬性名稱模式

提供自定義EncryptablePropertyFilter

您可以通過提供EncryptablePropertyFilter帶有名稱的型別的Bean來覆蓋預設實現,encryptablePropertyFilter或者如果您想提供自己的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而應使用預設的解析器。如果提供自定義解析器,則您將負責檢測和解密屬性的整個過程。

參考連結

git連結jasypt-spring-boot:https://github.com/ulisesbocchio/jasypt-spring-boot