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

时间:2014-01-20 22:52:25

标签: java ssl webservice-client

我在 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

21 个答案:

答案 0 :(得分:59)

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

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

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

答案 1 :(得分:21)

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

解决了这个问题
System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");
openConnection 方法之前

答案 2 :(得分: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连接的几个常见变体,并报告它看到的任何错误,以及任何安全漏洞。

答案 3 :(得分:8)

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

-Djavax.net.debug=all

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

答案 4 :(得分: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

答案 5 :(得分:7)

我认为你错过了证书。

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

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

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

让我知道它是否有效。

答案 6 :(得分:2)

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

答案 7 :(得分:1)

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

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

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

答案 8 :(得分:1)

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

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

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

答案 9 :(得分:1)

你可以在下面的代码中写下你当前的java程序

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

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

答案 10 :(得分:1)

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

答案 11 :(得分:1)

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

在这种情况下,密钥库文件由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");

答案 12 :(得分:0)

我遇到了同样的错误,但在我的情况下,它是由Intellij IDE中的DEBUG模式引起的。调试减慢了库的速度,然后服务器在握手阶段结束了通信。标准的“运行”非常有效。

答案 13 :(得分:0)

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

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

检查它是否合适?

javax.net.ssl.SSLHandshakeException是因为服务器因以下原因而无法连接到指定的网址 -

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

答案 14 :(得分: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文件的路径,一切都运行良好。

答案 15 :(得分:0)

如何解决问题的方法是转到

  1. 设置

  2. 搜索 “网络”

  3. 选择“将IDEA常规代理设置用作默认Subversion”

答案 16 :(得分:0)

根据https://kb.informatica.com/solution/23/Pages/69/570664.aspx添加此属性有效

CryptoProtocolVersion = TLSv1.2

答案 17 :(得分:0)

使用TLSv1.2 ALERT: fatal, handshake_failure线程调试后获得的基数为previos answer

-Djavax.net.debug = all

我去了https://www.ssllabs.com/,发现该Web服务器要求SSLv3连接于2015年6月弃用,而JDKu31 Release notes

弃用

ssllabs results

我在一行中编辑了$ {java_home} /jre/lib/security/java.security

jdk.tls.disabledAlgorithms = SSLv3,RC4,DES,MD5和RSA,DH密钥大小<1024,
EC keySize <224,3DES_EDE_CBC,anon,NULL

jdk.tls.disabledAlgorithms = RC4,DES,带有RSA的MD5,DH密钥大小<1024,
EC键大小<224,3DES_EDE_CBC,anon,NULL

最后一步,我得到了这个错误

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target [javax.net.ssl.SSLHandshakeException]

我按照此答案PKIX path building failed” and “unable to find valid certification path to requested target”

修复了使用java keytool安装证书的问题

答案 18 :(得分:0)

我在指定 https url 并在同一个 url 中明确指定 http 端口(而不是 https 端口)时收到此错误。删除显式端口 :8080 为我解决了这个问题。

答案 19 :(得分:-1)

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

答案 20 :(得分:-3)

这就解决了我的问题。

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

如果无效,请尝试使用apache库http://hc.apache.org/index.html

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