apache httpclient 4.5.1仅对非ssl站点进行SSL连接,并失败

目前我在jdk / tomcat v6上使用httpclient 4.2.5,而且运行的很好。在尝试升级时,我在jdk / tomcat v8上移动到httpclient 4.5.1,现在得到的错误如下:

javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:992) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:394) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:353) at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:134) at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353) at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:388) at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236) at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184) at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88) at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) at com.temp.MyHttpClient.makeHttpRequest(MyHttpClient.java:275) ....... at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) Caused by: java.io.EOFException: SSL peer shut down incorrectly at sun.security.ssl.InputRecord.read(InputRecord.java:505) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973) ... 25 more 

要么

 java.lang.Exception: Unrecognized SSL message, plaintext connection? .... at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) Caused by: javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection? at sun.security.ssl.InputRecord.handleUnknownRecord(InputRecord.java:710) at sun.security.ssl.InputRecord.read(InputRecord.java:527) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:394) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:353) at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:134) at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353) at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:388) at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236) at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184) at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88) at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) 

 java.lang.Exception: Searching source item B00OFLNE1C threw an error: Connection reset ..... at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) Caused by: java.net.SocketException: Connection reset at java.net.SocketInputStream.read(SocketInputStream.java:209) at java.net.SocketInputStream.read(SocketInputStream.java:141) at sun.security.ssl.InputRecord.readFully(InputRecord.java:465) at sun.security.ssl.InputRecord.read(InputRecord.java:503) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:394) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:353) at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:134) at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353) at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:388) at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236) at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184) at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88) at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) ...... 

 java.lang.Exception: Connect to 189.219.54.22:10000 [/189.219.54.22] failed: Connection timed out: connect ... at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) Caused by: org.apache.http.conn.HttpHostConnectException: Connect to 189.219.54.22:10000 [/189.219.54.22] failed: Connection timed out: connect at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:151) at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353) at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:388) at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236) at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184) at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88) at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) ...... ... 4 more Caused by: java.net.ConnectException: Connection timed out: connect at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:589) at org.apache.http.conn.socket.PlainConnectionSocketFactory.connectSocket(PlainConnectionSocketFactory.java:74) at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:134) ... 19 more 

我search并发现第一个错误(SSL对等closures不正确)被指示为与2个jdks中的协议差异相关,但是使用“-Dhttps.protocols = TLSv1,SSLv3”没有帮助。 但我认为其余的错误是由于httpclient试图build立一个SSL连接到一个所谓的http网站(我给了它的url也只有http – 没有任何“https”任何地方)。

然后我试图使用一个自定义的socketConnectionRegistry,如

 ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory(); LayeredConnectionSocketFactory sslsf = SSLConnectionSocketFactory.getSocketFactory(); Registry<ConnectionSocketFactory> sockConnRegistry = RegistryBuilder.<ConnectionSocketFactory>create() .register("http", plainsf) .register("https", sslsf) .build(); 

并用它来build立一个池连接pipe理器,并使用它来build立一个自定义客户端,但错误依然存在。

有趣的是,它的老版本4.2.5在jdk / tomcat v6上运行良好,并且可以连接到这些站点而没有任何错误。 不知道我在哪里做错了..

任何帮助/指针将是伟大的。

谢谢。


更新:12-Jan

@ Oleg我还没有尝试上面给出的协议替代,但仍然试图获得新的httpclient 4.5.1连接到http本身的代理站点,这总是超时。 我创build了两个独立的eclipse项目,一个是HC 4.2.5(在jdk-6上),另一个是HC 4.5.1(在jdk-8上),发现老的HC可以很容易地连接到一个代理并且获得目标HTML,但更新的HC超时代理连接..此外,我发现如果我在HC 4.5上设置代理,同时build立客户端(即

 CloseableHttpClient httpClient = HttpClients.custom() .setRoutePlanner(routePlanner) ...... .setProxy(proxy) .build(); 

那么它连接完美,并带来了HTML,但是当我使用自定义的RoutePlanner并通过它设置代理,然后上述问题(超时)。 这是自定义路线计划:

 static class ProxyRoutePlanner implements HttpRoutePlanner { public HttpHost proxy = null; @Override public HttpRoute determineRoute(HttpHost target, HttpRequest request, HttpContext context) throws HttpException { if (null == proxy) return new HttpRoute(target); return new HttpRoute(target, null, proxy, "https".equalsIgnoreCase(target.getSchemeName())); } } 

并且在提出请求之前设置代理主机(在每个请求之前的不同代理,通过一组代理进行循环循环)。 它在这种情况下失败。

你能以任何错误的方式看到做什么? 谢谢。


更多更新:

其实,如果我设定了

 .setRoutePlanner(routePlanner) 

在构build自定义HC时,它会忽略通过.setProxy(…)或通过RequestConfig的任何代理集,因为routePlanner中没有设置代理(似乎有道理)。 因此它直接连接到目标并获取页面。 但是,如果我在routePlanner中设置代理,或者删除HCbuild设中的规划器,并通过reqConfig或.setProxy设置代理,它会尝试连接到代理,然后再次失败(超时)。

我在HC 4.2中设置代理如下:

 HttpHost proxy = new HttpHost(proxyHost, proxyPort, proxyProtocol); httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); 

我现在完全失去了..是否正确的方式来设置在HC 4.2代理? 如何validationHC 4.2是否使用代理设置如上,或者如何在4.5中正确设置代理?

除非有明确的指示,否则HttpClient不会将“https.protocols”属性(或其他任何其他的)

 CloseableHttpClient client = HttpClients.createSystem(); 

从版本4.5开始,HttpClient默认禁用SSLv3协议版本

但是可以使用自定义SSL连接工厂明确设置受支持的SSL协议版本

 SSLContext sslcontext = SSLContexts.createSystemDefault(); SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory( sslcontext, new String[] { "TLSv1", "SSLv3" }, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier()); Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create() .register("http", PlainConnectionSocketFactory.INSTANCE) .register("https", sslConnectionSocketFactory) .build(); PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry); CloseableHttpClient httpClient = HttpClients.custom() .setConnectionManager(cm) .build();