How to set up Apache CXF client to use WebSphere truststore? (Receiving "No trusted certificate found" exception.)

Toby Artisan picture Toby Artisan · Sep 1, 2011 · Viewed 13.4k times · Source

First, I'll start with a summary. I'm using an Apache CXF client to communicate over SSL with an Apache CXF service provider that is using a self-signed certificate. I imported the certificate into the WebSphere truststore on the client server, but I still receive a "javax.net.ssl.SSLHandshakeException: SSLHandshakeException invoking https://somesvcprovider.com/appname/svc/myservice: com.ibm.jsse2.util.h: No trusted certificate found" exception.

Now, here's the details:

I have an Apache CXF web service client that I am configuring using Spring, and the client is deployed to a WebSphere 6.1 application server. The CXF client communicates with an Apache CXF service provider on a different WebSphere server. The communication uses SSL.

The service provider is using a self-signed certificate. I've imported the provider's certificate into the WebSphere truststore on the client server through the administrative console. I accomplished this by going to SSL certificate and key management > SSL configurations > NodeDefaultSSLSettings > Key stores and certificates > NodeDefaultTrustStore > Signer certificates; then I used the "Retrieve from port" tool to import the certificate.

However, I still receive this error when attempting to contact the service provider: "javax.net.ssl.SSLHandshakeException: SSLHandshakeException invoking https://somesvcprovider.com/appname/svc/myservice: com.ibm.jsse2.util.h: No trusted certificate found".

The Spring configuration file is as follows:

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:sec="http://cxf.apache.org/configuration/security"
  xmlns:http="http://cxf.apache.org/transports/http/configuration"
  xmlns:jaxws="http://cxf.apache.org/jaxws"
  xsi:schemaLocation="
      http://cxf.apache.org/configuration/security
      http://cxf.apache.org/schemas/configuration/security.xsd
      http://cxf.apache.org/transports/http/configuration
      http://cxf.apache.org/schemas/configuration/http-conf.xsd
      http://cxf.apache.org/jaxws
      http://cxf.apache.org/schemas/jaxws.xsd
      http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd">
    <http:conduit name="*.http-conduit">
        <!-- deactivate HTTPS url hostname verification (localhost, etc) -->
        <!-- WARNING ! disableCNcheck=true should not used in production. -->
        <http:tlsClientParameters disableCNCheck="true" />
    </http:conduit>
    <!-- Read properties from property file(s). -->
    <bean id="propertyPlaceholderConfigurer"
            class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <!-- The *.spring.properties files are prefixed with a system property
                    that is set on the WebSphere server. -->
                <value>classpath:spring.${my.env}.properties</value>
            </list>
        </property>
    </bean>
    <jaxws:client id="myServiceClient"
        serviceClass="com.client.stub.cxf.IMyService"
        address="${my.svc.url}" />
    <bean id="myReport" class="com.client.MyReportRequestor">
        <property name="client" ref="myServiceClient"/>
    </bean>
</beans>

As shown above, the CXF client is injected via a setter by Spring. The code to contact the service is below:

List<String> formNames = client.retrieveNames(formIdsList);

Also, I don't know if this is related, but no trust managers are returned when I inspect the TLSClientParameters object on the CXF client at runtime. The code to do the inspection is below:

// Get the trust managers for this client.
Client proxy = ClientProxy.getClient(client);
HTTPConduit conduit = (HTTPConduit) proxy.getConduit();
TLSClientParameters tls = conduit.getTlsClientParameters();
TrustManager[] trustManagers = tls.getTrustManagers();  // trustManagers is null

Is there anything else that I need to do to get the Apache CXF client to trust the self-signed certificate?

I prefer to not have to specify the path to a truststore along with a password in the configuration file.

Thank you!

Answer

Kjetil &#216;degaard picture Kjetil Ødegaard · Jun 13, 2012

CXF is probably using the wrong SSL socket factory.

Try adding this to your Spring config:

<http-conf:conduit name="*.http-conduit">
    <http-conf:tlsClientParameters useHttpsURLConnectionDefaultSslSocketFactory="true"/>
</http-conf:conduit>