加密和解密
要使用加密和解密功能,您需要在 JVM 中安裝完全強度的 JCE(預設不包含)。您可以從 Oracle 下載“Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files”,然後按照安裝說明進行操作(本質上,您需要將 JRE lib/security 目錄中的兩個策略檔案替換為您下載的檔案)。 |
如果遠端屬性源包含加密內容(以 {cipher}
開頭的值),它們會在透過 HTTP 傳送到客戶端之前被解密。這種設定的主要優點是屬性值在“靜止狀態”(例如,在 Git 倉庫中)時不需要是純文字。如果某個值無法解密,它將從屬性源中移除,並新增一個帶有相同鍵但以 invalid
為字首的附加屬性,其值表示“不適用”(通常是 <n/a>
)。這主要是為了防止密文被用作密碼並意外洩露。
如果您為 Config Client 應用程式設定了遠端配置倉庫,它可能包含一個類似於以下內容的 application.yml
檔案
spring:
datasource:
username: dbuser
password: '{cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ'
application.properties
檔案中的加密值不能用引號括起來。否則,該值將不會被解密。以下示例顯示了有效的配置值
spring.datasource.username: dbuser spring.datasource.password: {cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ
您可以安全地將此純文字推送到共享 Git 倉庫,並且秘密密碼仍受到保護。
伺服器還暴露了 /encrypt
和 /decrypt
端點(假設這些端點是安全的,並且只能由授權代理訪問)。如果您編輯遠端配置檔案,可以使用 Config Server 透過向 /encrypt
端點發送 POST 請求來加密值,如以下示例所示
$ curl localhost:8888/encrypt -s -d mysecret 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
如果您使用 curl 進行測試,請使用 --data-urlencode (而不是 -d ),並在要加密的值前面加上 = (curl 需要這樣做),或者設定明確的 Content-Type: text/plain 以確保當存在特殊字元('+' 特別棘手)時 curl 能正確編碼資料。 |
請確保不要將任何 curl 命令統計資訊包含在加密值中,這就是為什麼示例使用 -s 選項來靜默輸出。將值輸出到檔案有助於避免此問題。 |
逆向操作也透過 /decrypt
端點可用(前提是伺服器配置了對稱金鑰或完整的金鑰對),如以下示例所示
$ curl localhost:8888/decrypt -s -d 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda mysecret
獲取加密後的值,並在將其放入 YAML 或 properties 檔案中,以及提交併推送到遠端(可能不安全)儲存之前,加上 {cipher}
字首。
/encrypt
和 /decrypt
端點也都接受 /*/{application}/{profiles}
形式的路徑,當客戶端呼叫主環境資源時,這可用於按應用程式(名稱)和按配置檔案控制加密。
要以這種細粒度的方式控制加密,您還必須提供一個 @Bean ,型別為 TextEncryptorLocator ,它為每個名稱和配置檔案建立一個不同的加密器。預設提供的加密器不是這樣做的(所有加密都使用相同的金鑰)。 |
Spring 命令列客戶端(安裝了 Spring Cloud CLI 擴充套件)也可用於加密和解密,如以下示例所示
$ spring encrypt mysecret --key foo 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda $ spring decrypt --key foo 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda mysecret
要在檔案中使用金鑰(例如用於加密的 RSA 公鑰),在金鑰值前加上 "@" 並提供檔案路徑,如以下示例所示
$ spring encrypt mysecret --key @${HOME}/.ssh/id_rsa.pub AQAjPgt3eFZQXwt8tsHAVv/QHiY5sI2dRcR+...
--key 引數是強制性的(儘管帶有 -- 字首)。 |
解密錯誤
當配置伺服器無法解密某個值時,它將在 HTTP 響應中建立一個帶有 invalid
字首的屬性。
例如
{
"label": null,
"name": "application",
"profiles": [
"prd"
],
"propertySources": [
{
"name": "file:/demo/configserver/application-prd.yaml",
"source": {
"invalid.SharedPassword": "<n/a>"
}
},
{
"name": "file:/demo/configserver/application.yaml",
"source": {
"SharedPassword": "Fill_me_in"
}
}
],
"state": null,
"version": null
}
在上面的示例中,配置伺服器無法解密 application-prd.yaml
中 SharedPassword
的值,因此配置伺服器在屬性名稱前加上了 invalid
字首。
如果 Config Client 接收到此響應並將其新增到應用程式的 Environment
中,並且客戶端請求 SharedPassword
的值,它將獲得 Fill_me_in
。
如果您不希望配置伺服器對無法解密的屬性加上 invalid
字首,則可以將 spring.cloud.config.server.encrypt.prefix-invalid-properties
設定為 false
。如果您這樣做,來自配置伺服器的相同響應將如下所示
"label": null,
"name": "application",
"profiles": [
"prd"
],
"propertySources": [
{
"name": "file:/demo/configserver/application-prd.yaml",
"source": {
"SharedPassword": "AYBKlpcZpaR36OcRDQjNIQl6fmnddAQhetMw/uyTpnn5fDj+unJ9QOEbqiPc9fX0N+CC8i+EJiN6nlH9Xqu6sH1tX/P6zg1CIy+ct/1RWGNbmQ256jc6vQaXhiN8sA8Mr6QiqYnMoBd+Jni/Miir5G3a7G9MmjbEUASKJOhUlIFKqL1IqB81RBT/cv0bg9kAiy5VBF1WppxP/PwtjECzbeUi2Y1jbpYb98rnc/qmRO3ZJam9fDNcPpW09qGFhGgJIujca257F7G4guS2w/7haVzNoyRiwHzZ14oL8AIxHLMBSJJF19ULlsMAkROj9o9TnwhL9r4rX9sAWk28c5eq77+iVpmlT3yoRdZqvMqffzKiibDlzz95Gmms7V7mctxrhNVOOWTwMSJvk94Y9ZPenljKgPJIV3Z1cqqx+W8JxFFeelOuYvMEe4bOVBh1TepGzzdWVdYbylgXJy35uRTZ2drybUe5+jc0hiAuujHz0zdY1FwOHfwzSsSidlYn4syPeuytnxTzn7fbWXeXetTTtDlmLRf8MBSzXzDFWNH0cNGOCQ=="
}
},
{
"name": "file:/demo/configserver/application.yaml",
"source": {
"SharedPassword": "Fill_me_in"
}
}
],
"state": null,
"version": null
}
在這種情況下,如果 Config Client 接收到上述響應並從 Environment
請求 SharedPassword
的值,它將獲得加密後的值,而不是 Fill_me_in
。