使用 Apache HttpClient 訪問 HTTPS 資源時,若目標伺服器使用自簽名憑證或憑證鏈不完整,會拋出 SSLHandshakeException: PKIX path building failed。開發/測試環境常需繞過驗證。
import javax.net.ssl.*;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import java.io.*;
import java.security.SecureRandom;
public class HttpsTrustAllExample {
public static void main(String[] args) throws Exception {
// 1. 建立信任所有憑證的 TrustManager
TrustManager[] trustAll = new TrustManager[]{
new X509TrustManager() {
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {}
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {}
public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[0]; }
}
};
// 2. 初始化 SSLContext
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, trustAll, new SecureRandom());
// 3. 允許所有主機名
HostnameVerifier allHostsValid = (hostname, session) -> true;
// 4. 建立 HttpClient
SSLConnectionSocketFactory sslFactory = new SSLConnectionSocketFactory(ctx, allHostsValid);
var httpClient = HttpClients.custom().setSSLSocketFactory(sslFactory).build();
// 5. 執行請求並下載圖片示例
String url = "https://pic2.zhimg.com/6f7c6805962dc58cc21d4df748f18125_xl.jpg";
HttpGet get = new HttpGet(url);
var response = httpClient.execute(get);
try (InputStream in = response.getEntity().getContent();
OutputStream out = new FileOutputStream("httpstest.jpg")) {
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) != -1) out.write(buf, 0, len);
}
System.out.println("下載完成");
}
}
true 忽略主機名驗證(防止 CN 不匹配報錯)。嚴禁在生產環境使用此方案! 這會導致中間人攻擊風險。正確做法:
keytool -import)。