背景
微服務之間存在調用關系,且部署為 SSL 協議時,Feignt 請求報異常:
Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
這個異常是怎么產生的,解決辦法是什么呢?利用 DeepSeek 回憶一下這個問題。輸入問題:
FeignClient發送 https 請求時的 SSL 驗證原理是什么呢
FeignClient在發送HTTPS請求時,其SSL驗證原理主要涉及SSL/TLS協議的握手過程、證書驗證機制以及如何處理自定義的SSL配置,以下是詳細的原理說明。
1. SSL/TLS握手過程
當FeignClient發起HTTPS請求時,首先會與目標服務器進行SSL/TLS握手。握手過程包括以下幾個步驟:
- 客戶端發送支持的加密套件和壓縮方法:客戶端向服務器發送它支持的加密算法(如TLSv1.2)和壓縮方法。
- 服務器響應并選擇加密套件:服務器選擇一個加密套件并發送自己的數字證書。
- 證書驗證:客戶端驗證服務器的證書是否由受信任的證書頒發機構(CA)簽發。如果證書有效,則繼續握手。
- 生成共享密鑰:客戶端生成一個隨機數(premaster secret),并使用服務器的公鑰加密后發送給服務器。
- 服務器解密并生成會話密鑰:服務器使用自己的私鑰解密premaster secret,并生成會話密鑰,用于后續的加密通信。
- 加密通信:客戶端和服務器使用會話密鑰對數據進行加密和解密,確保數據傳輸的安全性。
2. 證書驗證機制
在SSL/TLS握手過程中,證書驗證是確保通信雙方身份真實性的關鍵步驟。FeignClient在發送HTTPS請求時,會根據配置的SSL上下文(SSLContext)和信任管理器(X509TrustManager)來驗證服務器的證書。
- 默認驗證:如果未配置自定義的SSL上下文,FeignClient會使用系統默認的SSL上下文,該上下文信任由Java自帶的CA簽發的證書。如果目標服務器的證書是自簽名的或由不受信任的CA簽發的,驗證會失敗,導致連接中斷。
- 自定義驗證:通過配置自定義的SSL上下文和信任管理器,可以指定信任的證書或忽略證書驗證。例如,使用
X509TrustManager
信任所有證書,或者通過NoopHostnameVerifier
忽略主機名驗證。
3. FeignClient的SSL配置
在Spring Cloud項目中,FeignClient的SSL配置通常通過以下方式實現:
- 使用
@FeignClient
注解:在Feign客戶端接口中指定URL為HTTPS地址,例如:
@FeignClient(name = "cloud-paltform", url = "https://xxx:9999")
- 配置SSL上下文:通過自定義的
Client
配置類,設置SSL上下文和信任管理器。例如:
@Configurationpublic class FeignHttpsConfig {@Beanpublic Client feignClient() {return new Client.Default(getSSLSocketFactory(), new NoopHostnameVerifier());}private SSLSocketFactory getSSLSocketFactory() throws Exception {SSLContext sslContext = SSLContext.getInstance("TLSv1.2");X509TrustManager tm = new X509TrustManager() {@Overridepublic void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {// 忽略客戶端證書驗證}@Overridepublic void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {// 忽略服務器證書驗證}@Overridepublic X509Certificate[] getAcceptedIssuers() {return new X509Certificate[0];}};sslContext.init(null, new TrustManager[]{tm}, new SecureRandom());return sslContext.getSocketFactory();}}
通過上述配置,FeignClient在發送HTTPS請求時會忽略SSL證書驗證,從而繞過證書信任問題。
- Spring Boot配置:在
application.yml
或application.properties
中配置SSL相關參數,例如:
feign:httpclient:disable-ssl-validation: true
4. 繞過SSL驗證的注意事項
雖然繞過SSL驗證可以解決證書信任問題,但需要注意以下幾點:
- 安全性風險:忽略SSL驗證會導致中間人攻擊(MITM)的風險,攻擊者可以攔截和修改通信內容,因此僅在測試環境中使用。
- 證書管理:如果使用自簽名證書,需要將其添加到信任庫中,否則客戶端無法驗證證書的有效性。
- 依賴管理:確保項目中引入了正確的依賴,例如
feign-httpclient
,以便使用HttpClient的SSL配置。
5. 總結
FeignClient在發送HTTPS請求時,通過SSL/TLS協議進行加密通信,并通過證書驗證確保服務器身份的真實性。
默認情況下,FeignClient會使用系統默認的SSL上下文,但可以通過自定義配置繞過SSL驗證。
在實際應用中,建議使用受信任的CA簽發的證書,并正確配置SSL上下文以確保通信的安全性。
解決辦法:
- 通過配置
feign.httpclient.disable-ssl-validation: true
禁用 SSL 校驗 。測試了,不生效。需要跟源碼看看具體生效配置是什么。 - 基于 spring-cloud-loadbalancer 的 Feign 客戶端配置禁用 SSL 校驗
結論:最好還是應該通過配置來控制,方法二需要添加一個條件。