SSL равноправно закрывается в 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$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
Я получил успешный ответ с https://google.com/ но эта ошибка с URL-адреса выше ( https://ancine.band.com.br/xml/pgrt1_dta_20150303.xml).
Используя PHP, .NET и NodeJS, этот URL работает нормально.
У кого-нибудь есть идеи, почему это происходит?
22 ответа
Это проблема протокола безопасности. Я использую TLSv1, но хост принимает только TLSv1.1 и TLSv1.2, затем я изменил протокол в Java с помощью инструкции ниже:
System.setProperty("https.protocols", "TLSv1.1")
;
Вы можете установить версии протокола в системном свойстве как:
преодолеть ошибку рукопожатия ssl
System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");
Помимо принятого ответа, другие проблемы могут вызвать исключение. Для меня это было то, что сертификат не был доверенным (то есть, самоподписанный сертификат, а не в доверенном хранилище).
Если файл сертификата не существует или не может быть загружен (например, опечатка в пути) может - при определенных обстоятельствах - вызвать такое же исключение.
Как предположил @Zigri2612, у меня сработало добавление TLS
https.protocols
, но мне пришлось сделать это с пробелами вместо значений, разделенных запятыми:
System.setProperty("https.protocols", "TLSv1 TLSv1.1 TLSv1.2 TLSv1.3");
Пожалуйста , закройте студию Android и удалите файл
.gradle
и
.idea
файл из вашего проекта. Надеюсь, это будет полезно
Расположение: перейдите в проекты студии Android-> ваш проект -> см. Оба файла удалить (.gradle
&
.idea
)
Эта ошибка является общей для библиотек безопасности и может возникнуть в других случаях. В случае, если другие люди имеют такую же ошибку при отправке электронных писем с 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});
Я столкнулся с тем же сообщением об ошибке, но причина и решение довольно интересны:
моя проблема решена путем обновления openjdk с 8u40 до 8u191 или более поздней версии 8u312,
основной причиной является своего рода проблема совместимости, которая кажется, что клиент и сервер используют другой метод заполнения или параметр шифрования (например, кривую EC) для обмена ключами DH,
поэтому, если у вас закончились решения, возможно, вы можете попробовать обновить свой jdk(не просто обновить до основной версии, сначала попробуйте обновить до более высокой минорной версии, обратите внимание, что моя проблема решена более старшей минорной версией для openjdk8uXXX, но все еще не удалось с openjdk9)
вы можете обратиться ко всему процессу устранения неполадок в (раздел рукопожатия):https://lyhistory.github.io/docs/software/network/http_ssl_tls_setup.html
Код ниже работал у меня.Вы должны добавить конфигурацию ниже в плагине surefire.
<configuration> <argLine>-Dhttps.protocols=TLSv1.1</argLine> </configuration>
Для меня установка
-Dhttps.protocols="TLSv1,TLSv1.1,TLSv1.2"
(или
-Dhttps.protocols="TLSv1.2"
если на то пошло) не сработало.
Поскольку я запускал проблемный код в контейнере Docker в кластере AWS K8S, я нашел аналогичное решение в документации AWS. После установки этого системного свойства
-Djdk.tls.client.protocols=TLSv1.2
, ошибка исчезла.
У меня была такая же проблема, как и у всех, я полагаю... добавление System.setProperties(....) не помогло мне.
Итак, мой почтовый клиент находится в отдельном проекте, загруженном в коллекцию. Я импортирую этот проект в другие проекты как зависимость от Gradle. Моя проблема заключалась в том, что я использовалimplementation
в моем build.gradle для javax.mail
, что вызывало проблемы ниже по течению.
Я изменил эту строку сimplementation
к api
и мой последующий проект начал работать и снова подключаться.
У меня был включен взаимный SSL в моем приложении Spring Boot, и мой конвейер Jenkins перестраивал докеры, запускал компоновку, а затем запускал интеграционные тесты, которые каждый раз терпели неудачу с этой ошибкой. Мне удавалось каждый раз тестировать работающие докеры без этой ошибки SSL в отдельном тесте на той же машине Jenkins. Оказалось, что сервер не был полностью запущен, когда начались тесты. Ввод в режим сна на несколько секунд в моем сценарии bash, чтобы разрешить загрузочное приложение Spring работать и запускать, полностью решило проблему.
В моем случае я делал запрос к системе, использующей SSLV3. Итак, я добавил следующую опцию jvm. И проблема решена.
-Dhttps.protocols="TLSv1,TLSv1.1,TLSv1.2"
Иногда это может быть вызвано проблемами с сетью. Не знаю причину, но после переключения в другую сеть приложение было успешно собрано и установлено.
Для моего приложения, использующего Spring Boot API, эта проблема была вызвана подключением к VPN.
Я пробовал различные обходные пути, включая принятый ответ (я позвонилSystem.setProperty("https.protocols", "TLSv1.1")
в моей основной функции), но ничего не сработало.
Я отключился от VPN и больше не получаю эту ошибку.
У меня возникла эта проблема с Android Studio, потому что я не разрешил «adb.exe» через брандмауэр Windows. Тем самым проблема была решена.
Я столкнулся с той же самой проблемой, для меня добавление сертификата в доверенное хранилище решило эту проблему.
Принятый ответ не сработал в моей ситуации, не знаю почему. Я переключился с JRE1.7 на JRE1.8, и это решило проблему автоматически. JRE1.8 использует TLS1.2 по умолчанию
Я испытал это исключение, используя библиотеку Socket сервера SSL/TLS на java 8. Обновление jdk до 14 (а также виртуальной машины до 14) решило проблему.
У меня была похожая проблема, которая была решена путем снятия флажка в расширенной безопасности Java для "Использовать совместимый с SSL 2.0 формат ClientHello.
При использовании клиентских сертификатов подобную ошибку также можно вызвать, если у вас есть просроченный, отозванный или иным образом ненадежный сертификат клиента, особенно если он работает для некоторых клиентов, а не для других, и программное обеспечение идентично. По какой-то причине Java не утруждает себя проверкой своего собственного конца, прежде чем жаловаться на неожиданное поведение другого конца.
Практически любая причина, по которой рукопожатие TLS может закончиться неудачно в середине обмена, может быть действительным триггером для такого рода ошибки.
Журналы на стороне сервера (или общие журналы на другой стороне) могут предоставить дополнительную информацию о том, почему рукопожатие было прекращено.
Проверьте подключение к Интернету, а затем повторно синхронизируйте свой проект.
В моем случае в URL был только пробел. Поэтому сначала проверьте строку запроса!