相关文章推荐
听话的马克杯  ·  python ...·  8 月前    · 
拉风的领结  ·  api.weixin.qq.com:443 ...·  10 月前    · 
有胆有识的大蒜  ·  SpringBoot 报 No ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I need to make a request through a HTTPS protocol. I wrote the following code:

import java.net.HttpURLConnection;
import java.net.URL;
import org.junit.Test;
public class XMLHandlerTest {
    private static final String URL = "https://ancine.band.com.br/xml/pgrt1_dta_20150303.xml";
    @Test
    public void testRetrieveSchedule() {
        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(URL).openConnection();
            connection.setRequestMethod("HEAD");
            int responseCode = connection.getResponseCode();
            System.out.println(responseCode);
        } catch (Exception e) {
            e.printStackTrace();

I got this exception stacktrace with a java.io.EOFException:

javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:953)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1332)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1359)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1343)
    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.getInputStream(HttpURLConnection.java:1301)
    at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:468)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338)
    at br.com.onebr.onesocial.arte1.service.core.scheduler.Arte1XMLHandlerTest.testRetrieveSchedule(Arte1XMLHandlerTest.java:16)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
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:934)
    ... 32 more

I got successful response from https://google.com but this error from URL above (https://ancine.band.com.br/xml/pgrt1_dta_20150303.xml).

Using PHP, .NET and NodeJS that URL works fine.

Anyone has any idea why this happening?

Please run your client with -Djavax.net.debug=ssl,handshake and post the output in your question. – user207421 Mar 6, 2015 at 22:58

That is a problem of security protocol. I am using TLSv1 but the host accept only TLSv1.1 and TLSv1.2 then I changed the protocol in Java with the instruction below:

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

Apart from the accepted answer, other problems can cause the exception too. For me it was that the certificate was not trusted (i.e., self-signed cert and not in the trust store).

If the certificate file does not exists, or could not be loaded (e.g., typo in path) can---in certain circumstances---cause the same exception.

Add it to your truststore (to the OS-wide one, or define one when starting the JVM with -Djavax.net.ssl.trustStore=... and -Djavax.net.ssl.trustStorePassword=....) – D. Kovács Nov 17, 2016 at 12:40 are you 100% sure it is the same error? I find it hard to believe self-signed certificate would cause "SSL peer shut down incorrectly" error. – eis Sep 29, 2021 at 11:05 @eis I was surprised too. But this happened years ago, still with Java SE 8. Since then, there have been a lot of changes in TLS handling, so my answer may not be valid anymore. – D. Kovács Sep 30, 2021 at 16:02

As @Zigri2612 suggested, what worked for me was to add TLS https.protocols, but i had to do it with white spaces instead of comma separated values:

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

This error is generic of the security libraries and might happen in other cases. In case other people have this same error when sending emails with javax.mail to a smtp server. Then the code to force other protocol is setting a property like this:

prop.put("mail.smtp.ssl.protocols", "TLSv1.2");            
//And just in case probably you need to set these too
prop.put("mail.smtp.starttls.enable", true);    
prop.put("mail.smtp.ssl.trust", {YOURSERVERNAME});

I've encountered the same error message but the reason and solution are quite interesting:

my problem resolved by upgrading the openjdk from 8u40 to 8u191 or higher version 8u312,

the root cause is a kind of interoperability issue that seems the client and server are using different padding method or cipher parameter(e.g EC curve) for DH key exchange,

so if you run out of solutions, probably you may try upgrade your jdk(don't just upgrade to a major version, try to upgrade to a higher minor version first, please note my problem resolved by higher minor version for openjdk8uXXX but still failed with openjdk9)

you may refer to the whole troubleshooting process at(handshake section): https://lyhistory.github.io/docs/software/network/layer4_http_ssl_tls_setup.html

I had this same issue until I saw your comment & upgraded my Openjdk to the latest, everything got solved. Phew! quite some headache. – Tosin Onikute May 12 at 14:14

The accepted answer didn't work in my situation, not sure why. I switched from JRE1.7 to JRE1.8 and that resolved the issue automatically. JRE1.8 uses TLS1.2 by default

I was having the same issue, as everyone else I suppose.. adding the System.setProperties(....) didn't fix it for me.

So my email client is in a separate project uploaded to an artifactory. I'm importing this project into other projects as a gradle dependency. My problem was that I was using implementation in my build.gradle for javax.mail, which was causing issues downstream.
I changed this line from implementation to api and my downstream project started working and connecting again.

I had mutual SSL enabled on my Spring Boot app and my Jenkins pipeline was re-building the dockers, bringing the compose up and then running integration tests which failed every time with this error. I was able to test the running dockers without this SSL error every time in a standalone test on the same Jenkins machine. It turned out that server was not completely up when the tests started executing. Putting a sleep of few seconds in my bash script to allow Spring boot application to be up and running completely resolved the issue.

In my case i was making a request to a system that is using SSLV3. So i have added the following jvm option. And problem got resolved.

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

For me, setting -Dhttps.protocols="TLSv1,TLSv1.1,TLSv1.2" (or -Dhttps.protocols="TLSv1.2" for that matter) didn't work.

Since I was running the problematic code in a Docker container in an AWS K8S cluster, I found a similar solution in the [AWS Documentation][1] After setting this system property -Djdk.tls.client.protocols=TLSv1.2, the error was gone.

[UPDATE] After deploying this to production, I noticed the behaviour is intermittent: sometimes I emails were getting sent, sometimes they didn't. Whilst researching some more, I found that my client was using TLS 1.0 which the server didn't support (it only supported TLS 1.2) The verbose error messages I was getting is this:

javax.net.ssl|SEVERE|10|grpc-default-executor-0|2021-10-22 19:38:48.017 GMT|Logger.java:765|Fatal (HANDSHAKE_FAILURE): Couldn't kickstart handshaking

Finally, after multiple trials, I solved it using the answer from here: How to force JavaMailSenderImpl to use TLS1.2? [1]: https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/security-java-tls.html

For my Spring Boot API consuming app, this issue was caused by being connected to a VPN.

I tried various work arounds including the accepted answer (I called System.setProperty("https.protocols", "TLSv1.1") in my main function) but nothing worked.

I disconnected from the VPN and no longer got this error.

If using client certificates, it is also possible to trigger an error like this by having an expired, revoked or otherwise untrusted client certificate, particularly if it works for some clients and not for others and software is identical. For some reason Java does not bother checking its own end is somehow sane before complaining about the other end acting unexpectedly.

Almost any reason a TLS handshake could end unhappily in mid-exchange could be valid trigger for this kind of error.

Serverside (or general other-side) logs may you give more information about why the handshake was terminated.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.