JAVA 6 не поддерживает SNI. Есть ли альтернативный способ проверки и принятия SSL-сертификата через TLS?

Я знаю, почему браузеры и java7 не затронуты, потому что они отправляют Server Name Indication-SNI как часть информации SSL. Таким образом, apache знает, какой виртуальный хост использовать перед запуском SSL-рукопожатия, и возвращает соответствующий сертификат. Java 6 не поддерживает SNI. Итак, мой вопрос: как мне проверить и разрешить принятие сертификата в java 6.

Я сделал клиент Spring для использования веб-сервиса, вот мой код

public class classname1 {

    static {
        System.setProperty("javax.net.ssl.trustStore", "E://Workspace//keystore");
        System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
        System.setProperty("https.protocols", "SSLv3");
        System.setProperty("https.protocols", "TLSv1");

    }
    static {

                HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier()
                    {
                        public boolean verify(String hostname, SSLSession session)
                        {
                            if (hostname.equals("192.168.10.22"))
                                return true;
                            return false;
                        }
                    });
            }

    private static void main(String[] args) {
        try {
            SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
            SOAPConnection soapConnection = soapConnectionFactory.createConnection();

            String url = "https://192.168.10.22/getInformationSearch.asmx?wsdl";
            SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url);
            printSOAPResponse(soapResponse);
            soapConnection.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static SOAPMessage createSOAPRequest() throws Exception {
        // ... Code for request, which will be hitted to url
    }

    private static void printSOAPResponse(SOAPMessage soapResponse) throws Exception {
        // ... Code for response, which will fetch information from webservice
        // URL
    }

}

Как видите, я сделал два метода: 1. для запроса createSOAPRequest() 2. для ответа printSOAPResponse(). (Имя URL изменено в приведенном выше фрагменте)

В методе main() строка ниже сгенерирует запрос и отправит этот запрос заданному url SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url);, после чего он перейдет к статическому блоку, как показано выше в методе HttpsURLConnection.setDefaultHostnameVerifier().

В это время отладчик говорит: рукопожатие ssl не удалось, и одноранговый узел SSL закрылся неправильно. Это происходит только в JAVA 6, но этот код работает правильно с java 7/8.

Вместо этого статического блока я пробовал код ниже в java 6.

 HostnameVerifier hv = new HostnameVerifier() {
                public boolean verify(String urlHostName,
                        SSLSession session) {
                    return true;
                }
            };

Но все равно не получится!!!

Я использую следующие банки xercesImpl.jar, saaj-api.jar, saaj-impl.jar, spring-ws-core-1.5.6.jar, spring-ws-security-1.5.6.jar и сертификат для этого домена SSL. был импортирован в хранилище ключей и работает в java7/8, так что в хранилище доверенных сертификатов нет проблем, верно? (Я также сделал 2 сертификата, используя keytool для java 6 и 7, оба отлично работают в java7/8, но не в 6)

Я следил за этой потоком, но это не сработает. Итак, есть ли альтернативный способ проверить сертификат и получить ответ в среде Java 6, или мне следует изменить какой-либо JAR?


person Community    schedule 08.10.2016    source источник


Ответы (2)


Вы не можете, если сервер не настроен для подключения без SNI.

Без SNI сервер не может определить, какой виртуальный хост вам нужен, пока после не будет установлено соединение SSL.

Чтобы увидеть разницу, если у вас есть OpenSSL, вы можете использовать опцию s_client< /a>, чтобы извлечь различные представленные сертификаты или, возможно, отметить сбой подключения, когда вы не используете SNI:

СНИ:

echo | openssl s_client -servername www.virtualhost.com -connect 192.168.1.55:443 | openssl x509 -text

Замените 192.168.1.55 фактическим IP-адресом сервера, а www.virtualhost.com — именем хоста виртуального хоста, к которому вы хотите подключиться. Команда echo, добавленная перед конвейером, предотвращает зависание openssl в ожидании ввода.

Без СНИ:

echo | openssl s_client -connect 192.168.1.55:443 | openssl x509 -text

Без SNI вы можете увидеть совсем другой сертификат или получить ошибку подключения.

person Andrew Henle    schedule 08.10.2016

Как вы уже упоминали, Java 6 не поддерживает SNI. Но проблема отсутствия SNI заключается не только в проверке сертификата (поскольку сервер отправляет неправильный сертификат), но и в том, что в зависимости от конфигурации серверов сервер вызовет ошибку рукопожатия, если расширение SNI отсутствует и не указывает на имя хоста, доступное на сервере. И тут явно так:

... рукопожатие ssl завершилось неудачно, и одноранговый узел SSL закрылся неправильно. Это происходит только в JAVA 6, но этот код работает правильно с java 7/8.

Попытка изменить проверку сертификата, как вы пытались, в этом случае совершенно не поможет, потому что ошибка возникает еще до того, как клиент получит сертификат для проверки. Это означает, что нет никакого способа обойти это: вам нужно поддерживать SNI в вашем клиенте, если вы хотите общаться с этим конкретным сервером.

person Steffen Ullrich    schedule 08.10.2016