Sunday, July 29, 2012

Consuming "HTTPS" Web Services in Java

Recently we had a requirement to consume a Secure web service (i.e. SSL enabled endpoint). This is quite common requirement that may interest many of you. I would not be surprised if you find terms like HTTPS, SSL, Certificates, KeyStore, TrustStore, etc. scary. I too didn't understand most of these terms till few years ago.

So let me first give a brief (unofficial) explanation of some of these scary terms.
  • SSL (Secure Socket Layer) is a protocol to encrypt information.
  • HTTPS is nothing but HTTP + SSL. HTTPS ensures that the information being transferred over HTTP is secured from theft.
  • SSL Certificate contains Public Key + Identity information of the website/company which is verified by the Certification authority (visit Reference #3, #4 if you don't understand this).
  • TrustStore: file that contains the server certificates that are required by JVM for accepting SSL connections with trusted servers (simply: to trust outbound connections).
  • KeyStore: file that contains client certificates that are required by JVM for establishing an SSL connection with a server that requires client certificate authentication.

Note: Technically, there is no difference between TrustStore & KeyStore. They both are essentially used for storing SSL Certificates.

Enough background? Okay! Time to go back to the original topic!

Here is a logical diagram of the process of consuming HTTPS enabled Web Services:
Oversimplified diagram of Java Client to consume Secure Web Service


Important: You don't need to change your java program to consume a SECURE web service Vs. a NON-SECURE web service.

You just need to import the SSL Certificate of the Secure Web Service to the TrustStore using a JVM tool called "keytool" (I will not go into the steps of importing certs using keytool).

JVM comes with a Certificate Store called 'cacerts'. It resides in "\jre\lib\security\cacerts". 'cacerts' is JVM's default TrustStore as well as default KeyStore. 

You can also create your own Certificate Store using "keytool". If you are using your own TrustStore instead of using 'cacerts', you have to inform JVM to look into it while searching for certificates using below property:
java -Djavax.net.ssl.trustStore=.\key.jks
If your Web Service client is a web application, then you need to set this property for your Web server's JVM. For example, I modified tomcat's setenv.bat file to add this JVM property:

set "JAVA_OPTS=... -Djavax.net.ssl.trustStore=%CATALINA_HOME%/trustStore/key.jks"


Isn't it easier than you thought it would be? :-)



References:
  1. http://ws.apache.org/xmlrpc/ssl.html
  2. http://www.eu-sol.net/science/bioinformatics/tutorials/secure-biomoby-web-services/how-to-call-a-secure-web-service 
  3. http://info.ssl.com/article.aspx?id=10241
  4. http://www.symantec.com/theme.jsp?themeid=how-ssl-works

6 comments:

Shaj said...

Good simple explanation! A picture is worth a thousand words!!

Rushikesh S. Thakkar said...

Thank you! Appreciate your feedback..

Fortune said...

Well explained ! There's just something i wonder about the certificates.

If i import my SSL certificate with the keytool, it will just work for me right ?

Or is the truststore coming with the application on the build ?

Thanks in advance and again, nice tutorial.

Rushikesh S. Thakkar said...

Hi Fortune,
Thanks for your kind feedback. I couldn't quite understand your question. Can you please elaborate?

Unknown said...

Hi Rushi,

i m facing an issue while updating the client certificates. I have many client modules for different service providers in my application and i m looking to update the certificate for one specific module say ABC.

Can anyone please help. And any inputs on how to enable the SOAP request and response logging would be really appreciated.

Rushikesh S. Thakkar said...

Hi Nishant, Sorry for such a late reply.
Regarding your first question, check out documentation of Keytool. Using keytool, add certificates to the default truststore of the jvm that your application is using.

Regarding soap request/response logging, you can use either tcpmon utility of Apache Axis or use your webservice framework's own method of logging soap messages.

HTH!