Получение javax.net.ssl.SSLException: получено фатальное предупреждение: protocol_version при очистке данных с помощью Jsoup
Я пытаюсь получить данные с сайта с помощью Jsoup. Ссылка на сайт находится здесь!
Вот мой код для получения данных. `
// WARNING: do it only if security isn't important, otherwise you have
// to follow this advices: http://stackru.com/a/7745706/1363265
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager(){
public X509Certificate[] getAcceptedIssuers(){return null;}
public void checkClientTrusted(X509Certificate[] certs, String authType){}
public void checkServerTrusted(X509Certificate[] certs, String authType){}
}};
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
;
}`
String url = "https://www.sos.nh.gov/corporate/soskb/SearchResults.asp?FormName=CorpNameSearch&Words=Starting&SearchStr="+query+"&SearchType=Search";
Connection.Response response = Jsoup.connect(url).timeout(30000)
.method(Connection.Method.GET)
.userAgent("Mozilla/5.0 (Windows NT 10.0; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0")
.execute();
Document document = response.parse();
Пожалуйста, предложите мне, в чем моя ошибка здесь.
2 ответа
Вы хотите использовать Java 8 здесь, так как он поддерживает TLSv1.2 по умолчанию с дополнительными необходимыми комплектами шифров.
Почему не Java 7?
Я протестировал на своем компьютере Java 7 (1.7.0_45) и получил ту же ошибку.
Я активировал сообщения отладки и принудительно включил TLSv1.2.
System.setProperty("javax.net.debug", "all");
System.setProperty("https.protocols", "TLSv1.2");
Тогда я столкнулся с этой новой ошибкой:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
Наконец, я пошел к анализатору SSL Comodoca и увидел кое-что интересное. Согласно анализатору SSL, на сайт, на который вы нацелены, включены только следующие комплекты шифров:
Cipher Suites включен Имя (ID) Размер ключа (в битах) TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xC02F) 128 ECDH 256-бит (P-256) TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xC030) 256 ECDH 256-бит (P-256) TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x9E) 128 DH 2048 бит TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x9F) 256 DH 2048 бит
(см. полную информацию)
Со своей стороны, у меня нет ни одного из вышеуказанных апартаментов. Проверьте, есть ли они у вас:
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, null, new java.security.SecureRandom());
String[] scs = sc.getSocketFactory().getSupportedCipherSuites();
Arrays.sort(scs);
for(String s : scs) {
System.out.println(s);
}
См. SSLSocketFactoryEx для включения необходимых наборов шифров.
Почему Java 8?
С другой стороны, мне удалось запустить код, перейдя с Java 7 на Java 8 (1.8.0_20), которые по умолчанию поддерживают TLS v1.2 и предоставляют необходимые наборы шифров.
Вот сокращенный список поддерживаемых комплектов шифров (всего 71 комплект) для Java 8 (1.8.0_20) в Windows 7.
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
...
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
отрывок
try {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
}
} };
// Install the all-trusting trust manager
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Fetch url
String url = "https://www.sos.nh.gov/corporate/soskb/SearchResults.asp?FormName=CorpNameSearch&Words=All&SearchStr=facebook&SearchType=Search";
Connection.Response response = Jsoup //
.connect(url) //
.timeout(60000) //
.method(Connection.Method.GET) //
.userAgent("Mozilla/5.0 (Windows NT 10.0; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0") //
.execute();
Document document = response.parse();
System.out.println(document);
} catch (Exception e) {
e.printStackTrace();
}
Заключительная мысль:
Когда дело доходит до безопасности, ВСЕГДА используйте последнюю обновленную версию.
(Из комментария для закрытия, немного расширен для будущих искателей)
Экспериментально для этого сайта требуется версия протокола TLSv1.2, и хотя в Java7 JSSE это реализовано, на стороне клиента по умолчанию отключаются версии 1.2 и 1.1. Java8 включает их по умолчанию; или в Java7, так как Jsoup использует HttpsURLConnection
Вы можете изменить включенные версии с системным свойствомhttps.protocols
, Вам нужно включить хотя бы TLSv1.2
и для большей гибкости следует использовать все приемлемые в настоящее время протоколы https.protocols=TLSv1,TLSv1.1,TLSv1.2
,
Кроме того, используя это все доверие TrustManager
означает, что любой злоумышленник, имеющий доступ к вашей сети, может подделать этот сайт и раскрыть любые конфиденциальные данные, которые вы ему отправляете. Лучше установить локальное хранилище доверенных сертификатов, чтобы оно принимало сертификаты и, следовательно, серверы, которые вам нужны, но не поддельные.