搶先一步
VMware 提供培訓和認證,以加速您的進程。
了解更多安全通訊端層 (SSL) 和傳輸層安全性 (TLS) 是確保分層或面向服務架構中系統之間通訊的關鍵組件。 這種架構中的 Spring Boot 應用程式通常會接受傳入的網路連線或建立傳出的連線,而開發人員的任務是設定應用程式以在這種安全的環境中運作。
如果您曾經使用過 Java 安全性與 SSL API,您可能知道這不是一項特別有趣的任務。 它通常需要多次造訪 stackoverflow.com 來複製和貼上程式碼。 有幾個因素使得使用 SSL 令人痛苦。
首先,您可能會獲得用於生產環境的金鑰材料,例如憑證和私密金鑰。 您可能需要為預生產測試產生不同的金鑰材料(通常使用自我簽署憑證授權單位)。 這些金鑰材料通常採用 Java 金鑰庫檔案的形式,格式為 JKS 或 PKCS #12,或者可能是 PEM 編碼的文字檔。 這些檔案類型中的每一種都需要不同的處理方式。
取得金鑰材料後,您需要將其轉換為可以傳遞給 Java 連線 API 的東西。 由於連線 API 可以透過多種方式進行設定,因此這裡可能會變得困難
java.security.KeyStore
實例。javax.net.ssl.KeyManager
和 javax.net.ssl.TrustManager
實例。javax.net.ssl.SSLContext
實例。SSL 的層級也相當低,因此您通常需要剝除幾層抽象才能找到需要使用來自 java.security
或 java.net.ssl
套件的物件進行設定的東西。 例如,如果您想在 Spring RestTemplate
上設定 SSL,您需要深入了解支援它的 ClientHttpRequestFactory
。 對於典型的 Spring Boot 應用程式,這可能是 HttpComponentsClientHttpRequestFactory
、OkHttp3ClientHttpRequestFactory
或 SimpleClientHttpRequestFactory
。 這些都提供不同的設定 API。
使用 SSL 或 TLS 設定連線對於 Spring Boot 來說並不陌生,但團隊決定全面檢視目前支援的內容,並尋找改進和擴展支援的機會。 我們希望您會發現 Spring Boot 3.1 使 SSL 設定變得更加容易。
Spring Boot 3.1 引入了 SSL 套件的概念,用於設定和使用自訂 SSL 金鑰材料,例如金鑰庫、憑證和私密金鑰。 設定完成後,可以使用設定屬性或 API 將套件套用到一個或多個連線。
用於設定 SSL 金鑰材料的屬性位於 application.yaml
或 application.properties
檔案中的 spring.ssl.bundle
前置詞下。 有兩個頂層群組可用於反映設定不同類型金鑰材料所需的唯一資訊。
spring.ssl.bundle.jks
可用於使用 Java 金鑰庫檔案設定套件。spring.ssl.bundle.pem
可用於使用 PEM 編碼的文字檔設定套件。可以設定每個類型的一個或多個套件,並且為每個設定的套件提供使用者提供的名稱。 在使用屬性套用套件或使用 API 檢索套件時,會使用該名稱。
以下範例 application.yaml
檔案顯示了兩個 SSL 套件的設定。 第一個名為 server
,並定義了一個 Java 金鑰庫檔案(採用 PKCS #12 格式),可用於保護嵌入式 Web 伺服器。 第二個名為 client
,並定義了一個信任庫,其中包含 PEM 編碼的憑證檔案,可用於保護需要用戶端驗證的伺服器的連線用戶端。
spring:
ssl:
bundle:
jks:
server:
key:
alias: "server"
keystore:
location: "classpath:server.p12"
password: "secret"
type: "PKCS12"
pem:
client:
truststore:
certificate: "classpath:client.crt"
有關可用設定屬性的更多詳細資訊,請參閱 Spring Boot 參考文件 以及 JksSslBundleProperties 和 PemSslBundleProperties 類別。
Spring Boot 使用 spring.ssl.bundle
屬性來建立提供對指定金鑰材料存取的物件。
如上所述,Java 安全性和 SSL API 提供了三個抽象層級來公開從 Java 金鑰庫或 PEM 檔案讀取的金鑰材料
java.security.KeyStore
實例。javax.net.ssl.KeyManager
和 javax.net.ssl.TrustManager
實例。javax.net.ssl.SSLContext
實例。在最低層級,您可能需要信任庫和金鑰庫物件才能將 SSL 應用於連線。 這些可以使用 SslStoreBundle
介面進行存取,如下所示
public interface SslStoreBundle {
KeyStore getKeyStore();
String getKeyStorePassword();
KeyStore getTrustStore();
}
KeyManager
和 TrustManager
實例可以從金鑰庫和信任庫中衍生。 這些可以使用 SslManagerBundle
介面進行存取
public interface SslManagerBundle {
KeyManager[] getKeyManagers();
KeyManagerFactory getKeyManagerFactory();
TrustManager[] getTrustManagers();
TrustManagerFactory getTrustManagerFactory();
}
最後,可以從 KeyManager
和 TrustManager
建立 SSLContext
,並使用 createSslContext
工廠方法進行存取。
將所有這些放在一起,我們有一個 SslBundle
介面,可以存取各種不同的設定樣式
public interface SslBundle {
SslStoreBundle getStores();
SslManagerBundle getManagers();
SSLContext createSslContext() {
}
有關 SslBundle
中方法的完整清單,請參閱 原始程式碼。
已設定的 SslBundle
集合在 SslBundles
Bean 中提供,可以自動連線到其他 Spring Bean
public interface SslBundles {
SslBundle getBundle(String bundleName) throws NoSuchSslBundleException;
}
使用 SslBundles
檢索和套用 SSLContext
的範例可能如下所示
@Component
public class MyComponent {
public MyComponent(SslBundles sslBundles) {
SslBundle sslBundle = sslBundles.getBundle("client");
SSLContext sslContext = sslBundle.createSslContext();
// do something with the created sslContext
}
}
Spring Boot 3.1 中啟用的一個令人興奮的 SSL 功能新領域是 REST 用戶端的設定。 Spring Boot 支援自訂 RestTemplate
或 WebClient
現在包括套用 SSL 套件以保護用戶端和 REST 服務之間連線的能力。
RestTemplateBuilder
有一個新的 setSslBundle()
方法,該方法接受從自動設定的 SslBundles
檢索的 SSL 套件,如本範例所示
@Service
public class MyService {
private final RestTemplate restTemplate;
public MyService(RestTemplateBuilder restTemplateBuilder, SslBundles sslBundles) {
this.restTemplate = restTemplateBuilder.setSslBundle(sslBundles.getBundle("mybundle")).build();
}
}
WebClientSsl
介面允許檢索 SSL 套件並將其應用於 WebClient.Builder
,如本範例所示
@Service
public class MyService {
private final WebClient webClient;
public MyService(WebClient.Builder webClientBuilder, WebClientSsl ssl) {
this.webClient = webClientBuilder.baseUrl("https://example.org").apply(ssl.fromBundle("mybundle")).build();
}
}
Spring Boot 讓您能夠輕鬆地設定用於從應用程式連線到資料服務的用戶端程式庫。 這些用戶端程式庫是 API 的良好範例,這些 API 使用 Java 安全性和 SSL API 的三個層級中的任何一個進行設定。
在 3.1 之前,Spring Boot 提供自動設定的許多資料服務都可以使用某種形式的 SSL 設定。 但是,跨服務的支援層級和用於設定的屬性不一致。 大多數資料服務自動設定屬性現在都有類似的 ssl
結構,從而在服務之間提供更高的相容性
spring.cassandra.ssl
spring.couchbase.env.ssl
spring.elasticsearch.restclient.ssl
spring.data.mongodb.ssl
spring.data.redis.ssl
大多數服務都有 *.ssl.enabled
屬性,它會使用 Java 執行時環境 cacerts
中包含的信任材料,在客戶端函式庫中啟用 SSL 支援。 *.ssl.bundle
屬性會套用一個已命名的 SSL 組合,以使用組合中的自訂信任材料來啟用客戶端函式庫的 SSL 支援。 這使得配置更加一致,並允許將相同的信任材料應用於多個連線,從而減少屬性或 YAML 配置的數量。
為了提供這種程度的一致性,一些先前的 SSL 相關屬性已被棄用。 有關更多詳細資訊,請參閱組態屬性變更日誌。
JDBC 連線明顯從此列表中遺漏。 我們計劃在即將發布的 Spring Boot 版本中將 SSL 組合方法應用於 JDBC 連線。
Spring Boot 支援的所有嵌入式 Web 伺服器都可以使用 server.ssl.*
屬性配置,以保護傳入連線的安全。 自 Spring Boot 創建以來,就已支援 Java 金鑰儲存檔案,而自 2.7 以來,就已支援 PEM 編碼的檔案。
隨著時間的推移,server.ssl
字首下的屬性數量不斷增加,並且缺乏結構使得難以判斷哪些屬性可以一起使用,哪些屬性是互斥的。 先前的 server.ssl.*
屬性將繼續受到支援,但可以使用新的 server.ssl.bundle
屬性將配置的 SSL 組合應用於嵌入式 Web 伺服器。
以下兩個範例在功能上是相同的
server:
ssl:
key-alias: “server”
key-password: “keysecret”
key-store: "classpath:server.p12"
key-store-password: "storesecret"
client-auth: NEED
spring:
ssl:
bundle:
jks:
web-server:
key:
alias: "server"
password: “keysecret”
keystore:
location: "classpath:server.p12"
password: "storesecret"
server:
ssl:
bundle: “web-server”
client-auth: NEED
較舊的結構更簡潔,但較新的結構減少了錯誤配置的可能性,並允許在多個連線上使用相同的 SSL 組合。
對 management.server.ssl
和 spring.rsocket.server.ssl
屬性進行了類似的變更。
我們衷心希望您發現 SSL 組合是 Spring Boot 3.1 的有用功能。 如果您發現任何其他技術,認為我們應該新增 SSL 支援,請提出 GitHub issue,我們將在未來的版本中考慮它。