Spring Cloud之 Config 中 配置文件的加密與解密

Spring Cloud Config 中配置文件的加密與解密

上篇文章和大家聊了 Spring Cloud Config 分佈式配置中心的基本用法,相信大家對 Spring Cloud Config 已經有了一個基本的認識。可能有讀者也發現問題了,原本在非分佈式環境下,一些由運維工程師掌握的敏感信息現在不得不寫在配置文件中了,這樣網傳的程序員刪庫跑路的段子可能就成真了!但是在微服務中,我們又不太可能讓運維工程師手動去維護這些信息,因爲工作量太大了,那麼一個好的辦法,就是對這些配置信息進行加密,這也是我們本文要說的重點。

常見加密方法

說到加密,需要先和大家來捋一捋一些常見的加密策略,首先,從整體上來說,加密分爲兩大類:

  • 不可逆加密
  • 可逆加密

  • 不可逆加密就是大家熟知的在 Spring Security 或者 Shiro 這一類安全管理框架中我們對密碼加密經常採取的方案。這種加密算法的特點就是不可逆,即理論上無法使用加密後的密文推算出明文,常見的算法如 MD5 消息摘要算法以及 SHA 安全散列算法, SHA 又分爲不同版本,這種不可逆加密相信大家在密碼加密中經常見到。

    可逆算法看名字就知道,這種算法是可以根據密文推斷出明文的,可逆算法又分爲兩大類:

  • 對稱加密
  • 非對稱加密
  • 對稱加密是指加密的密鑰和解密的密鑰一致,例如 A 和 B 之間要通信,爲了防止別人偷聽,兩個人提前約定好一個密鑰。每次發消息時, A 使用這個密鑰對要發送的消息進行加密,B 收到消息後則使用相同的密鑰對消息進行解密。這是對稱加密,常見的算法有 DES、3DES、AES 等。

    對稱加密在一些場景下並不適用,特別是在一些一對多的通信場景下,於是又有了非對稱加密,非對稱加密就是加密的密鑰和解密的密鑰不是同一個,加密的密鑰叫做公鑰,這個可以公開告訴任何人,解密的密鑰叫做私鑰,只有自己知道。非對稱加密不僅可以用來做加密,也可以用來做簽名,使用場景還是非常多的,常見的加密算法是 RSA 。

    配置文件加密肯定是可逆加密,不然給我一個加密後的字符串,我拿着也沒用,還是沒法使用。可逆算法中的對稱加密和非對稱加密在 Spring Cloud Config 中都得到支持,下面我們就分別來看。

    對稱加密

    Java 中提供了一套用於實現加密、密鑰生成等功能的包 JCE(Java Cryptography Extension),這些包提供了對稱、非對稱、塊和流密碼的加密支持,但是默認的 JCE 是一個有限長度的 JCE ,我們需要到 Oracle 官網去下載一個不限長度的 JCE :
    不限長度JCE下載地址

    下載完成後,將下載文件解壓,解壓後的文件包含如下三個文件:
    在這裏插入圖片描述
    將 local_policy.jar 和 US_export_policy.jar 兩個文件拷貝到 JDK 的安裝目錄下,具體位置是 %JAVA_HOME%\jre\lib\security ,如果該目錄下有同名文件,則直接覆蓋即可。

    下面我們開始創建工程實現。首先我們創建一個父工程叫cloud-config-salt的普通maven工程,然後再創建一個cloudConfig作爲子工程,再創建一個cloudRepo作爲子工程。然後我們在cloudConfig的目錄下創建兩個SpringBoot工程,分別是config_client和config_server,然後再cloudRepo的目錄下創建一個client1的文件夾用來放配置文件。

    這些都準備好了後,我們在cloud_config的resource下創建一個bootstrap.yml
    並且增加如下配置:

    encrypt:
      key: 666666
    

    這裏我們配置了我們的密鑰爲666666, 然後我們去訪問下面這個接口來檢查我們的配置是否正確http://localhost:8081/encrypt/status
    在這裏插入圖片描述
    可以看到訪問這個接口返回的是ok,說明是沒有問題的。

    我們使用post方法來訪問http://localhost:8081/encrypt 加密接口:
    在這裏插入圖片描述
    這裏我們對普通對文本內容:love coding進行了加密,加密返回後內容如下:
    在這裏插入圖片描述
    拿到加密後的字符串後,我們肯定要進行解密,那麼我們訪問解密接口http://127.0.0.1:8081/decrypt
    在這裏插入圖片描述
    傳入已經加密的字符串,然後得到解密的字符串:
    在這裏插入圖片描述
    這樣就完成了解密。
    當然這只是在本地倉庫中使用,那麼我修改v本地倉庫中的config-server-dev.yml配置文件。將加密的字符串拷貝進來如下:

    love: '{cipher}AQBBRuFnazIXBRpoHaaSbGe4IfnNAVUfB06odDRFf9WAzGlaZ0inHvr6rJTjZ1mIB2IihSBV3C2dn4YQOr8NSHOh7Tknr2MNvHYiwaMfDWk15Y0nbzd1Ndl77Bh8py144WKMCSmzaMVbswiLWn5WrwZ23Aje6a9G+MtjOXQ2cjIJKdf/0nXHzloaaT2Y3SsWOTF65N3v94C39RueCGaHz44QtAABA6AMJSqiW5KRmGaY162xlcLLxifbdTQn9vNeztAxEWsZY/eSCx1pgZIC0NkA2ekDlOfVwHrqvkWw41DMwHXHRLpPXVNoiwieMcVRKdPufco6AHn2pbDRXGYcOwZ64tOviUoKA9f0edWjIYJ8UpNZ+uVAB6EfpiFjQBV85zo='
    

    這就是config-server-dev.yml中的內容,注意{cipher} 不要忘記了。只有加上它我們才能解密。

    這樣修改完成後,我們需要同步到github倉庫,這裏步驟就不闡述了。

    然後我們創建一個config_client項目,然後作爲子項目,並且加入config client的依賴:

    <dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.cloud</groupId>
    			<artifactId>spring-cloud-starter-config</artifactId>
    		</dependency>
    

    加入依賴後,我們創建一個HelloController如下:

    @RestController
    public class HelloController {
        @Value("${love}")
        String love;
    
        @GetMapping("/hello")
        public String hello() {
            return love;
        }
    }
    

    其中的love 就是我們從遠端倉庫讀取的配置名稱。
    然後我們訪問http://localhost:8002/hello 結果如下:
    在這裏插入圖片描述
    我們的遠端解密就完成了。

    非對稱解密

    當然我們也可以使用非對稱加密的方式來對配置文件進行加密,非對稱加密要求我們先有一個密鑰,密鑰的生成我們可以使用 JDK 中自帶的 keytool。keytool 是一個 Java 自帶的數字證書管理工具 ,keytool 將密鑰(key)和證書 (certificates) 存在一個稱爲 keystore 的文件中。具體操作步驟如下:
    首先打開命令行窗口,輸入如下命令:

    keytool -genkeypair -alias config-server -keyalg RSA -keystore /Users/zhoubiao/Desktop/config-server.keystore
    

    上面參數的解釋如下:

  • -genkeypair 表示生成密鑰對
  • -alias 表示 keystore 關聯的別名
  • -keyalg 表示指定密鑰生成的算法
  • -keystore 指定密鑰庫的位置和名稱
  • 執行過程中,密鑰庫口令需要牢記,這個我們在後面還會用到。其它的信息可以輸入也可以直接回車表示 Unknown ,自己做練習無所謂,實際開發中還是建議如實填寫。好了,這個命令執行完成後,在 /Users/zhoubiao/Desktop路徑下就會生成一個名爲 config-server.keystore 的文件,將這個文件直接拷貝到 config_server 項目的 classpath 下,如下:
    在這裏插入圖片描述

    然後在 config_server 的 bootstrap.yml 文件中,添加如下配置(注意註釋掉對稱加密時的那一行配置:

    encrypt:
      key-store:
        location: config-server.keystore
        alias: config-server
        password: 123456
        secret: 123456
    

    配置完成後,重新啓動 config_server 。啓動成功後,加密解密的鏈接地址和對稱加密都是一樣的,因此,我們可以繼續 http://localhost:8081/decrypt 對文本進行加密:
    在這裏插入圖片描述
    加密後的字符串:
    在這裏插入圖片描述
    然後訪問 http://localhost:8081/decrypt 進行解密:
    在這裏插入圖片描述
    解密後的字符串
    在這裏插入圖片描述
    那麼我們需要修改本地的config-server-dev.yml配置文件新增一個加密的配置如下:

    name: '{cipher}AQA/T13gboCx9ai1toFG+xUfTUHsJ1pU3VU78l1cQebdUwPcLuN+X8KWi0SZPe8bIkFdjYS0uYC/q8WFlLCX5oWZIpoo7tj08cziFxlyBZSGgL9U8me+PHEg4GM34DL4wSpSvTTWKx6S9Ebtzhq7IUaMZZ6HQNrg9TfTq7jx6aYou1DOpELUhdOphKfYl45rCw7NRUZbLU5eevIXMC3QW6ImppqjwMtyVQ/2hBVYsy8TAIG4tKfCztwOJ/HnnTNhz8yHkWQUkGenWyQJ39c0UwXqREm57x7ZFsfa/AEPmd5blV9sRcllfLRu1IaruYI+PcgvS7le+V8lQPBPjJ2TA/qSacKkKhBTelbi8MCqNAmehPjwaBYdfEyrPZQuY+XHTAY='
    

    然後上傳到github倉庫。然後我們修改config_client中的HelloController

    @RestController
    public class HelloController {
        @Value("${love}")
        String love;
        
        @Value("${name}")
        String name;
    
        @GetMapping("/hello")
        public String hello() {
            return love;
        }
        
        @GetMapping("/name")
        public String name() {
            return name;
        }
    }
    

    其中的name就是我們新增加的。然後我們重啓config_server然後訪問

    http://localhost:8002/name
    

    結果如下:
    在這裏插入圖片描述
    這樣就完成了解密。

    安全管理

    目前的 config_server 存在很大的安全隱患,因爲所有的數據都可以不經過 config_client 直接訪問。出於數據安全考慮,我們要給 config_server 中的接口加密。在 Spring Boot 項目中,項目加密方案當然首選 Spring Security ,使用 Spring Security 也很簡單,只需要在 config_server 項目中添加如下依賴即可:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    

    添加完成之後,重啓 config_server 項目,然後瀏覽器中輸入 http://localhost:8081/config-server/dev/master

    在這裏插入圖片描述
    可以看到,此時接口已經被保護起來了,必須要登錄之後才能訪問,我們輸入用戶名jishu,密碼123456 就可以訪問我們遠端的配置文件了。

    總結

    本篇主要教大家配置中心的加密和解密,以及使用SpringSecurity來對配置中心進行安全保護。下一節將會教大家如何做到動態刷新、重試。

    源碼地址

    github

    發表評論
    所有評論
    還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
    相關文章