SSL 对等端在 Java 中错误关闭

SSL peer shut down incorrectly in Java

我需要通过 HTTPS 协议发出请求。我写了下面的代码:

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();
        }
    }

}

我用 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.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.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access[=12=]0(ParentRunner.java:53)
    at org.junit.runners.ParentRunner.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

我收到了 https://google.com but this error from URL above (https://ancine.band.com.br/xml/pgrt1_dta_20150303.xml 的成功回复。

使用 PHP、.NET 和 NodeJS URL 工作正常。

有人知道为什么会这样吗?

那是安全协议的问题。我使用的是 TLSv1,但主机仅接受 TLSv1.1 和 TLSv1.2,然后我使用以下说明更改了 Java 中的协议:

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

除了接受的答案外,其他问题也可能导致异常。对我来说,是证书不受信任(即自签名证书,不在信任库中)。

如果证书文件不存在或无法加载(例如,路径中的拼写错误)可能---在某些情况下---导致相同的异常。

您可以在系统 属性 中将协议版本设置为:

克服ssl握手错误

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

我遇到了同样的问题,我将证书添加到信任库解决了这个问题。

我有一个类似的问题,通过取消选中 java 高级安全中的选项解决了“使用 SSL 2.0 兼容的 ClientHello 格式。

此错误是安全库的一般错误,在其他情况下也可能发生。 以防其他人在使用 javax.mail 向 smtp 服务器发送电子邮件时遇到同样的错误。然后强制其他协议的代码设置一个 属性 像这样:

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});

接受的答案在我的情况下不起作用,不知道为什么。我从 JRE1.7 切换到 JRE1.8,这自动解决了问题。 JRE1.8 默认使用 TLS1.2

我在 java 8 上使用 SSL/TLS 服务器套接字库时遇到此异常。将 jdk 更新为 14(并将 VM 更新为 14)解决了该问题。

我和其他人一样遇到了同样的问题.. 添加 System.setProperties(....) 并没有为我解决问题。

所以我的电子邮件客户端在一个单独的项目中上传到一个工件。我正在将此项目作为 gradle 依赖项导入到其他项目中。我的问题是我在我的 build.gradle 中为 javax.mail 使用 implementation,这导致了下游问题。
我将此行从 implementation 更改为 api,我的下游项目开始工作并再次连接。

请关闭 android 工作室并删除文件

.gradle

.idea

从您的项目中获取文件。希望对您有所帮助

位置:转到Android工作室项目->您的项目->查看两个文件删除(.gradle & .idea

我在我的 Spring 引导应用程序上启用了相互 SSL,我的 Jenkins 管道正在重建码头工人,启动撰写,然后 运行 集成测试每次都失败并出现此错误. 在同一台 Jenkins 机器上的独立测试中,我每次都能在没有此 SSL 错误的情况下测试 运行 码头工人。 事实证明,当测试开始执行时,服务器还没有完全启动。 在我的 bash 脚本中休眠几秒钟以允许 Spring 启动应用程序并 运行 完全解决了这个问题。

在我的例子中,我正在向使用 SSLV3 的系统发出请求。 所以我添加了以下 jvm 选项。问题得到解决。

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

有时可能是网络问题造成的 不知道原因,但在切换到其他网络后,应用程序构建并安装成功。

下面的代码对我有用 您必须在 surefire 插件中添加以下配置

<configuration> <argLine>-Dhttps.protocols=TLSv1.1</argLine> </configuration>

对我来说,设置 -Dhttps.protocols="TLSv1,TLSv1.1,TLSv1.2"(或 -Dhttps.protocols="TLSv1.2" 就此而言)没有用。

因为我是 运行 AWS K8S 集群中 Docker 容器中的问题代码,所以我在 [AWS 文档][1] 中找到了类似的解决方案 设置此系统后 属性 -Djdk.tls.client.protocols=TLSv1.2,错误消失了。

[更新] 将其部署到生产环境后,我注意到这种行为是间歇性的:有时会发送我的电子邮件,有时不会。 在研究更多的同时,我发现我的客户端使用的是服务器不支持的 TLS 1.0(它只支持 TLS 1.2) 我收到的详细错误消息是这样的:

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

最后,经过多次试验,我使用这里的答案解决了它: [1]: https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/security-java-tls.html

正如@Zigri2612 所建议的,对我有用的是添加 TLS https.protocols,但我必须使用空格而不是逗号分隔值来完成它:

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

检查您的互联网连接,然后重新同步您的项目。

我也遇到过同样的错误提示,但是原因和解决方法很有意思:

我的问题通过将 openjdk 从 8u40 升级到 8u191 或更高版本 8u312 得到解决,

根本原因是一种互操作性问题,似乎客户端和服务器使用不同的填充方法或密码参数(例如 EC 曲线)进行 DH 密钥交换,

所以如果你 运行 没有解决方案,可能你可以尝试升级你的 jdk(不要只升级到主要版本,先尝试升级到更高的次要版本,请注意我的问题已通过 openjdk8uXXX 的更高次要版本解决,但仍因 openjdk9)

而失败

您可以在(握手部分)参考整个故障排除过程: https://lyhistory.github.io/docs/software/network/http_ssl_tls_setup.html