SNI Java 1.8 и рукопожатие Jboss SSL

Мои вопросы):

Похоже, что одним из отличий в базовом sun.net.www.protocol.https.HttpsClient является реализация HostNameVerifier. В настоящее время проблема заключается в HttpsClient в методе afterConnect, где setHost не вызывается, и это не похоже, относятся к любым SSLParameters - моя попытка обойти это состояла в том, чтобы заставить наш код вызова клиента WS загрузить нашу фабрику, до сих пор я безуспешно -

1) Как мне получить наш код вызова клиента WS для загрузки нашей фабрики?

OR

2) Как настроить JBOSS для правильной обработки этого запроса? (Предположим, что это конфигурация JBOSS)

Этап: - Java Oracle JDK 1.8 64-разрядная версия - Jboss 6.4 EAP - AXIS2 - JAX - Сертификаты действительны и загружены правильно - Я могу воспроизвести ошибку с помощью автономного приложения Java, и я могу исправить ошибку с помощью автономного Java-приложение.

Попытки:

1) Добавлен выходной перехватчик CXF фазы PRE-PROTOCOL, который добавит имя хоста в заголовок.

public void handleMessage(Message message) {
       System.out.println("Inside handle message");
       Map<String, List> headers = (Map<String, List>) message.get(Message.PROTOCOL_HEADERS);
       try {
                  headers.put("Host", Collections.singletonList("ecm-users-dev.aexp.com"));
           } catch (Exception ce) {
           throw new Fault(ce);
       }
    }

2) Попытался отключить HostNameVerfier, так как в некоторых блогах предлагалось, чтобы включение hostNameverfier вызвало проблемы.

3) Создал оболочку вокруг SSLSocketFactory для ввода параметров SSL, как это предлагается ниже в блоге http://javabreaks.blogspot.com/2015/12/java-ssl-handshake-with-server-name.html

4) Внедрение параметров хоста в сеанс httpconduit через клиентскую политику.

final HTTPConduit httpConduit = (HTTPConduit) cxfClient.getConduit();
    final TLSClientParameters tlsCP = new TLSClientParameters();
   HTTPClientPolicy clientPolicy = new HTTPClientPolicy();
   clientPolicy.setHost(endpoint.getHost());
   httpConduit.setClient(clientPolicy);
   httpConduit.setTlsClientParameters(tlsCP);

5) Пробовал внедрить оболочку SSLSocketfactory через провайдера привязки.

В чем проблема: установка SNI..

Мои журналы:

-------Работающий-----

14:11:02,417 INFO  [stdout] (http-/127.0.0.1:8080-2) Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA224withECDSA, SHA224withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA, MD5withRSA
14:11:02,419 I
NFO  [stdout] (http-/127.0.0.1:8080-2) Extension server_name, server_name: [type=host_name (0), value=some.server.value]
14:11:02,419 
INFO  [stdout] (http-/127.0.0.1:8080-2) ***

----Нерабочий-----

14:15:35,081 INFO  [stdout] (http-/127.0.0.1:8080-1) Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA224withECDSA, SHA224withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA, MD5withRSA
14:15:35,082 
INFO  [stdout] (http-/127.0.0.1:8080-1) ***

(в этом отсутствует SNI)

(две попытки) фрагменты кода:

try{               bp.getRequestContext().put("com.sun.xml.ws.transport.https.client.SSLSocketFactory", new SSLSocketFactoryWrapper(sslContext.getSocketFactory(), sslParameters));
                        } catch (Exception e) {
                            log.error("Error of port default SSL configuration applying", e);
                            throw new IllegalArgumentException("fail to configure ws client by configuration", e);
                           }

--------------------

bp.getRequestContext().put("com.sun.xml.ws.transport.https.client.SSLSocketFactory" , new SSLSocketFactoryFacade().createSocket(endPoint,443));
                        log.info("exit getServiceClient(): " + client);
                        return client;
        } catch(Throwable e) {
                        log.error("Error creating the Service Client", e);
                        throw new RuntimeException("Error creating the Service Client: " + e.getMessage(), e);
    }

Аналогичный вопрос:

(Предложение не сработало) Расширенное имя_сервера (расширение SNI) не отправляется с jdk1.8.0, но отправляется с jdk1.7.0


person Bob    schedule 18.11.2016    source источник


Ответы (2)


Если ваш клиент WS основан на resteasy :

  • есть ошибка в w java 8 (см.: bugs.java.com/bugdatabase/view_bug.do?bug_id=8144566)
  • эта ошибка влияет на устаревший код apache httpclient (см. Issues.apache.org/jira/browse/HTTPCLIENT-1726)
  • этот устаревший код используется в resteasy (https://issues.jboss.org/browse/RESTEASY- 1089)

Обходной путь от https://issues.jboss.org/browse/RESTEASY-1089:

new ResteasyClientBuilder().httpEngine(new URLConnectionEngine()).build()

person Majka    schedule 18.11.2016
comment
Эй, Майка! спасибо за ответ - эта конкретная система настроена так, что она подберет любую структуру JAX-WS, которую предоставляет сервер приложений - я считаю, что в этом случае она должна вызывать инфраструктуру CXF apache, предоставленную jboss. (Не хотел бы я использовать resteasy!!!) - person Bob; 18.11.2016
comment
Эта ошибка в java возникает только без прокси-сервера https. Если вы можете настроить прокси, он должен работать. - person Majka; 18.11.2016

Клиент WS, который мы использовали в этом случае, использует AXIS2 и не зависит от используемой платформы. Проблема SNI была вызвана тем, что заголовок SSL, который не был установлен, назывался:

Расширение имя_сервера, имя_сервера:

Его опубликованные значения должны выглядеть примерно так:

[тип=host_name (0), значение=some.server.value]

Во время наших первоначальных испытаний были сделаны два ошибочных набора предположений: 1) можно было использовать любой httpclient, т. е. клиент, предоставленный jboss, или клиент, предоставленный JAVAX, или даже клиент, предоставленный AXIS2, — однако это было не так, и это привело ко многим путям, которые были не способствует решению. Мы с достаточной степенью уверенности знали, что нам нужно установить заголовки SNI через SSLFactory, но мы не знали, как заставить эту фабрику производить коннекторы, которые будут использоваться системой. Что-то, что могло бы помочь в определении этой проблемы, было бы:

 Class klass = String.class;
URL location = klass.getResource('/' + klass.getName().replace('.', '/') + ".class");

2) Еще одной областью, которую мы не смогли продвинуть вперед, было решение для привязки, представленное во многих вики и руководствах:

bindingProvider.getRequestContext().put("<a href="http://com.sun.xml.internal.ws">com.sun.xml.internal.ws</a>.transport.https.client.SSLSocketFactory", new SSLSocketFactoryFacade());

Приложение имело собственную версию HTTPclient, которую необходимо было использовать. Поэтому был создан новый класс BrokeredEpaasSSLSocketFactory, который реализует SecureProtocolSocketFactory на основе org.apache.commons.httpclient 3.1, предоставленного приложением. Ключевые фрагменты кода следующие: В самом клиенте: (чтобы ограничить использование фабрик, мы изменили URL-адреса EPAAS, чтобы они содержали epaas вместо HTTPS) Изначально мы думали об использовании регистрации в классе протокола для https – однако это будет означать, что каждое приложение с уникальным URL-адресом должно быть протестировано

Protocol myHTTPS = new Protocol( "https", new MySSLSocketFactory(), 443 );
 Protocol.registerProtocol( "https", myHTTPS );

Также попытка изменить протокол (с использованием epaas для выполнения запроса вместо https) привела к тому, что AXIS выдавал ошибку, которая не позволяла продолжить работу, поэтому мы отказались от этой идеи…

String endPointFinal = endPoint.replaceAll("epaas://", "https://");
          bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endPointFinal);
          bp.getRequestContext().put("SO_TIMEOUT", new Integer(sTimout));
          bp.getRequestContext().put("CONNECTION_TIMEOUT", new Integer(cTimeout));
          BrokeredEpaasSSLSocketFactory factory = new BrokeredEpaasSSLSocketFactory();   
          Protocol authhttps = new Protocol("https", factory, 443);
          HttpClient httpclient = new HttpClient();
          URL URI = new URL(endPointFinal);
          httpclient.getHostConfiguration().setHost(URI.getHost(), 443, authhttps);
          GetMethod httpget  = new GetMethod("/ecmuser/BrokeredConnectorService");
          httpclient.executeMethod(httpget);

Недавно созданный класс (BrokeredEpaasSSLSocketFactory) имеет два метода, представляющих особый интерес: В настоящее время это единственный метод createSocket, используемый приложением (хотя все они были изменены для использования в будущем):

public Socket createSocket(String host, int port, InetAddress localAddress, int localPort, HttpConnectionParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
        // TODO Auto-generated method stub
        if (params == null) {
            throw new IllegalArgumentException("Parameters may not be null");
        }
        int timeout = params.getConnectionTimeout();
        if (timeout == 0) {
            return _defaultFactory.createSocket(host, port,localAddress,localPort);
        } else {

            SSLSocket socket = (SSLSocket) _defaultFactory.createSocket();
            setParameters(socket,host);
            SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
            SocketAddress remoteaddr = new InetSocketAddress(host, port);
            socket.bind(localaddr);
            socket.connect(remoteaddr, timeout);
            return socket;
        }
    }

Это метод, который фактически устанавливает заголовки SNI в исходящем запросе SSL:

private void setParameters(SSLSocket socket, String host)
        throws MalformedURLException {
    SSLParameters sslParameters = new SSLParameters();
    List<SNIServerName> sniHostNames = new ArrayList<SNIServerName>(1);
    sniHostNames.add(new SNIHostName(host));
    sslParameters.setServerNames(sniHostNames);
    socket.setSSLParameters(sslParameters);
}
person Bob    schedule 07.12.2016