Java 11 SSLHandshakeException с TLS 1.3: как вернуться к TLS 1.2?
Мое приложение представляет собой разновидность "веб-скребка", который загружает HTML- код с нужной страницы ввода с помощью библиотеки Java Jsoup. Недавно я обновил свою платформу приложений с Java 8 до Java 11. После этого обновления я получил несколько отчетов от моих клиентов, в которых говорилось, что они получают исключения SSLHandshakeExceptions при попытке загрузить HTML-содержимое определенных веб-страниц. Веб-страницы, на которых они появляются, различаются от устройства к устройству, и на некоторых устройствах мои клиенты вообще не могут загружать какие-либо веб-страницы (ни http://, ни https: // веб-страницы).
Я пытался решить эту проблему несколькими способами, но безрезультатно:
- Замена файла CACERT среды выполнения Java 11 файлом CACERT среды выполнения Java 8
- Создание настраиваемого приемника сертификата SSL, который принимает все сертификаты SSL независимо от срока действия (я знаю, что это плохо для производственного кода, но это было сделано только для тестовых целей) - см. Доверие ко всем сертификатам с использованием HttpClient через HTTPS
На данный момент я не совсем уверен, какие варианты выбрать, поскольку у меня ограниченные знания SSL, TLS и HTTPS. Этих ошибок никогда не возникало в Java 8, и до обновления до Java 11 все работало нормально.
Насколько я понимаю, единственное, что изменилось в Java 11 в отношении SSL, - это обновление до TLS 1.3, тогда как предыдущая версия Java полагалась на использование TLS 1.2.
Следовательно, я хотел бы заставить Java 11 использовать TLS 1.2, а не TLS 1.3, поскольку я считаю, что это является причиной SSLHandshakeExceptions. Как мне это сделать?
3 ответа
При использовании Jsoup соединение Neardupe Java 11 HTTPS не удается из-за исключения SSL HandshakeException, но мне есть что добавить.
Используйте Connection.sslSocketFactory (factory) с подходящим аргументом. Предполагая стандартные поставщики / поставщики по умолчанию, вы можете использовать фабрику, созданную изSSLContext.getInstance("TLSv1.2")
возможно, с менеджером доверия по умолчанию и менеджером ключей, т.е. .init(null,null,null)
.
Или установить jdk.tls.client.protocols
или https.protocols
согласно таблице 8-3 в документации JSSE. Обратите внимание, что это может повлиять на любые другие соединения SSL/TLS или другие соединения URLConnection для HTTPS, созданные с той же JVM.
Я был бы удивлен, если это решит вашу проблему. TLS1.3 был отложен на годы отчасти из-за добавленных хаков, поэтому он не дает сбоев в устаревших 1.2 (и даже более ранних) системах и "ящиках".
Вы также можете определить jdk.tls.client.protocols=TLSv1.2
в командной строке вашего Java-клиента:
java -Djdk.tls.client.protocols=TLSv1.2 -jar ... <rest of command line here>
Это заставит вашего клиента рекламировать только TLS версии 1.2 и использовать эту версию, даже если сервер, к которому вы подключаетесь, поддерживает TLS 1.3.
Для справки: эта ошибка TLS1.3 была известной ошибкой в JDK11 до 11.0.2. https://bugs.openjdk.java.net/browse/JDK-8211806