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