使用CloseableHttpClient的不受支持的记录版本SSLv2Hello

我正在尝试进行https调用并收到以下错误:不支持的记录版本SSLv2Hello

任何人都可以说明我做错了什么? 谢谢你的帮助。

这是StackTrace:

     debug:不支持的记录版本SSLv2Hello javax.net.ssl.SSLException:Sun.security上sun.security.ssl.InputRecord.read(未知来源)sun.security.ssl.InputRecord.readV3Record(未知来源)的不受支持的记录版本SSLv2Hello .sl.SSLSocketImpl.readRecord(未知来源)at sun.security.ssl.SSLSocketImpl.performInitialHandshake(未知来源)sun.security.ssl.SSLSocketImpl.startHandshake(未知来源)at sun.security.ssl.SSLSocketImpl.startHandshake(未知来自org.apache.http的org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:275)org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:254)位于org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:318)的.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:123)org.apache.http.impl.execchain.MainClientExec.establishRoute (MainCl  ientExec.java:363)org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:219)org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)at org位于org.apache.http.impl.client的org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)上的.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:86) .internalHttpClient.doExecute(InternalHttpClient.java:184)atg.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)at httpcomponents.httpsTest.main(httpsTest.java:135) 

这是工作示例:

     import com.sun.net.ssl.internal.ssl.Provider;  import java.io.IOException;  import java.security.KeyManagementException;  import java.security.NoSuchAlgorithmException;  import java.security.SecureRandom;  import java.security.Security;  import java.security.cert.CertificateException;  import java.security.cert.X509Certificate;  import java.text.MessageFormat;  import java.util.ArrayList;  import java.util.List;  import java.util.Timer;  import java.util.TimerTask;  import java.util.concurrent.TimeUnit;  import javax.net.ssl.SSLContext;  import javax.net.ssl.SSLException;  import javax.net.ssl.SSLSession;  import javax.net.ssl.SSLSocket;  import javax.net.ssl.TrustManager;  import javax.net.ssl.X509TrustManager;  import org.apache.http.Header;  import org.apache.http.HttpHeaders;  import org.apache.http.client.config.RequestConfig;  import org.apache.http.client.methods.CloseableHttpResponse;  import org.apache.http.client.methods.HttpHead;  import org.apache.http.conn.socket.LayeredConnectionSocketFactory;  import org.apache.http.conn.ssl.SSLConnectionSocketFactory;  import org.apache.http.conn.ssl.SSLContexts;  import org.apache.http.conn.ssl.X509HostnameVerifier;  import org.apache.http.entity.ContentType;  import org.apache.http.impl.client.CloseableHttpClient;  import org.apache.http.impl.client.HttpClientBuilder;  import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;  import org.apache.http.protocol.BasicHttpContext;  import org.apache.http.protocol.HttpContext; 
字符串audioURL =“ https://mydata.com/webreports/audio.jsp?callID=338786512&authentication=98695279578B04166629C0 ”; RequestConfig requestConfig = null; requestConfig = RequestConfig .custom()。setConnectTimeout(5000).setConnectionRequestTimeout(5000).setSocketTimeout(5000).build(); PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = null; poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(); poolingHttpClientConnectionManager.setMaxTotal(5); CloseableHttpClient closeableHttpClient = null; HttpHead httpHead = new HttpHead(audioURL); 尝试{Provider sslProvider = new Provider(); if(Security.getProvider(sslProvider.getName())== null){Security.addProvider(sslProvider); } TrustManager [] trustAllCerts = new TrustManager [] {new X509TrustManager(){@ Override public X509Certificate [] getAcceptedIssuers(){return null; } @Override public void checkServerTrusted(X509Certificate [] certs,String authType)throws CertificateException {} @Override public void checkClientTrusted(X509Certificate [] certs,String authType)throws CertificateException {}}}; SSLContext sslContext = SSLContexts .custom()。useSSL()。build(); sslContext.init(null,trustAllCerts,new SecureRandom()); LayeredConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext); X509HostnameVerifier x509HostnameVerifier = new X509HostnameVerifier(){@ Override public void verify(String host,SSLSocket ssl)throws IOException {//什么都不做} @Override public void verify(字符串主机,X509Certificate cert)抛出SSLException {//什么都不做//做没有} @Override public void verify(String host,String [] cns,String [] subjectAlts)抛出SSLException {//什么都不做} @Override public boolean verify(String string,SSLSession ssls){return true; }}; closeableHttpClient = HttpClientBuilder .create()。setDefaultRequestConfig(requestConfig).setConnectionManager(poolingHttpClientConnectionManager).setSslcontext(sslContext).setHostnameVerifier(x509HostnameVerifier).setSSLSocketFactory(sslConnectionSocketFactory).build(); } catch(NoSuchAlgorithmException noSuchAlgorithmException){System.out.println(noSuchAlgorithmException.getMessage()); } catch(KeyManagementException keyManagementException){System.out.println(keyManagementException.getMessage()); } HttpContext httpContext = new BasicHttpContext(); CloseableHttpResponse closeableHttpResponse = null; try {if(closeableHttpClient!= null){closeableHttpResponse = closeableHttpClient.execute(httpHead,httpContext); if(closeableHttpResponse!= null){int statusCode = closeableHttpResponse.getStatusLine()。getStatusCode(); 的System.out.println(将String.valueOf(的StatusCode)); catch(IOException iOException){System.out.println(iOException.getMessage()); } finally {if(closeableHttpResponse!= null){try {closeableHttpResponse.close(); } catch(IOException iOException){System.out.println(iOException.getMessage()); if(closeableHttpClient!= null){try {closeableHttpClient.close(); } catch(IOException iOException){System.out.println(iOException.getMessage()); }}}

似乎问题是JDK8客户端无法使用默认Provider连接到SSL2服务器(SSLv2已被弃用很长时间)。 您必须强制服务器使用SSL3(或其他更安全的协议),或者您必须使用其他提供程序(BouncyCastle?)。 目前我们在SOAP webservice JDK8客户端和JDK6服务器上遇到了类似的问题。

http://en.wikipedia.org/wiki/Transport_Layer_Security#SSL_2.0

http://tools.ietf.org/html/rfc6176

看起来你正在连接到服务器,在这个时代,它仍然支持SSLv2。

尝试从启用的协议列表中删除SSlv2ClientHello ,但是您可以使用Apache HTTPClient执行此操作。

注意:自2004年以来,您不需要使用com.sun.net.ssl.internal.ssl.Provider ,因此您需要注意您的TrustManagerHostnameVerifier都是根本不安全的。 此外,不允许TrustManager.getAcceptedIssuers()返回null:请参阅Javadoc。

弄清楚了。 我绊倒鞋带的两个地方是:

    需要使用PoolingHttpClientConnectionManager注册https
    将TLSv1设置为SSLConnectionSocketFactory中唯一受支持的协议
 package httpcomponents; import java.io.IOException; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLException; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpHead; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.LayeredConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.SSLContexts; import org.apache.http.conn.ssl.TrustStrategy; import org.apache.http.conn.ssl.X509HostnameVerifier; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; /** * * @author mark.jones */ public class HttpTest3 { public static void main(String[] args) { CloseableHttpClient closeableHttpClient = null; CloseableHttpResponse closeableHttpResponse = null; try { HttpHead httpHead = null; TrustStrategy trustStrategy = null; SSLContext sslContext = null; X509HostnameVerifier x509HostnameVerifier = null; LayeredConnectionSocketFactory sslConnectionSocketFactory = null; Registry registry = null; PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = null; RequestConfig requestConfig = null; String audioURL = "https://ancientserver.com/webreports/audio.jsp?callID=338786512&authentication=98695279578B04166629C0AC0ABB49F0"; httpHead = new HttpHead(audioURL); trustStrategy = new TrustStrategy() { @Override public boolean isTrusted(X509Certificate[] xcs, String authType) throws CertificateException { return true; } }; sslContext = SSLContexts .custom() .useSSL() .loadTrustMaterial(null, trustStrategy) .setSecureRandom(new SecureRandom()) .build(); x509HostnameVerifier = new X509HostnameVerifier() { @Override public void verify(String host, SSLSocket ssl) throws IOException { //do nothing } @Override public void verify(String host, X509Certificate cert) throws SSLException { //do nothing //do nothing } @Override public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException { //do nothing } @Override public boolean verify(String string, SSLSession ssls) { return true; } }; //either one works //LayeredConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, new String[]{"TLSv1"}, null, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, new String[]{"TLSv1"}, null, x509HostnameVerifier); registry = RegistryBuilder.create() .register("http", PlainConnectionSocketFactory.getSocketFactory()) .register("https", sslConnectionSocketFactory) .build(); poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(registry); requestConfig = RequestConfig .custom() .setConnectTimeout(5000) //5 seconds .setConnectionRequestTimeout(5000) .setSocketTimeout(5000) .build(); closeableHttpClient = HttpClientBuilder .create() .setDefaultRequestConfig(requestConfig) .setSslcontext(sslContext) .setHostnameVerifier(x509HostnameVerifier) .setSSLSocketFactory(sslConnectionSocketFactory) .setConnectionManager(poolingHttpClientConnectionManager) .build(); if (closeableHttpClient != null) { closeableHttpResponse = closeableHttpClient.execute(httpHead); if (closeableHttpResponse != null) { int statusCode = closeableHttpResponse.getStatusLine().getStatusCode(); System.out.println(String.valueOf(statusCode)); System.out.println(closeableHttpResponse.getFirstHeader("Content-Type")); } } } catch (NoSuchAlgorithmException noSuchAlgorithmException) { System.out.println(noSuchAlgorithmException.getMessage()); } catch (KeyStoreException keyStoreException) { System.out.println(keyStoreException.getMessage()); } catch (KeyManagementException keyManagementException) { System.out.println(keyManagementException.getMessage()); } catch (IOException iOException) { System.out.println(iOException.getMessage()); } finally { if (closeableHttpResponse != null) { try { closeableHttpResponse.close(); } catch (IOException iOException) { System.out.println(iOException.getMessage()); } } if (closeableHttpClient != null) { try { closeableHttpClient.close(); } catch (IOException iOException) { System.out.println(iOException.getMessage()); } } } } }