Calling / Invoking Secure RESTful Web Service over HTTPS with JAX-RS in Java without Keystore & Truststore Information

The article is written for/using J2SE 6, Jersey 1.1.4.1 and Eclipse IDE for Java EE Developers [Ganymede].

Table of Content

  1. Introduction
  2. System Requirements
  3. Article Prerequisites
  4. Securing JAX-RS Clients using SSL
  5. Summary
  6. Downloads
  7. Resources
  8. Feedback

Introduction

You are required to secure the communications between your Java™ API for RESTful Web Services (JAX-RS) application and clients that invoke the application by using Secure Sockets Layer (SSL) transport layer security. Java™ API for RESTful Web Services (JAX-RS) application might be running a Third Party Application running on same or different server. It is possbile that you are not aware of it’s Keystore & Truststore Information. For Example, in one of my projects, recently, we need to invoke Secure Java™ API for RESTful Web Services (JAX-RS) application over HTTPS on Thrid Party Server without having the information about Keystore & Truststore installed on that server. Now, what to do?

This post covers such scenario on how to Calling/Invoking Secure RESTful Web Service over HTTPS with JAX-RS in Java without Keystore & Truststore Information.

Back to the top

System Requirements

Back to the top

Article Prerequisites

Back to the top

Securing JAX-RS Clients using SSL

JAX-RS client programs can take advantage of transport security using Secure Socket Layer (SSL) in order to protect requests and responses from JAX-RS resources.

If you have configured your JAX-RS application to use an SSL channel for transport level security when starting REST resources, your JAX-RS client is required to use the SSL connection to enable the client to interact with a JAX-RS resource that is deployed in the Application Server environment. For example, if your JAX-RS application is configured to use basic authentication, it is a common practice to use SSL so that the user credentials are transported over secure connections.


Back to the top

Writing JAX-RS Clients

To get started we will create a simple Java Project in eclipse by selecting Project… > Java Project > Next > from the new toolbar menu. Alternatively, invoke the wizard using File > New > Project… > Java Project > Next >.

Name the project SecureRestClientDemo and press Next >.

Add Jersey Libraries to project.

Now, create the SecureRestClientTrustManager class. Use the File > New > Class wizard, put SecureRestClientTrustManager in the Name field, com.bhaveshthaker.restws.securerestclientdemo in the Package field and Finish the wizard. Replace the contents of the generated class with the following code:

/**
 * Copyright (c) 2008 - 2011 Bhaveshkumar Thaker [http://bhaveshthaker.com].  All rights reserved.
 */
package com.bhaveshthaker.restws.securerestclientdemo;

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.X509TrustManager;

/**
 * @author <a href="http://bhaveshthaker.com/">Bhavesh Thaker</a>
 * 
 */
public class SecureRestClientTrustManager implements X509TrustManager {

	@Override
	public void checkClientTrusted(X509Certificate[] arg0, String arg1)
			throws CertificateException {
	}

	@Override
	public void checkServerTrusted(X509Certificate[] arg0, String arg1)
			throws CertificateException {
	}

	@Override
	public X509Certificate[] getAcceptedIssuers() {
		return new X509Certificate[0];
	}

	public boolean isClientTrusted(X509Certificate[] arg0) {
		return true;
	}

	public boolean isServerTrusted(X509Certificate[] arg0) {
		return true;
	}

}

Now, create the SecureRestClient class. Use the File > New > Class wizard, put SecureRestClient in the Name field, com.bhaveshthaker.restws.securerestclientdemo in the Package field and Finish the wizard. Replace the contents of the generated class with the following code:

/**
 * Copyright (c) 2008 - 2011 Bhaveshkumar Thaker [http://bhaveshthaker.com].  All rights reserved.
 */
package com.bhaveshthaker.restws.securerestclientdemo;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;

import org.hyperic.hq.hqapi1.types.ResourceResponse;
import org.hyperic.hq.hqapi1.types.ResponseStatus;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
import com.sun.jersey.core.util.MultivaluedMapImpl;

/**
 * @author <a href="http://bhaveshthaker.com/">Bhavesh Thaker</a>
 * 
 */
public class SecureRestClient {

	private static final long serialVersionUID = 1L;

	/**
	 * 
	 */
	public SecureRestClient() {
	}

	private HostnameVerifier getHostnameVerifier() {
		return new HostnameVerifier() {
			@Override
			public boolean verify(String hostname,
					javax.net.ssl.SSLSession sslSession) {
				return true;
			}
		};
	}

	public synchronized long retrieveHqeResource(final String hqeServerIp,
			final String hqeServerUsername, final String hqeServerPassword,
			final String hqeResourceName) throws Exception {

		long resourceId = 0L;
		Client client = null;
		WebResource webResource = null;
		SSLContext sslContext = null;

		final String HQE_SECURE_BASE_URL = "https://" + hqeServerIp + ":"
				+ "7443" + "/hqu/hqapi1/";
		final String GET_RESOURCE_URL = "resource/get.hqu";

		SecureRestClientTrustManager secureRestClientTrustManager = new SecureRestClientTrustManager();
		sslContext = SSLContext.getInstance("SSL");
		sslContext
				.init(
						null,
						new javax.net.ssl.TrustManager[] { secureRestClientTrustManager },
						null);

		DefaultClientConfig defaultClientConfig = new DefaultClientConfig();
		defaultClientConfig
				.getProperties()
				.put(
						com.sun.jersey.client.urlconnection.HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,
						new com.sun.jersey.client.urlconnection.HTTPSProperties(
								getHostnameVerifier(), sslContext));
		client = Client.create(defaultClientConfig);
		client.addFilter(new HTTPBasicAuthFilter(hqeServerUsername,
				hqeServerPassword));
		webResource = client.resource(HQE_SECURE_BASE_URL).path(
				GET_RESOURCE_URL);

		// Create mulit valued map for hyperic hqe resource name.
		final MultivaluedMap<String, String> platformByNameParamsMap = new MultivaluedMapImpl();
		platformByNameParamsMap.add("platformName", hqeResourceName);
		platformByNameParamsMap.add("verbose", "true");
		platformByNameParamsMap.add("children", "false");

		// Invoke the HQE webservice securely to get the resource.
		final ResourceResponse resourceResponse = webResource.queryParams(
				platformByNameParamsMap).accept(MediaType.APPLICATION_XML)
				.type(MediaType.APPLICATION_XML).get(ResourceResponse.class);

		if (resourceResponse != null
				&& ResponseStatus.SUCCESS.equals(resourceResponse.getStatus())
				&& resourceResponse.getResource() != null) {
			// Retrieve the resourceId from get resource response.
			System.out.println("GET call's Response: "
					+ resourceResponse.getStatus());
			resourceId = resourceResponse.getResource().getId().longValue();
		} else {
			System.out.println("GET calls Resource Response: "
					+ resourceResponse.getStatus());
			System.out.println("GET calls FAILURE Resource Response's reason: "
					+ resourceResponse.getError().getReasonText());
		}

		// clean up.
		webResource = null;
		client.destroy();
		client = null;

		return resourceId;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		SecureRestClient src = new SecureRestClient();
		try {
			System.out.println("Hyperic HQE Resource Id is: "
					+ src.retrieveHqeResource("127.0.0.1", "hqadmin",
							"hqadmin", "ctunifiedcore30"));
		} catch (Throwable t) {
			t.printStackTrace();
		}
	}

}

Back to the top

Summary

We have defined a secure connection between the client and the target server using SSL to enable integrity and confidentiality of the communication between the JAX-RS application and our client.

Back to the top

Downloads

Downloads

SecureRestClientDemo.zip contains the SecureRestClientDemo project we created in this tutorial.

Back to the top

Resources

Back to the top

Feedback

I would like to hear from you! If you liked this tutorial, have some suggestions or even some corrections for me, please let me know. I track all user feedback in comments sections.

Back to the top

9 Comments

  1. Vikas says:

    Hello resourceResponse gives error , Iwould like to use Raritan third party API but unable to call I have SSL issues ..

    • shalu says:

      I am also getting the same error related to org.hyperic.hq.hqapi1
      Can someone please give the link for the hyperic jar to be downloaded.

  2. Ramalinga Reddy says:

    The article is very nice….Thanks for the post…. Waiting for more information on JAX-RS secutrity

  3. Ramanujam says:

    Thanks for knowledge sharing.Can you please publish an article for JAXRS or JAXWS security related.It is most usefull for me……

  4. srinivasan says:

    The article on secure REST web services is really good. Similar articles are really appreciated.

  5. Aditi says:

    Thanks I did webserive without keystore and truststore.
    I want to create webservice with keystore and truststore.
    plz help me

  6. gle says:

    That’s not secure at all. You are trusting just any server presenting any certificate.
    Since you do not enforce authentication of the server (the “enable integrity” part in your conclusion), you have no guarantee of confidentiality since you are an easy target of MITM attacks with this “trust everything” configuration.

  7. Sishant Kumar says:

    Thanks a lot !!, this was really useful.

  8. Seetha says:

    awesome. it helped a lot!!

Leave a Reply

Your email address will not be published. Required fields are marked *