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

问题描述 投票:61回答:18

我收到javax.net.ssl.SSLHandshakeException:当我尝试通过互联网进行Web服务的HTTPS发布时,握手异常期间远程主机关闭连接。但是相同的代码适用于其他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);
}

完整的堆栈跟踪:

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

实际上,这里有两种情况。当我作为一个独立的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
java ssl webservice-client
18个回答
59
投票

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

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

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


1
投票

在我的情况下,我遇到了这个问题,因为我已经给服务器一个不存在的证书,因为配置文件中有拼写错误。服务器没有抛出异常,而是像往常一样继续向客户端发送空证书。因此,可能需要检查以确保服务器提供正确的响应。

使用Jersey客户端连接到服务器时遇到此错误。我解决它的方法是调试库并看到它在尝试读取时确实收到了EOF。我也尝试使用网络浏览器进行连接并获得相同的结果。

只是写这个,以防它最终帮助任何人。


1
投票

您可以在当前的Java程序中将此代码写在下面

System.setProperty(“https.protocols”,“TLSv1.1”);

要么

System.setProperty(“http.proxyHost”,“proxy.com”); System.setProperty(“http.proxyPort”,“911”);


1
投票

我使用Java 8运行我的应用程序,Java 8将安全证书带到其信任存储区。然后我切换到Java 7并将以下内容添加到VM选项中:

-Djavax.net.ssl.trustStore=C:\<....>\java8\jre\lib\security\cacerts

我只是指出了证书所在的位置。


0
投票

我使用的是我在MacBook中使用Keychain导出的p12,然而,它在我的java-apns服务器代码上无效。我必须做的是使用我已经生成的pem键创建一个新的p12键,如here所述:

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

然后更新了新p12文件的路径,一切都运行良好。


0
投票

我有同样的错误,但在我的情况下,它是由Intellij IDE中的DEBUG模式引起的。调试减慢了库的速度,然后服务器在握手阶段结束了通信。标准的“RUN”工作得很好。


0
投票

我曾经遇到过同样的问题。我认为这是因为URL

String xmlServerURL =“https://example.com/soap/WsRouter”;

检查它是否合适?

javax.net.ssl.SSLHandshakeException是因为服务器无法连接到指定的URL,原因如下:

  • 要么未验证网站的身份。
  • 服务器的证书与URL不匹配。
  • 或者,服务器的证书不受信任。

0
投票

如何解决它是通过去

  1. 设置
  2. 搜索“网络”
  3. 选择“使用IDEA通用代理设置作为默认Subversion”

-1
投票

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


-3
投票

这就解决了我的问题。

如果您尝试使用调试器,请确保断点不在URL或URLConnection上,只需将断点放在BufferReader上或while循环中。

如果没有任何效果,请尝试使用apache库http://hc.apache.org/index.html

没有SSL,不需要JDK更新,甚至不需要设置属性,只需简单的技巧:)


21
投票

我遇到了同样的问题,我通过添加:

System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");

在openConnection方法之前。


15
投票

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

服务器确实正在关闭,这是一个SSL / TLS协议违规,虽然是一个相当小的;服务器可能无法与您握手的原因有很多,但它应首先发送致命警报,您的JSSE或weblogic等效应该指示。在这种情况下,如果您能够(并且允许)与知识渊博的服务器管理员进行通信,则服务器日志中可能会有一些有用的信息。或者您可以尝试在您的客户端计算机上安装网络监视器,或者一个足够近的网络监视器查看您的所有流量我个人喜欢www.wireshark.org。但这通常只表明关闭是在ClientHello之后立即出现的,而后者并未缩小范围。您没有说是否应该为此服务器配置“客户端证书”(实际上是密钥和证书,以Java privateKeyEntry的形式);如果服务器要求并且不正确,某些服务器可能会认为这是一种攻击并且通过关闭而故意违反协议,即使他们正式发送警报也是如此。

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

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


8
投票

诊断问题的第一步是启动客户端 - 如果您自己运行服务器,那么服务器的私有测试实例 - 通过使用VM选项启动Java:

-Djavax.net.debug=all

另见https://blogs.oracle.com/java-platform-group/entry/diagnosing_tls_ssl_and_https


7
投票

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

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

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

我的解决方案是安装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 8:http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html


7
投票

我想你错过了你的证书。

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

获得证书后,需要将其放在jdk home中的安全目录下,例如:

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

如果有效,请告诉我。


2
投票

我遇到了类似的问题,发现我遇到了错误的端口。修好港口后,事情很顺利。


1
投票

感谢大家分享您的答案和示例。同样的独立程序通过小的更改为我工作,并添加下面的代码行。

在这种情况下,密钥库文件由webservice提供者提供。

// 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");

1
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.