javax.net.ssl.SSLHandshakeException:Web 服务通信期间握手期间远程主机关闭连接

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21245796/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 07:37:55  来源:igfitidea点击:

javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake during web service communicaiton

javasslwebservice-client

提问by user3216923

I am getting javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshakeexception when I try to do HTTPS Post of a web service through internet. But same code works for other internet hosted web services. I tried many things, nothing is helping me. I posted my sample code here. Can anyone please help me to resolve this problem?

当我尝试通过互联网执行 Web 服务的 HTTPS 发布时,我收到javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshakeexception。但是相同的代码适用于其他 Internet 托管的 Web 服务。我尝试了很多东西,但没有任何帮助。我在这里发布了我的示例代码。任何人都可以帮我解决这个问题吗?

public static void main(String[] args) throws Exception {

    String xmlServerURL = "https://example.com/soap/WsRouter";
    URL urlXMLServer = new URL(xmlServerURL);
    // URLConnection supports HTTPS protocol only with JDK 1.4+ 
    Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(
            "xxxx.example.com", 8083));
    HttpURLConnection httpsURLConnection = (HttpURLConnection) urlXMLServer
            .openConnection(proxy);
    httpsURLConnection.setRequestProperty("Content-Type","text/xml; charset=utf-8");
    //httpsURLConnection.setDoInput(true);
    httpsURLConnection.setDoOutput(true);
    httpsURLConnection.setConnectTimeout(300000);
    //httpsURLConnection.setIgnoreProxy(false);
    httpsURLConnection.setRequestMethod("POST"); 
    //httpsURLConnection.setHostnameVerifier(DO_NOT_VERIFY); 
    // send request
    PrintWriter out = new PrintWriter(
            httpsURLConnection.getOutputStream());
    StringBuffer requestXML = new StringBuffer();
    requestXML.append(getProcessWorkOrderSOAPXML());   
    // get list of user     
    out.println(requestXML.toString()); 
    out.close();
    out.flush();
    System.out.println("XML Request POSTed to " + xmlServerURL + "\n");
    System.out.println(requestXML.toString() + "\n"); 
    //Thread.sleep(60000);  
    // read response

    BufferedReader in = new BufferedReader(new InputStreamReader( 
            httpsURLConnection.getInputStream()));
    String line;
    String respXML = "";
    while ((line = in.readLine()) != null) {
        respXML += line;
    }
    in.close();

    // output response
    respXML = URLDecoder.decode(respXML, "UTF-8"); 
    System.out.println("\nXML Response\n");
    System.out.println(respXML);
}

Full stacktrace:

完整的堆栈跟踪:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
       at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:946)
       at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
       at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339)
       at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323)
       at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
       at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
       at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1091)
       at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:250)
       at com.labcorp.efone.vendor.TestATTConnectivity.main(TestATTConnectivity.java:43)
Caused by: java.io.EOFException: SSL peer shut down incorrectly
       at sun.security.ssl.InputRecord.read(InputRecord.java:482)
       at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927)
       ... 8 more

Actually, there are two scenarios here. When I work as a standalone Java program I am getting the above exception. But when I try to execute in weblogic application server, I am getting the below exception: Any clue what could be the reason?

实际上,这里有两种情况。当我作为独立 Java 程序工作时,出现上述异常。但是当我尝试在 weblogic 应用程序服务器中执行时,我收到以下异常:任何线索可能是什么原因?

java.io.IOException: Connection closed, EOF detected
    at weblogic.socket.JSSEFilterImpl.handleUnwrapResults(JSSEFilterImpl.java:637)
    at weblogic.socket.JSSEFilterImpl.unwrapAndHandleResults(JSSEFilterImpl.java:515)
    at weblogic.socket.JSSEFilterImpl.doHandshake(JSSEFilterImpl.java:96)
    at weblogic.socket.JSSEFilterImpl.doHandshake(JSSEFilterImpl.java:75)
    at weblogic.socket.JSSEFilterImpl.write(JSSEFilterImpl.java:448)
    at weblogic.socket.JSSESocket$JSSEOutputStream.write(JSSESocket.java:93)
    at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
    at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
    at java.io.FilterOutputStream.flush(FilterOutputStream.java:140)
    at weblogic.net.http.HttpURLConnection.writeRequests(HttpURLConnection.java:192)
    at weblogic.net.http.HttpURLConnection.getInputStream(HttpURLConnection.java:433)
    at weblogic.net.http.SOAPHttpsURLConnection.getInputStream(SOAPHttpsURLConnection.java:37)
    at com.labcorp.efone.service.impl.WorkOrderServiceImpl.processATTWorkOrder(ATTWorkOrderServiceImpl.java:86)
    at com.labcorp.efone.bds.WorkOrderBusinessDelegateImpl.processATTWorkOrder(WorkOrderBusinessDelegateImpl.java:59)
    at com.labcorp.efone.actions.ATTWorkOrderAction.efonePerformForward(ATTWorkOrderAction.java:41)
    at com.labcorp.efone.actions.EfoneAction.efonePerformActionForward(EfoneAction.java:149)
    at com.labcorp.efone.actions.EfoneAction.execute(EfoneAction.java:225)
    at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
    at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
    at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
    at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:751)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:844)
    at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:280)
    at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:254)
    at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:136)
    at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:341)
    at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:25)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at com.labcorp.efone.security.EfoneAuthenticationFilter.doFilter(EfoneAuthenticationFilter.java:115)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
    at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3367)
    at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3333)
    at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
    at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)
    at weblogic.servlet.provider.WlsSubjectHandle.run(WlsSubjectHandle.java:57)
    at weblogic.servlet.internal.WebAppServletContext.doSecuredExecute(WebAppServletContext.java:2220)
    at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2146)
    at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2124)
    at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1564)
    at weblogic.servlet.provider.ContainerSupportProviderImpl$WlsRequestExecutor.run(ContainerSupportProviderImpl.java:254)
    at weblogic.work.ExecuteThread.execute(ExecuteThread.java:295)
    at weblogic.work.ExecuteThread.run(ExecuteThread.java:254)
Exception: java.io.IOException: Connection closed, EOF detected

回答by Federico Piazza

I think you are missing your certificates.

我认为您缺少证书。

You can try generating them by using InstallCerts app. Here you can see how to use it: https://github.com/escline/InstallCert

您可以尝试使用 InstallCerts 应用程序生成它们。在这里你可以看到如何使用它:https: //github.com/escline/InstallCert

Once you get your certificate, you need to put it under your security directory within your jdk home, for example:

拿到证书后,需要将其放在jdk home下的security目录下,例如:

C:\Program Files\Java\jdk1.6.0_45\jre\lib\security

Let me know if it works.

让我知道它是否有效。

回答by dave_thompson_085

Not an answer yet, but too much for a comment. This is clearly not a server cert problem; the symptoms of that are quite different. From your system's POV, the server appears to be closing during the handshake. There are two possibilities:

还没有答案,但评论太多了。这显然不是服务器证书问题;症状是完全不同的。从您系统的 POV 来看,服务器似乎在握手期间正在关闭。有两种可能:

The server really is closing, which is a SSL/TLS protocol violation though a fairly minor one; there are quite a few reasons a server might fail to handshake with you but it should send a fatal alert first, which your JSSE or the weblogic equivalent should indicate. In this case there may well be some useful information in the server log, if you are able (and permitted) to communicate with knowledgeable server admin(s). Or you can try putting a network monitor on your client machine, or one close enough it sees all your traffic; personally I like www.wireshark.org. But this usually shows only that the close came immediately after the ClientHello, which doesn't narrow it down much. You don't say if you are supposed to and have configured a "client cert" (actually key&cert, in the form of a Java privateKeyEntry) for this server; if that is required by the server and not correct, some servers mayperceive that as an attack and knowingly violate protocol by closing even though officially they should send an alert.

服务器真的要关闭了,虽然这是一个很小的问题,但它违反了 SSL/TLS 协议;服务器无法与您握手的原因有很多,但它应该首先发送一个致命警报,您的 JSSE 或 weblogic 等效项应该指出。在这种情况下,如果您能够(并被允许)与知识渊博的服务器管理员进行通信,那么服务器日志中可能会有一些有用的信息。或者您可以尝试在您的客户端机器上放置一个网络监视器,或者一个足够近的它可以看到您的所有流量;我个人喜欢 www.wireshark.org。但这通常仅表明关闭在 ClientHello 之后立即发生,这并没有缩小多少范围。你没有说你是否应该为这个服务器配置一个“客户端证书”(实际上是 key&cert,以 Java privateKeyEntry 的形式);可能会将其视为攻击并故意通过关闭来违反协议,即使他们应该正式发送警报。

Or, some middlebox in the network, most often a firewall or purportedly-transparent proxy, is deciding it doesn't like your connection and forcing a close. The Proxy you use is an obvious suspect; when you say the "same code" works to other hosts, confirm if you mean through the sameproxy (not just a proxy) and using HTTPS (not clear HTTP). If that isn't so, try testing to other hosts with HTTPS through the proxy (you needn't send a full SOAP request, just a GET / if enough). If you can, try connecting without the proxy, or possibly a different proxy, and connecting HTTP (not S) through the proxy to the host (if both support clear) and see if those work.

或者,网络中的某些中间件,通常是防火墙或据称是透明的代理,决定它不喜欢您的连接并强制关闭。您使用的代理是一个明显的嫌疑人;当您说“相同的代码”适用于其他主机时,请确认您的意思是通过相同的代理(不仅仅是代理)并使用 HTTPS(不明确的 HTTP)。如果不是这样,请尝试通过代理使用 HTTPS 测试其他主机(您无需发送完整的 SOAP 请求,只需发送 GET / 如果足够)。如果可以,请尝试在不使用代理或可能使用不同代理的情况下进行连接,并通过代理将 HTTP(而不是 S)连接到主机(如果两者都支持清除)并查看这些是否有效。

If you don't mind publishing the actual host (but definitely not any authentication credentials) others can try it. Or you can go to www.ssllabs.com and request they test the server (without publishing the results); this will try several common variations on SSL/TLS connection and report any errors it sees, as well as any security weaknesses.

如果您不介意发布实际主机(但绝对不是任何身份验证凭据),其他人可以尝试。或者您可以访问 www.ssllabs.com 并要求他们测试服务器(不发布结果);这将尝试 SSL/TLS 连接的几种常见变体,并报告它看到的任何错误以及任何安全漏洞。

回答by user3225313

I ran into a similar issue and found I was hitting the wrong port. After fixing the port things worked great.

我遇到了类似的问题,发现我打错了端口。修复端口后,一切都很好。

回答by user671646

Adding certificates to Java\jdk\jre\lib\security folder worked for me. If you are using Chrome click on the green bulb [https://support.google.com/chrome/answer/95617?p=ui_security_indicator&rd=1]and save the certificate in security folder.

将证书添加到 Java\jdk\jre\lib\security 文件夹对我有用。如果您使用的是 Chrome,请单击绿色灯泡 [ https://support.google.com/chrome/answer/95617?p=ui_security_indicator&rd=1]并将证书保存在安全文件夹中。

回答by Laxman

Thanks to all for sharing your answers and examples. The same standalone program worked for me by small changes and adding the lines of code below.

感谢所有人分享您的答案和示例。相同的独立程序通过小的更改和添加下面的代码行对我有用。

In this case, keystore file was given by webservice provider.

在这种情况下,密钥库文件由网络服务提供商提供。

// Small changes during connection initiation.. 

// Please add this static block 

      static {

        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier()

            {   @Override

        public boolean verify(String hostname, SSLSession arg1) {

        // TODO Auto-generated method stub

                if (hostname.equals("X.X.X.X")) {

                    System.out.println("Return TRUE"+hostname);

                    return true;

                }

                System.out.println("Return FALSE");

                return false;

              }
               });
         }


String xmlServerURL = "https://X.X.X.X:8080/services/EndpointPort";


URL urlXMLServer = new URL(null,xmlServerURL,new sun.net.www.protocol.https.Handler());


HttpsURLConnection httpsURLConnection = (HttpsURLConnection) urlXMLServer               .openConnection();

// Below extra lines are added to the same program

//Keystore file 

 System.setProperty("javax.net.ssl.keyStore", "Drive:/FullPath/keystorefile.store");

 System.setProperty("javax.net.ssl.keyStorePassword", "Password"); // Password given by vendor

//TrustStore file

System.setProperty("javax.net.ssl.trustStore"Drive:/FullPath/keystorefile.store");

System.setProperty("javax.net.ssl.trustStorePassword", "Password");

回答by matt forsythe

I encountered this problem with Java 1.6. Running under Java 1.7 fixed my particular rendition of the problem. I think the underlying cause was that the server I was connecting to must have required stronger encryption than was available under 1.6.

我在 Java 1.6 中遇到了这个问题。在 Java 1.7 下运行修复了我对问题的特定再现。我认为根本原因是我连接到的服务器必须要求比 1.6 下可用的加密更强的加密。

回答by Cyberdelphos

I was using the p12 which I exported with Keychain in my MacBook, however, it didn't work on my java-apns server code. What I had to do was to create a new p12 key as stated here, using my already generated pem keys:

我在 MacBook 中使用了与钥匙串一起导出的 p12,但是,它在我的 java-apns 服务器代码上不起作用。我所要做的就是创建一个新的P12密钥说在这里,用我已经生成的PEM键:

openssl pkcs12 -export -in your_app.pem -inkey your_key.pem -out your_app_key.p12

Then updated the path to that new p12 file and everything worked perfectly.

然后更新该新 p12 文件的路径,一切正常。

回答by McIntosh

I encountered a similar problem with glassfish application server and Oracle JDK/JRE but not in Open JDK/JRE.

我在 glassfish 应用程序服务器和 Oracle JDK/JRE 中遇到了类似的问题,但在 Open JDK/JRE 中没有。

When connecting to a SSL domain I always ran into:

连接到 SSL 域时,我总是遇到:

javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
...
Caused by: java.io.EOFException: SSL peer shut down incorrectly

The solution for me was to install the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Filesbecause the server only understood certificates that are not included in Oracle JDK by default, only OpenJDK includes them. After installing everything worked like charme.

我的解决方案是安装Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files,因为服务器仅理解默认情况下未包含在 Oracle JDK 中的证书,只有 OpenJDK 包含它们。安装后一切都像魅力一样工作。



JCE 7: http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html

JCE 7:http: //www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html

JCE 8: http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

JCE 8:http: //www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

回答by Bechyňák Petr

I had the same error, but in my case it was caused by the DEBUG mode in Intellij IDE. The debug slowed down the library and then server ended communication at handshake phase. The standard "RUN" worked perfectly.

我有同样的错误,但就我而言,它是由 Intellij IDE 中的调试模式引起的。调试减慢了库的速度,然后服务器在握手阶段结束了通信。标准的“RUN”完美运行。

回答by Erica Kane

Java 7 defaults to TLS 1.0, which can cause this error when that protocol is not accepted. I ran into this problem with a Tomcat application and a server that would not accept TLS 1.0 connections any longer. I added

Java 7 默认为 TLS 1.0,当该协议不被接受时可能会导致此错误。我在使用 Tomcat 应用程序和不再接受 TLS 1.0 连接的服务器时遇到了这个问题。我加了

-Dhttps.protocols=TLSv1.1,TLSv1.2

to the Java options and that fixed it. (Tomcat was running Java 7.)

到 Java 选项并修复它。(Tomcat 运行的是 Java 7。)