問題:在使用 org.apache.http.*下的 CloseableHttpClient 發送https請求時報了以上錯誤
解決方案一:使用java.net.HttpURLConnection
import java.net.HttpURLConnection; public static HttpURLConnection connectToWeb(String uri) { HttpURLConnection connection = null; try { URL url = new URL(uri); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.connect(); } catch (MalformedURLException ex) { ex.printStackTrace(); } catch (IOException ex) { ex.printStackTrace(); } return connection; }
解決方案二:在創建SSLConnectionSocketFactory時,添加NoopHostnameVerifier.INSTANCE參數
public static CloseableHttpClient createSSLClientDefault() { CloseableHttpClient client = null; try { SSLContext sslContext = null; sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() { @Override public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException { return true; } }).build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);//這里的紅色部分 client = HttpClients.custom().setSSLSocketFactory(sslsf).build(); } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) { e.printStackTrace(); } return client; }
原理擴展:
在org.apache.http.conn.ssl.SSLConnectionSocketFactory.verifyHostname方法中有如下代碼:
而NoopHostnameVerifier源代碼如下;verify方法直接返回true
/**
* The NO_OP HostnameVerifier essentially turns hostname verification
* off. This implementation is a no-op, and never throws the SSLException.
* 關閉主機名驗證,直接返回true
* @since 4.4
*/
@Contract(threading = ThreadingBehavior.IMMUTABLE) public class NoopHostnameVerifier implements HostnameVerifier { public static final NoopHostnameVerifier INSTANCE = new NoopHostnameVerifier(); @Override public boolean verify(final String s, final SSLSession sslSession) { return true; } @Override public final String toString() { return "NO_OP"; } }