1. 程式人生 > >spring、spring-boot配置檔案屬性內容加解密

spring、spring-boot配置檔案屬性內容加解密

實際專案開發過程中,我們的應用程式都有很多的配置檔案(例如properties或者yml檔案等),我們時常會遇到需要對配置檔案敏感欄位的引數內容進行加密處理(比如資料庫連線密碼、與第三方的通訊金鑰等)。

如果採用一定採用傳統的springMVC做系統整合,我們可以繼承PropertyPlaceholderConfigurer類並複寫其converProperty方法,在該方法內一般需要做兩步處理:

  • 1、根據引數名propertyName或者根據引數值propertyValue判斷當前是否需要進行內容解密。
  • 2、如果需要解密,根據系統設計呼叫解密處理邏輯,然後呼叫父級converProperty方法。

按照上面的思路,我們先實現自己的PropertyPlaceholderConfigurer子類,假如當前我們的需求是要將test.content引數值後面追加內容“《我是後加的內容》”

@Slf4j
public class MyPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
    @Override
    protected String convertProperty(String propertyName, String propertyValue) {
        //這裡做對屬性的內容的加解密等操作
//TODO something if (propertyName.equalsIgnoreCase("test.content")) { log.info("當前即將過濾的內容[" + propertyName + "]=[" + propertyValue + "]"); propertyValue = propertyValue + "《我是後加的內容》"; } else if (propertyName.equalsIgnoreCase("spring.datasource.password"
)) { propertyValue = propertyValue.replace("abc", ""); } return super.convertProperty(propertyName, propertyValue); } }

接下來,我們要是例項化我們自定義的PropertyPlaceholderConfigurer,如果我們使用xml方式配置,則程式碼如下:

<bean id="propertyConfigurer" class="com.spring.boot.test.util.MyPropertPlaceholderConfigurer">
    <property name="locations">
        <list>
        <value>classpath:application.poperties</value>
        </list>
    </property>
</bean>

如果採用javaconfig方式時程式碼如下:

    @Bean
public PropertyPlaceholderConfigurer propertyPlaceholderConfigurer(){
    PropertyPlaceholderConfigurer placeholderConfigurer=new MyPropertyPlaceholderConfigurer();
    PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    Resource resource = resolver.getResource("classpath:application.properties");
    placeholderConfigurer.setLocation(resource);
    return placeholderConfigurer;
}

通過上面的步驟,我們可以在程式的TestService中使用自動注入或者Spring表示式@Value(“$(引數名)”)獲取到的內容就是我們解密之後的內容。我們啟動程式後我們可以看到日誌內容

c.s.b.t.u.MyPropertyPlaceholderConfigurer[16] - 當前即將過濾的內容[test.content]=[測試內容]
c.s.b.t.s.TestService[24] - 當前拿到的testContent=測試內容《我是後加的內容》

遺憾的時,上述方式存在兩個缺點:

  • 1、目前只支援properties配置檔案,當我們使用yaml檔案後就不生效了,執行會報檔案格式異常,如果要生效,必須複寫底層的loadProperties方法分別對不同格式的檔案進行解析。但是這樣可能會麻煩的多。
  • 2、當我們使用spring boot後,對資料庫相關配置引數解析後,資料庫自動初始化裝配無法成功,即資料庫會在PropertyPlaceholderConfigurer類之前初始化,如果加密內容正好是資料庫連線密碼,那麼程式啟動後會因為資料庫無法連線而報錯,程式自動結束通話。錯誤內容:Failed to initialize pool: Access denied for user 'root'@'localhost' (using password: YES)

面對以上問題,直接通過修改PropertyPlaceholderConfigurer解決的路子我並沒有去測試,不過接下來我們介紹另外一種方式解決這個問題,那就是spring boot整合jasypt框架實現對配置檔案的引數內容加解密。

jasypt是一個java實現的安全框架,最新版本已經不提供PlaceholderConfigurer,所以我們很難直接使用該框架報對properties或者yml檔案進行處理,但是國外大神Ulises Bocchio寫了一個spring boot下用的工具包github地址https://github.com/ulisesbocchio/jasypt-spring-boot,該工具包支援使用jasypt框架來處理properties和yml配置檔案引數內容的加解密操作,該工具已經發布到了中央倉庫供大家使用。而且文件資訊非常詳細。下面我們簡單說一下該工具的優勢。

  • 1、該工具支援註解方式開啟jasypt功能,以及註解方式引入一個或多個需要處理的配置檔案。
  • 2、該工具同時支援properties與yml檔案的解析處理。
  • 3、該工具支援自定義加解密型別和複寫加解密方法。

在早期的版本中jasypt為spring提供過EncryptablePropertyPlaceholderConfigurer與EncryptablePropertySourcesPlaceholderConfigurer兩個類,但是後面的包中都不包含這兩個類了。如果希望使用這種方式可以參考如下兩篇部落格:

最新的1.9.2版本中以上兩個類都已經不存在了。所以推薦使用Ulises Bocchio寫工具包來做系統整合。下面我們按照其文件簡單配置一下使用思路。

首先,引入工具包依賴

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

如果不使用stater,我們可以引入如下包

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

預設情況下jasypt採用的演算法是PBEWithMD5AndDES,該演算法對同一串明文每次加密的密文都不一樣,比較適合做資料加解密。但是該演算法必須配置密碼,我們在yml檔案配置如下引數

jasypt:
  encryptor:
    password: e!Jd&ljyJ^e4I5oU

如果想要改變其他配置例如密文的前後綴也可以在這裡配置。

如果上面引入的包不是starter,那麼需要在啟動類上添加註解@EnableEncryptableProperties以啟動該功能。

然後我們寫一個junit測試類,具體內容如下

public class TestBootTest {
    @Autowired
    StringEncryptor stringEncryptor;//密碼解碼器自動注入

    @Test
    public void test() {
        System.out.println(stringEncryptor.encrypt("123456"));
    }
}

執行後的控制檯輸出123456加密後的內容:P7xVJnbrn/MCzyVEOejTRw==

小提示:在控制檯下,我們直接使用jasypt工具包進行原始資料加密可以採用如下命令

java -cp jasypt-1.9.2.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input=原文 password=密碼 algorithm=加密方式

例如,我們要對中文“原文”進行加密,密碼為123456,加密方式為PBEWithMD5AndDES,則具體命令為

java -cp jasypt-1.9.2.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input=原文 password=123456 algorithm=PBEWithMD5AndDES

執行後會在控制檯輸出如下內容

----ENVIRONMENT-----------------
Runtime: Oracle Corporation Java HotSpot(TM) 64-Bit Server VM 24.79-b02
----ARGUMENTS-------------------
algorithm: PBEWithMD5AndDES
input: 原文
password: 123456
----OUTPUT----------------------
BDhzghe2quZtDpX0ZM/e4w==

我們將spring.datasource.password的值配置為ENC(P7xVJnbrn/MCzyVEOejTRw==),為什麼需要這麼配置呢,因為預設情況下jasypt-spring-boot解析密碼的規則是字首是ENC(字尾是)。我們改造我們的單元測試工具類

public class TestBootTest {
    @Autowired
    StringEncryptor stringEncryptor;//密碼解碼器自動注入
    @Value("${spring.datasource.password}")
    private String password;
    @Autowired
    private UserInfoMapper userInfoMapper;

    @Test
    public void test() {
//        System.out.println(stringEncryptor.encrypt("123456"));
        System.out.println("連線資料庫密碼:" + password);
        System.out.println("查詢到的資訊:"+userInfoMapper.selectByUserId(1));
    }
}

啟動單元測試,可以看到日誌輸出瞭如下內容

連線資料庫密碼:123456
[2017-08-03 22:20:41,653][INFO ] c.z.h.HikariDataSource[95] - HikariPool-1 - Starting...
[2017-08-03 22:20:42,200][INFO ] c.z.h.HikariDataSource[107] - HikariPool-1 - Start completed.
查詢到的資訊:UserInfo(id=1, userName=test1, userAge=20, address=四川成都, addTime=2016-06-05 19:32:42)

可以看到採用jasypt-spring-boot-starter工具來整合spring boot與jasypt的功能成功實現了。我們看再看下配置日誌,可以看到預設情況下字串加密機預設的配置資訊

[2017-08-03 22:20:32,008][INFO ] c.u.j.StringEncryptorConfiguration[45] - Encryptor config not found for property jasypt.encryptor.algorithm, using default value: PBEWithMD5AndDES
[2017-08-03 22:20:32,009][INFO ] c.u.j.StringEncryptorConfiguration[45] - Encryptor config not found for property jasypt.encryptor.keyObtentionIterations, using default value: 1000
[2017-08-03 22:20:32,009][INFO ] c.u.j.StringEncryptorConfiguration[45] - Encryptor config not found for property jasypt.encryptor.poolSize, using default value: 1
[2017-08-03 22:20:32,010][INFO ] c.u.j.StringEncryptorConfiguration[45] - Encryptor config not found for property jasypt.encryptor.providerName, using default value: null
[2017-08-03 22:20:32,012][INFO ] c.u.j.StringEncryptorConfiguration[45] - Encryptor config not found for property jasypt.encryptor.saltGeneratorClassname, using default value: org.jasypt.salt.RandomSaltGenerator
[2017-08-03 22:20:32,029][INFO ] c.u.j.StringEncryptorConfiguration[45] - Encryptor config not found for property jasypt.encryptor.stringOutputType, using default value: base64

通過以上方式使用jasypt框架處理配置檔案引數加密的功能就基本上OK了,但是存在一定的風險,那就是程式配置檔案中,存在解密密文的密碼。因為PBEWithMD5AndDES演算法到處都可以找到實現。如果拿到了資料庫密文和演算法的密碼,那麼很容易解析出連線資料庫的密碼。一般嚴謹的做法是不會將密文資訊與解密工具放在一起,避免程式被獲取後,加密演算法和資料庫密碼密文以及解密密碼都同時被洩露。我們公司就是採用C語言寫了一個加解密工具,放在伺服器上特定的位置。有Java程式中去呼叫該工具進行解密。那麼這種情況下我們怎麼自定義解密邏輯呢?

從單元測試中可以看到我們注入了一個加解密的介面StringEncryptor,跟蹤改類的實現可以看到系統呼叫了encrypt方法用於明文加密,呼叫decrypt對密文進行解密。於是我們實現該介面,假如我們將資料庫密碼引數spring.datasource.password=123456配置為spring.datasource.password=ENC(654321),那麼在該類裡面我們要將654321替換為123456,得到我們的真實密碼。程式碼如下

public class DefaultEncryptor implements StringEncryptor {
    @Override
    public String encrypt(String message) {
        if ("123456".equalsIgnoreCase(message)) {
            message = "654321";
        }
        return message;
    }

    @Override
    public String decrypt(String encryptedMessage) {
        if ("654321".equalsIgnoreCase(encryptedMessage)) {
            log.info("將密文[654321]替換為[123456]");
            encryptedMessage = "123456";
        }
        return encryptedMessage;
    }
}

接下來,我們使用java config方式例項化該物件替換預設的StringEncryptor例項,如下

@Bean(name = "stringEncryptor")
public StringEncryptor stringEncryptor() {
    return new DefaultEncryptor();
}

我們執行單元測試,可以看到自定義密碼解碼器的日誌資訊

[2017-08-03 22:31:47,291][INFO ] c.s.b.t.u.DefaultEncryptor[22] - 將密文[654321]替換為[123456]

通過以上步驟,我們採用自定義的StringEncryptor實現了上下文中敏感資訊的自定義加解密處理。
特別說明,文中引入的jasypt-spring-boot-starter的版本是1.14,該版本要求JRE版本必須為1.8。如果要想在1.6或者1.7下執行,那麼必須使用1.4或1.5的版本的定製版本。

1.7版本下引入:

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

1.6版本下引入:

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

參考:

本人測試demo:https://github.com/hxdcts/SpringBootDemo/tree/master/SpringBootPropertyEncrypt

相關推薦

springspring-boot配置檔案屬性內容解密

實際專案開發過程中,我們的應用程式都有很多的配置檔案(例如properties或者yml檔案等),我們時常會遇到需要對配置檔案敏感欄位的引數內容進行加密處理(比如資料庫連線密碼、與第三方的通訊金鑰等)。 如果採用一定採用傳統的springMVC做系統整合,我們可以繼承P

Spring-boot配置檔案屬性大全(2.0.5版本)

# =================================================================== # COMMON SPRING BOOT PROPERTIES # # This sample file is provided as

Spring—@PropertySource讀取properties配置檔案屬性

1、示例程式碼Controller層 @Controller @RequestMapping("/test") @PropertySource("classpath:application.properties") public class TestController {   &nb

Spring Boot 配置檔案詳解:自定義屬性隨機數多環境配置

相信很多人選擇Spring Boot主要是考慮到它既能兼顧Spring的強大功能,還能實現快速開發的便捷。我們在Spring Boot使用過程中,最直觀的感受就是沒有了原來自己整合Spring應用時繁多的XML配置內容,替代它的是在pom.xml中引入模組化的Starter POMs,其中各個模組都有自己的預

spring boot 配置檔案properties,yml語法學習及屬性獲取@ConfigurationProperties和@Value

1 概述 SpringBoot使用一個全域性的配置檔案,配置檔名是固定的;當我們建立一個專案時會在resource目錄下出現一個預設的配置檔案application.properties 我們可以在裡面進行一些引數的配置,當然還有另外一種方式yml檔案application.yml(

Spring boot 配置檔案引數對映到配置屬性

【原理分析】:SpringBoot之@EnableConfigurationProperties分析 【原理分析】:在Spring Boot中使用 @ConfigurationProperties 註解, @EnableConfigurationProperties 1. pom

SpringBoot非官方教程 | 第二篇:Spring Boot配置檔案詳解

springboot採納了建立生產就緒Spring應用程式的觀點。 Spring Boot優先於配置的慣例,旨在讓您儘快啟動和執行。在一般情況下,我們不需要做太多的配置就能夠讓spring boot正常執行。在一些特殊的情況下,我們需要做修改一些配置,或者需要有自己的配置屬性。 當我們

Spring Boot配置檔案和常見操作

Spring Boot配置檔案和常見操作 Spring Boot專案釋出成jar包 Spring Boot配置方式 命令列方式 應用程式屬性檔案: application.properties 參考文獻 Sp

Spring Boot 配置檔案設定(三)

簡介 上篇我們做了一些簡單的執行檔案的配置,本篇帶領大家來認識常用的一些配置,當然了關於Spring Boot 這些配置太多太多了,如果想了解更多的話直接上官網參考一下,瞭解相關案例如本篇的配置。 application.properties配置官方指南參考。

Spring boot 配置檔案詳解 (properties 和yml )

從其他框架來看 我們都有自己的配置檔案, hibernate有hbm,mybatis 有properties, 同樣, Spring boot 也有全域性配置檔案。 Springboot使用一個全域性的配置檔案,而且配置檔案的名字是固定的。 有兩種 application.properties

SpringBoot學習第二篇:Spring Boot配置檔案詳解

原文首發於:https://www.fangzhipeng.com/springboot/2017/07/11/springboot2-config-file/ 本文出自方誌朋的部落格 springboot採納了建立生產就緒Spring應用程式的觀點。 Spring Boot優先於配置的慣例,旨

Spring Boot配置檔案詳解-ConfigurationProperties和Value優缺點-(轉)好文

文章轉自 http://www.cnblogs.com/itdragon/p/8686554.html Spring Boot提供了兩種常用的配置檔案,分別是properties檔案和yml檔案。他們的作用都是修改Spring Boot自動配置的預設值。相對於properties檔案而言,yml檔

spring boot 配置檔案中引數的使用

自定義引數 book.name=springBoot book.author=spring @可以通過@Value 註解來載入這些自定義引數: public class Book{ @Value("${book.name}") private String name

Spring Boot配置檔案全面詳解

Spring Boot在工作中是用到的越來越廣泛了,簡單方便,有了它,效率提高不知道多少倍。Spring Boot配置檔案對Spring Boot來說就是入門和基礎,經常經常會用到,所以寫下做個總結以便日後檢視。 1.配置檔案 當我們構建完Spring Boot專案後,會在resources目錄下給我們一

第一篇 Spring boot 配置檔案筆記

  spring boot 不需要配置太多檔案程式便可正常執行,特殊情況需要我們自己配置檔案。   專案以IDEA寫例項,系統會預設在src/main/java/resources目錄下建立application.properties檔案,配置檔案支援兩種格式properties/yml。 prop

spring Boot 配置檔案:Profile

1、多Profile 我們在主配置檔案編寫的時候,檔名可以是 application-{profile}.properties/yml 預設使用application.properties的配置; 2 yml檔案---代表不同的doucement          啟

企業級 SpringBoot 教程 (二)Spring Boot配置檔案詳解

springboot採納了建立生產就緒Spring應用程式的觀點。 Spring Boot優先於配置的慣例,旨在讓您儘快啟動和執行。在一般情況下,我們不需要做太多的配置就能夠讓spring boot正常執行。在一些特殊的情況下,我們需要做修改一些配置,或者需要有自己的配置屬性

第二篇:Spring Boot配置檔案詳解

Spring Boot採納了建立生產就緒Spring應用程式的觀點。 Spring Boot優先於配置的慣例,旨在讓您儘快啟動和執行。在一般情況下,我們不需要做太多的配置就能夠讓Spring Boot正常執行。在一些特殊的情況下,我們需要做一些配置修改,或者配置自定義屬性。 自定義屬

轉載:SpringBoot非官方教程 | 第二篇:Spring Boot配置檔案詳解

springboot採納了建立生產就緒Spring應用程式的觀點。 Spring Boot優先於配置的慣例,旨在讓您儘快啟動和執行。在一般情況下,我們不需要做太多的配置就能夠讓spring boot正常執行。在一些特殊的情況下,我們需要做修改一些配置,或者需要

《深入理解Spring Cloud與微服務構建》學習筆記(二)~使用Spring Boot配置檔案

接上一章demo: 一、IDEA在建立完Spring Boot專案時,會在src/main/resources目錄下生成一個application.properties檔案,使用者進行系統屬性配置,預設為空。Spring Boot也支援yml格式的檔案配置,當前使用yml檔案