Как исправить (SSLException) полученное фатальное предупреждение: версия протокола в Java


Я пытаюсь выполнить вызов get на веб-сайт https://www.facebookbrand.com/ и при этом я получаю ошибку (SSLException), полученную фатальным предупреждением: protocol_version. Сайт в вопрос, используя протоколе TLSv1.2 и если я настроить мой ConnectionFactory специально поддерживают этот протокол только он отлично работает, но мне нужно для каждого сайта, и от понимания моего жесткого кодирования его в протоколе TLSv1.2 бы не работать на другие веб-сайты HTTPS, который не используется в протоколе TLSv1.2. Я также пробовал в том числе и список протоколов ("протоколе TLSv1.2", "в протоколе TLSv1.1", "протоколе TLSv1", "протокол SSLv3", "SSLv2Hello"), но затем я получаю ошибку непризнанной протокол SSL сообщение, связь открытым текстом. Я не забочусь о том, насколько это безопасно, мне просто нужно иметь возможность подключиться к каждому веб-сайту по существу, и я пытаюсь найти лучший способ сделать это. Ниже я включил свой код.

Вот мой код для настройки httpClient etc:

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslBuilder.build(), SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
PlainConnectionSocketFactory pcsf = new PlainConnectionSocketFactory();
Registry socketFactoryRegistry = RegistryBuilder.create().register("https", sslsf).register("http", pcsf).build();
PoolingHttpClientConnectionManager multiConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
multiConnectionManager.setMaxTotal(100);
multiConnectionManager.setDefaultMaxPerRoute(10);
httpClientBuilder.setConnectionManager(multiConnectionManager);
this.httpClient = httpClientBuilder.disableContentCompression().setSSLSocketFactory(sslsf).build();

Вот код для запроса get и выполнения через httpClient:

HttpGet call = new HttpGet(url);
LinkPullerContentHandler handler = new LinkPullerContentHandler();
PageLinks pl = new PageLinks(url, 200, null);
HttpResponse getResponse;

try {
    call.addHeader("User-Agent","Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)");
    call.addHeader("Accept","text/html");
    call.setConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.IGNORE_COOKIES).build());

    try {
        getResponse = httpClient.execute(call);
    } catch (SocketTimeoutException ste) {
        LOG.error(String.format("Socket timeout pulling URL %s; skipping",url));
        pl.setHttpStatusCode(408);
        return pl;
    } catch (ConnectTimeoutException cte) {
        LOG.warn(String.format("Connect timeout pulling URL %s; skipping", url));
        pl.setHttpStatusCode(408);
        return pl;
    } catch (UnknownHostException uhe) {
        LOG.warn("Unable to resolve host for URL {}; skipping", url);
        pl.setHttpStatusCode(404);
        return pl;
    } catch (Exception e) {
        LOG.error(String.format("Unable to load link %s: (%s) %s",
            url,e.getClass().getSimpleName(),e.getMessage()),e);
        pl.setHttpStatusCode(420);
        return pl;
    }

    int code = getResponse.getStatusLine().getStatusCode();

Пытаясь включить специально протокол TLSv1. 2, я изменил код настройки SSLConnectionSocketFactory следующим образом:

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslBuilder.build(),
                new String[] { "TLSv1.2" }, null,
                SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

Который работает для данного веб-сайта, но я чувствую, что он потерпит неудачу на некоторых других, так как он жестко закодирован в TLSv1.2. Альтернативно вот как это выглядело, когда я попытался включить дополнительные протоколы:

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslBuilder.build(),
                new String[] { "TLSv1.2", "TLSv1.1", "TLSv1", "SSLv3", "SSLv2Hello"},
                null, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

Который в конечном итоге получает исключение " непризнанное сообщение SSL, открытое соединение.- Я тоже пытаюсь. включить список шифров, чтобы посмотреть, поможет ли это, но у меня пока не было никакого успеха.

Любая помощь, которую кто-то может оказать, чтобы помочь мне понять, как сделать эту работу, не жертвуя при этом возможностью получить другие сайты, была бы потрясающей.

Заранее спасибо

1 2

1 ответ:

Не используйте SSLv2Hello.

, что сайт, видимо, не поддерживает формат V2 привет; даже если он будет успешно вести переговоры протоколе TLSv1.2 на формат В3+ Здравствуйте, если я отправлю (с OpenSSL) формат поддерживает обновление до V2 в протоколе TLSv1.2 (проводная версия 3.3), она реагирует с HTML тело (даже заголовки HTTP) открытым текстом говорю, что "Служба недоступна" и "сайт недоступен". Это, конечно, не является допустимым ответом ни для протокола v2, ни для протоколов v3+.

Если настроить все протоколы от SSLv3 до TLSv1. 2, но не SSLv2Hello - который является по умолчанию для Java8 в любом случае-вы сможете вести переговоры с другими сайтами, которые поддерживают что-либо вплоть до SSLv3, предполагая, что нет никакой другой проблемы, как сайт использует недопустимый сертификат. (И исключая любой сайт, который реализует только проект TLSv1. 3 и ничего стандартного.) Если есть какой-либо сервер, все еще такой старый или хромой, что он поддерживает только SSLv2, Java не может фактически общаться с ним в любом случае; единственное "преимущество" SSLv2Hello заключается в том, что JSSE выдает конкретное исключение о "SSLv2 не поддерживается", а не различные и часто неоднозначные ошибки связи, которые сложнее отладить.