javax.net.ssl.SSLHandshakeException: Віддалений хост закрив з'єднання під час рукостискання під час спілкування веб-служби


77

Я отримую javax.net.ssl.SSLHandshakeException: Віддалений хост закрив підключення під час винятку рукостискання, коли я намагаюся зробити HTTPS Повідомлення веб-служби через Інтернет. Але той же код працює для інших веб-служб, розміщених в Інтернеті. Я багато чого пробував, мені ніщо не допомагає. Я розмістив тут свій зразок коду. Хто-небудь може допомогти мені вирішити цю проблему?

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

1
Чи можете ви опублікувати повний стек?
Хлопець із капелюхом

1
Ще однією з багатьох можливих причин може бути розрив або дуже низька якість з'єднання
comodoro

Що станеться, якщо ви використовуєте іншу програму для тестування своєї веб-служби, наприклад, curl або soap-ui? У мене схожа проблема, і вона працює з curl, але не з мого середовища виконання Java (servicemix). Я підозрюю, що це також може бути "cacert" клієнта, що не містить сертифікат сервера.
рюффп

Якщо хтось перейшов на цю сторінку через gradle, чого не вимагає OP, переконайтеся, що ви встановили для JAVA_HOME Java 8 або пізнішу версію.
Шрідхар Сарнобат

Відповіді:


71

За замовчуванням Java 7 має значення TLS 1.0, що може спричинити цю помилку, якщо цей протокол не приймається. Я зіткнувся з цією проблемою із програмою Tomcat та сервером, який більше не приймав підключення TLS 1.0. я додав

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

до опцій Java, і це виправило. (Tomcat використовував Java 7.)


2
Де я повинен додати цей рядок коду? всередині якого файлу? Не могли б ви сказати шлях до каталогу?
hamed

2
Це не код, це частина параметрів Java, які встановлюються, коли ви викликаєте виконуваний файл Java. Точна відповідь буде залежати від вашої операційної системи та програми. Для Tomcat у Windows, як у цьому прикладі, запуск Tomcat7w допоможе вам розпочати роботу, а потім змініть параметри Java. В інших випадках ви додаєте параметри до файлу ініціалізації або до командного рядка java.exe, додаючи його туди. Я б точно рекомендував дослідити варіанти Java, а не сліпо додавати це, якщо ви з ними не знайомі. Хорошим місцем для початку є docs.oracle.com/javase/7/docs/technotes/tools/windows/java.html .
Еріка Кейн,

1
@EricaKane - Приємно мати відповідь. Але як нам налагодити цю проблему та з’ясувати причину? (тобто як ми дійдемо до вашого рішення?)
MasterJoe

Якщо ви маєте справу з публічним веб-сайтом, ви можете використовувати SSL Labs або інший інструмент, щоб побачити, який протокол вони приймуть. Якщо вони більше не приймають TLS 1.0 (і, чесно кажучи, більшість не приймають), і ви використовуєте Java 7, вам потрібно буде це реалізувати. Щодо того, як я спеціально налагоджував це спочатку, я вже не пам’ятаю.
Еріка Кейн,

2
Здається, це все ще справедливо для Java 8 та Java Web Start того самого. Просто додано <property name="https.protocols" value="TLSv1.1,TLSv1.2"/>до файлу JNLP, щоб Web Start знову
запрацював

31

Я зіткнувся з тією ж проблемою і вирішив її, додавши:

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

раніше методом openConnection .


20

Ще не відповідь, але занадто багато для коментаря. Це явно не проблема сертифіката сервера; симптоми цього зовсім інші. З POV вашої системи сервер, здається, закривається під час рукостискання. Є дві можливості:

Сервер справді закривається, що є порушенням протоколу SSL / TLS, хоча досить незначним; Є досить багато причин, чому сервер може не вдатися з вами потиснути руки, але він повинен спочатку надіслати смертельне попередження, яке повинен вказати ваш JSSE або еквівалент weblogic. У цьому випадку в журналі сервера цілком може бути корисна інформація, якщо ви вмієте (і дозволяєте) спілкуватися зі знаючими адміністраторами сервера. Або ви можете спробувати встановити мережевий монітор на клієнтській машині, або досить близько, щоб він бачив весь ваш трафік; особисто мені подобається www.wireshark.org. Але це зазвичай показує лише те, що закриття відбулося відразу після ClientHello, що не сильно звужує його. Ви не говорите, чи повинні ви і налаштували "клієнтський сертифікат" (насправді ключ і сертифікат, у формі Java privateKeyEntry) для цього сервера;можуть сприймати це як атаку та свідомо порушувати протокол, закриваючи, хоча офіційно вони повинні надсилати попередження.

Або якийсь середній блок у мережі, найчастіше брандмауер або нібито прозорий проксі-сервер, вирішує, що вам не подобається ваше з’єднання, і змушує закрити. Проксі, який ви використовуєте, є очевидним підозрою; коли ви говорите, що "той самий код" працює для інших хостів, переконайтеся, що ви маєте на увазі той самий проксі (а не просто проксі) і використовуючи HTTPS (не чіткий HTTP). Якщо це не так, спробуйте протестувати на інших хостах за допомогою HTTPS через проксі (вам не потрібно надсилати повний запит SOAP, просто GET / якщо достатньо). Якщо ви можете, спробуйте підключитися без проксі-сервера або, можливо, іншого проксі-сервера, і підключіть HTTP (не S) через проксі-сервер до хосту (якщо обидва підтримують помилку) і перевірте, чи працюють вони.

Якщо ви не проти опублікувати фактичний хост (але точно не будь-які облікові дані для автентифікації), інші можуть спробувати. Або ви можете зайти на www.ssllabs.com і попросити їх перевірити сервер (без публікації результатів); це спробує кілька типових варіантів з'єднання SSL / TLS і повідомить про будь-які виявлені помилки, а також про будь-які слабкі місця в безпеці.



8

Я думаю, вам не вистачає ваших сертифікатів.

Ви можете спробувати створити їх за допомогою програми InstallCerts. Тут ви можете побачити, як ним користуватися: https://github.com/escline/InstallCert

Отримавши сертифікат, вам потрібно помістити його в каталог безпеки у вашому домі jdk, наприклад:

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

Повідомте мене, якщо це працює.


обидва посилання не працюють
kane

@kane я оновив посилання ... до речі, моя відповідь не намагається пояснити, як створювати сертифікати, а куди їх розміщувати. Я додав це посилання як контекстну інформацію на випадок, якщо ОП хоче глибше заглибитися в генерацію сертифіката.
Федеріко Пьяцца

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, оскільки сервер розумів лише сертифікати, які за замовчуванням не входять до 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


3

У моєму випадку я отримав цю проблему, оскільки надав серверу неіснуючий сертифікат через помилку у файлі конфігурації. Замість того, щоб видавати виняток, сервер діяв як звичайно і надіслав порожній сертифікат клієнту. Тож, можливо, варто перевірити, чи сервер надає правильну відповідь.

Я відчув цю помилку під час використання клієнта Джерсі для підключення до сервера. Я вирішив це шляхом налагодження бібліотеки та переконання, що вона справді отримала EOF у той момент, коли вона намагалася прочитати. Я також спробував підключитися за допомогою веб-браузера і отримав ті самі результати.

Просто напишіть це тут на випадок, якщо це допоможе комусь.


2

Я зіткнувся з подібною проблемою і виявив, що потрапив не в той порт. Після виправлення порту справи спрацювали чудово.


1

Дякуємо усім, що поділились своїми відповідями та прикладами. Ця сама автономна програма працювала для мене невеликими змінами та додаванням рядків коду нижче.

У цьому випадку файл зберігання ключів надано постачальником веб-послуг.

// 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.


1

У мене була та сама помилка, але в моєму випадку це було викликано режимом DEBUG в Intellij IDE. Налагодження уповільнило роботу бібліотеки, а потім сервер закінчив зв'язок на етапі рукостискання. Стандартний "RUN" спрацював чудово.


1

Я запускаю свою програму з Java 8, і Java 8 принесла сертифікат безпеки у свій довірчий магазин. Потім я перейшов на Java 7 і додав у параметри віртуальної машини наступне:

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

Просто я вказав на місце, де знаходиться сертифікат.


1

Ви можете написати цей код нижче в поточній програмі Java

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

або

System.setProperty("http.proxyHost", "proxy.com");

System.setProperty("http.proxyPort", "911");


0

Я використовував p12, який я експортував із брелоком у своєму MacBook, однак він не працював на моєму коді сервера java-apns. Що мені потрібно було зробити, це створити новий ключ p12, як зазначено тут , використовуючи мої вже створені ключі pem:

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

Потім оновив шлях до цього нового файлу p12, і все працювало чудово.


0

Як би ви це вирішили, перейшовши до

  1. Налаштування

  2. Шукати "Мережа"

  3. Виберіть "Використовувати загальні налаштування проксі-сервера IDEA як субверсію за замовчуванням"



0

З базою на TLSv1.2 ALERT: fatal, handshake_failure, яку я отримав після налагодження за допомогою цього потоку, попередня відповідь

-Djavax.net.debug = все

Я зайшов на https://www.ssllabs.com/ і помітив, що веб-сервер вимагав припинення з’єднання SSLv3 у червні 2015 року та припинення дії у примітках до випуску JDKu31

ssllabs результати

Я відредагував $ {java_home} /jre/lib/security/java.security на рядку

jdk.tls.disabledAlgorithms = SSLv3, RC4, DES, MD5withRSA, DH keySize <1024,
EC keySize <224, 3DES_EDE_CBC, anon, NULL

до

jdk.tls.disabledAlgorithms = RC4, DES, MD5withRSA, DH keySize <1024,
EC keySize <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]

Я виправив це встановлення сертифіката за допомогою інструментарію java, після цієї відповіді не вдалося побудувати шлях до PKIX ”і“ не вдалося знайти дійсний шлях сертифікації до запитуваної цілі ”



-2

Я зіткнувся з тим самим питанням одного разу. Я думаю, що це через URL-адресу

Рядок xmlServerURL = " https://example.com/soap/WsRouter ";

Перевірте, чи він належний чи ні ??

javax.net.ssl.SSLHandshakeException тому, що сервер не може підключитися до вказаної URL-адреси з наступних причин -

  • Або особистість веб-сайту не підтверджена.
  • Сертифікат сервера не відповідає URL-адресі.
  • Або сертифікат сервера не є надійним.

Це SSLHandshakeException не спричинено жодною з цих речей.
user207421

-4

Це те, що вирішує мою проблему.

Якщо ви намагаєтеся використовувати налагоджувач, переконайтеся, що точки зупинку немає на URL-адресі або URLConnection, просто поставте свою точку зупинки на BufferReader або всередині циклу while.

Якщо нічого не працює, спробуйте скористатися бібліотекою apache http://hc.apache.org/index.html .

не потрібно SSL, не потрібно оновлення JDK, не потрібно навіть встановлювати властивості, просто простий фокус :)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.