Sunday, November 21, 2010

Enabling SSL for AXIS2 service and client

We often encounter the satuation where requirement is to consume webservice exposed on https. In this article we will investigate how to consume webservice exposed over https using axis2. First lets see how to enable SSL for AXIS2 services:

Enabling SSL on server side for AXIS2 in tomcat:

You really don't need to do much enable SSL for services deplyed in AXIS2. Just follow how to enable SSL in tamcat.Add following in Server.xml of tamcat.

<Connector
port="8443" maxThreads="200"
scheme="https" secure="true" SSLEnabled="true"
keystoreFile="test.jks" keystorePass="test123"
clientAuth="false" sslProtocol="TLS"/>


Use axis2 1.5.3 in which axis2.xml has https transportReceiver enabled by default, listening on 8443 port so you don't need any configuration change in axis2.xml.
<transportReceiver name="https"
class="org.apache.axis2.transport.http.AxisServletListener">
<parameter name="port">8443</parameter>
</transportReceiver>

Prior to this version of axis2 was using org.apache.axis2.transport.nhttp.HttpCoreNIOSSLListener as transportReceive which was having issues and not generating https endpoint correctly.

SSL on client side:

Axis2 uses http commons to transfer SOAP message over http. Apache http common uses JSSE(java secure socket extension) library for SSL.
JSSE is integrated with JDK since version 1.4.

Ideally if we just provide end point URL starting with https, SSL connection will be started and we don’t need any additional configuration. Creation of secure connection will be taken care by JSSE. But then trust store and keystore used by the JSSE would be default keystores shipped with JDK.

In the practical/production scenarios user should have capability to choose his truststore/keystore.
user may decide to trust a self signed certificate and keep it his local truststore or different applications may use different keystore/truststore.
Above can be achieved by two ways:
Approach 1:
We can set truststore, password etc in system properties. This will be picked by JSSE in SSL handshake.
Ex.
System.setProperty("javax.net.ssl.trustStore","Your truststore path");
System.setProperty("javax.net.ssl.trustStorePassword","your trust store password");
This approach will not be appropriate for tooling since it sets keystore on JVM level. We should have flexibility where we could attach different keystore/truststore for different axis2 clint running in same JVM.

Approach 2:
Apache commons provide facility which allows us to customize the SSL socket factory responsible for creation of secure socket. By customization I mean ability to use user truststore/keystore in SSL handshake. To achieve it we need to extend SecureProtocolSocketFactory interface. In our custom socket factory implementation user refer its Keystore/Truststore against default keystores.
Apache commons provide a reference implementation class named AuthSSLProtocolSocketFactory for this purpose.

This class takes Truststore/Keystore as argument to constructor which will be referred later while initiating SSLContext. SSLContext is used to create SSL Socket Factory.
In your axis2 client code you need to add following:
Protocol authhttps = new Protocol ("https", new AuthSSLProtocolSocketFactory (new url("keystore URL"), "pwd", newURL("truststore URL"), "pwd"), 443);
Protocol.registerProtocol("https", authhttps);

And you are all set to consume secure webservice.