首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

HttpClient 忽略 SSL 憑證呼叫 HTTPS:信任所有憑證的 X509TrustManager 實作

     編輯:Java 相關知識

開發測試環境快速繞過憑證驗證:自定義 TrustManager + SSLSocketFactory

生產環境**嚴禁**忽略憑證驗證(中間人攻擊風險)。但在開發、測試、內網自簽憑證環境,常需暫時關閉驗證。本文展示 Apache HttpClient 3.x/4.x 兩代實作:構建「信任所有」X509TrustManager → 注入 SSLContext → 建立 SSLSocketFactory → 註冊 Scheme("https")。

HttpClient 4.x(現代標準)完整範例

CloseableHttpClient createInsecureClient() throws KeyManagementException, NoSuchAlgorithmException {
    // 1. 信任所有憑證的 TrustManager
    TrustManager trustAll = new X509TrustManager() {
        public void checkClientTrusted(X509Certificate[] chain, String authType) {}
        public void checkServerTrusted(X509Certificate[] chain, String authType) {}
        public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
    };

    // 2. SSLContext 初始化
    SSLContext sslContext = SSLContext.getInstance("TLS"); // 推薦 TLS
    sslContext.init(null, new TrustManager[]{trustAll}, new SecureRandom());

    // 3. 允許所有主機名(生產請用 DefaultHostnameVerifier)
    HostnameVerifier allowAll = (hostname, session) -> true;

    // 4. 建立 HttpClient
    return HttpClients.custom()
            .setSSLContext(sslContext)
            .setSSLHostnameVerifier(allowAll)
            .build();
}

// 使用
try (CloseableHttpClient client = createInsecureClient()) {
    HttpPost post = new HttpPost("https://api.example.com/endpoint");
    post.setEntity(new StringEntity(jsonBody, ContentType.APPLICATION_JSON));
    try (CloseableHttpResponse resp = client.execute(post)) {
        String result = EntityUtils.toString(resp.getEntity());
        // 處理結果
    }
}

HttpClient 3.x(舊專案維護)關鍵片段


// 同樣構建 trustAll TrustManager 與 SSLContext
SSLSocketFactory sf = new SSLSocketFactory(sslContext);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

DefaultHttpClient client = new DefaultHttpClient();
client.getConnectionManager().getSchemeRegistry()
      .register(new Scheme("https", sf, 443));
// 後續 client.executeMethod(postMethod)...

雙向認證(雙向 SSL)擴展

若伺服器要求客戶端憑證:

KeyStore clientStore = KeyStore.getInstance("PKCS12");
clientStore.load(new FileInputStream("client.p12"), "password".toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(clientStore, "password".toCharArray());
sslContext.init(kmf.getKeyManagers(), new TrustManager[]{trustAll}, new SecureRandom());

安全警示與最佳實踐

風險說明對策
中間人攻擊 (MITM)攻擊者攔截流量、偽造憑證、竊取/篡改數據**僅限開發/測試/受控內網**;生產**必須**驗證憑證鏈與主機名
憑證釘選繞過App 釘選公鑰哈希防偽造,信任所有會失效測試環境暫時關閉釘選邏輯
合規違規GDPR、PCI-DSS 等要求傳輸加密完整性上線前代碼審查禁止 trustAll 進入主分支

優雅替代:信任特定自簽憑證

// 將自簽 CA 或伺服器憑證匯入 JDK cacerts 或自定義 TrustStore
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(new FileInputStream("my-truststore.jks"), "changeit".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
// 此方式保留完整驗證鏈,僅擴充信任錨點
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved