Spring HTTP invoker с https и неподписанным сертификатом - PullRequest
3 голосов
/ 05 января 2012

Мы используем Springs HttpInvoker уже несколько недель, и это работает как шарм. Из моего внешнего (веб) приложения я подключаюсь к пользовательской службе бэкэнда следующим образом:

<bean id="userService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
    <property name="serviceUrl" value="http://${backend.host}/backend-ws/remoting/UserService"/>
    <property name="serviceInterface" value="com...service.UserService"/>
</bean>

UserService затем красиво добавляется в наши классы внешнего интерфейса.

Теперь мы развертываем это на правильном (WAS7) сервере, и требуется использовать SSL (https). Итак, я изменяю http (для serviceUrl) на https, но затем получаю:

 org.springframework.remoting.RemoteAccessException: Could not access HTTP invoker remote service at [https://pbp-dev.dev.echonet/public/backend-ws/remoting/ParameterHelper]; nested exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

, что имеет смысл, поскольку сертификат, установленный на сервере (где работает WAS), не подписан центром сертификации.

У нас уже есть некоторый опыт в этом, поскольку на том же WAS работает веб-сервис; для этого мы используем cxf и сгенерировали файл jks (с keytool), который находится в клиентском приложении и настроен следующим образом:

<http:conduit name="https://serverurl/.*">
<http:tlsClientParameters secureSocketProtocol="SSL" disableCNCheck="false">
    <sec:trustManagers>
        <sec:keyStore type="jks" password="pass123" resource="trust.jks"/>
    </sec:trustManagers>
</http:tlsClientParameters>

Я думаю, для Http Invoker нам нужно сделать что-то похожее, но мы не знаем, как использовать этот trust.jks в invoker.

Одна вещь, которую я нашел, это использовать другой requestExecutor; как это:

<bean id="userService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
    <property name="serviceUrl" value="https://${backend.host}/backend-ws/remoting/UserService"/>
    <property name="serviceInterface" value="com...service.UserService"/>
    <property name="httpInvokerRequestExecutor">
    <bean class="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor" />
    </property>
</bean>

После этого я больше не получаю ошибку сертификата, но пользовательская служба, кажется, не создается с тех пор, как я получаю:

NoSuchBeanDefinitionException: No matching bean of type [com...service.UserService] found for dependency

Ответы [ 2 ]

2 голосов
/ 09 сентября 2012

Если вы смешаете то, что можете найти здесь (http://stackoverflow.com/questions/5947162/https-and-self-signed-certificate-issue) для настройки возвращаемого HttpClient с предварительно настроенным SSLSocketFactory, вы можете изменить верификатор имени хоста фабрики сокетов, чтобы принимать сертификат, что-то похожее на это:

xxx.setHostnameVerifier(new HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) { println("bypassing ssl cert handshaking as configured for self signed cert."); return true; }
});

Согласно вашей конфигурации, кроме использования CommonsHttpInvokerRequestExecutor, вам также необходимо настроить используемый HTTPClient и фабрику сокетов SSL

Я знаю, что это, вероятно, не полностью отвечает на ваш вопрос, но это отправная точка для других поисков! Удачи и не забудьте опубликовать окончательное решение.

1 голос
/ 15 октября 2015

Вы можете попробовать что-то следующим образом:

Сначала напишите пользовательский класс org.springframework.remoting.httpinvoker.HttpComponentsHttpInvokerRequestExecutor:

package com.myorg.proid.sample;

import static org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;

import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.X509Certificate;

import org.apache.http.client.HttpClient;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.springframework.remoting.httpinvoker.HttpComponentsHttpInvokerRequestExecutor;

/**
 * @author visruth
 *
 */
public class CustomHttpComponentsHttpInvokerRequestExecutor extends
        HttpComponentsHttpInvokerRequestExecutor {

    public CustomHttpComponentsHttpInvokerRequestExecutor() {
        skipSecurityChecking();
    }

    @SuppressWarnings("deprecation")
    private void skipSecurityChecking() {

        // HttpClient from super class.
        HttpClient httpClient = getHttpClient();

        TrustStrategy trustStrategy = new TrustStrategy() {
            @Override
            public boolean isTrusted(X509Certificate[] certificate,
                    String authType) {
                return true;
            }
        };

        try {
            httpClient
                    .getConnectionManager()
                    .getSchemeRegistry()
                    .register(
                            new Scheme("https", 80, new SSLSocketFactory(
                                    trustStrategy,
                                    ALLOW_ALL_HOSTNAME_VERIFIER)));
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (UnrecoverableKeyException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
    }

}

и укажите этот класс в файле xml вместо org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor как

<bean id="userService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
    <property name="serviceUrl" value="https://${backend.host}/backend-ws/remoting/UserService"/>
    <property name="serviceInterface" value="com...service.UserService"/>
    <property name="httpInvokerRequestExecutor">
    <bean class="com.myorg.proid.sample.CustomHttpComponentsHttpInvokerRequestExecutor" />
    </property>
</bean>
...