3

We've been using Springs HttpInvoker for a few weeks now and it works like a charm. From my front end (web)application I connect to the backend's userService like this:

<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>

The UserService is then nicely injected into our front end classes.

Now we're deploying this on a proper (WAS7) server and the requirement there is to use SSL (https). So, I change the http (of the serviceUrl) to https but then I get:

 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

which makes sense because the certificate installed on the server (where WAS runs) is not signed by a CA.

We already have some experience with this since on the same WAS there is a webservice running; for this we use cxf and we have generated a jks file (with keytool) that resides in the client application and is set as following:

<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>

I guess for the Http Invoker we need to do something similar but we have no idea how to use this trust.jks in the invoker.

One thing I did find is to use a different requestExecutor; like this:

<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>

After this I no longer get the certificate error but the userService does not appear to be created since then I get:

NoSuchBeanDefinitionException: No matching bean of type [com...service.UserService] found for dependency
2
  • May this helps: blog.jayway.com/2008/09/30/… Commented Jan 5, 2012 at 11:51
  • @Ralph, tx, I already had a look at this blog before but, as I understand it, it doesn't completely address our issue (see the last post in this blog). Commented Jan 5, 2012 at 12:36

2 Answers 2

2

If you mix what you can find here (http://stackoverflow.com/questions/5947162/https-and-self-signed-certificate-issue) to configure the HttpClient returned to have a pre configured SSLSocketFactory, you can change the hostname verifier of the socket factory to accept the cerificate, something close to this:

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

According to you config, besides using CommonsHttpInvokerRequestExecutor you also have to configure the HTTPClient used and the SSL Socket factory

I know this probably does not completely answer your question but it's a starting point for other searches! Good Luck and don't forget to post the final solution.

Sign up to request clarification or add additional context in comments.

Comments

2

You can try something as follows:

First write a custom class of 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();
        }
    }

}

and refer this class in your xml file instead of org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor as

<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>

4 Comments

We no longer use Spring HTTP invoker so I can't validate your answer but +1 anyway for making the effort to provide a good reply to an old question
@StijnGeukens Thank you. But, may know why you don't use HTTP invoker, I mean if you are using any alternative for it?
I believe we switched to hessian.
The implementation can be updated for the last version of Apache HttpClient. See : stackoverflow.com/questions/19517538/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.