Thursday, September 30, 2010

Calling SSL enabled CXF Web Service From Java Client

Calling a SSL enabled service which also expects UserToken to be passed can be very frustrating. It has been really painful for me to consume SSL enabled CXF service and I spent nearly 1 week to get it working.


Environment
Apache Tomcat 6.0.28
JDK 1.6
CXF 2.2.3
IBM Rational Developer 7.5.2
Spring Web 2.5.6


We deployed the CXF Web Service with SSL and installed the security certificate (self signed) on the client machine.

I was able to view the WSDL coming in the browser but the problem started when I tried to call Web Service from Java Client. I was getting “Message could not sent”. I set the proxy in RAD and imported the client certificate in the JVM. Configured following JVM arguments:

-Djavax.net.ssl.trustStore="C:\Program Files\IBM\SDP\jdk\bin\mykeystore"
-Djavax.net.ssl.trustStorePassword="password"

But this configuration did not change the error message.

My next attempt was to configure proxy arguments in addition to the above JVM arguments for my program

-Djavax.net.ssl.trustStore="C:\Program Files\IBM\SDP\jdk\bin\mykeystore"
-Djavax.net.ssl.trustStorePassword="password"
-Dhttp.proxyHost=yourproxy
-Dhttp.proxyPort=8080
-Dhttps.proxyHost=yourproxy
-Dhttps.proxyPort=8080

Now I started getting ‘SSLHandshakeException’, ‘javax.net.ssl.SSLHandshakeException: Couldn't find trusted certificate’ . It confirmed that the client was trying to use the certificate to reach Web Service but due to self signed certificate it was getting invalidated.

Then I found a link on internet which covered my problem scenario and suggested to accept whatever certificate your application is trying to use instead of JVM trying to validate it. I used following code to accept the certificate with out checking its validity and I was able to reach Web Service successfully.


import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.cxf.configuration.jsse.TLSClientParameters;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.frontend.ClientProxyFactoryBean;
import org.apache.cxf.transport.http.HTTPConduit;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public static void main(String[] args)
  {
ApplicationContext context = new ClassPathXmlApplicationContext("appcontext.xml");

InfoService client = (InfoService) context.getBean("client");
ClientProxyFactoryBean factory = new ClientProxyFactoryBean();
Client proxy = ClientProxy.getClient( client );
HTTPConduit conduit = (HTTPConduit) proxy.getConduit();
TLSClientParameters tcp = new TLSClientParameters();

//Creating Trust Manager
TrustManager[] trustAllCerts = new TrustManager[] {
      new X509TrustManager()
         {
          public java.security.cert.X509Certificate[] getAcceptedIssuers()
           {
              return null;
           }
          public void checkClientTrusted(
                                                      java.security.cert.X509Certificate[] certs, String authType)  {      }
             
          public void checkServerTrusted(
                                                       java.security.cert.X509Certificate[] certs, String authType)
{
     System.out.println("authType is " + authType);
     System.out.println("cert issuers");
     for (int i = 0; i < certs.length; i++) {
     System.out.println("\t" + certs[i].getIssuerX500Principal().getName());
     System.out.println("\t" + certs[i].getIssuerDN().getName());
                }
           }
    }
};
                           
                        
tcp.setTrustManagers(trustAllCerts);
conduit.setTlsClientParameters( tcp );

client.callWebServiceMethod();
  }
}

Resources used:


Read Posting from Daniel


4 comments:

Web Scraper said...

Thank you for inform me about Calling SSL enabled CXF Web Service From Java Client. It confirmed that the client was trying to use the certificate to reach Web Service but due to self signed certificate it was getting invalidated. Thanks a lot.......

Manjeet Singh Wadhwa said...

I am glad you liked the post. When I worked with CXF I had the SSL issue for a long time and I spent long time digging out the solution and when finally I got it working I thought to put it on my blog so that other professional can take some idea(solution).

OrionPax said...

Thanks a lot for sharing your solution, i have the same problem, did you try to consume a web service over https but build it with Axis or wcf?.
Any way thanks a lot. i will do more research

PD. sorry but English not is my mother tongue. :)

Manjeet Singh Wadhwa said...

Hi there, I tried consuming the web service over https from JAVA client and it worked.