问题:在使用 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"; } }