Calling / Invoking Secure RESTful Web Service over HTTPS with JAX-RS in Java without Keystore & Truststore Information
Table of Content
- Introduction
- System Requirements
- Article Prerequisites
- Securing JAX-RS Clients using SSL
- Summary
- Downloads
- Resources
- 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.
System Requirements
- Java SE Development Kit (JDK) 6
- Jersey implements JAX-RS 1.1
- Eclipse IDE for Java EE Developers
- Third Party Server or Application Server running Java™ API for RESTful Web Services (JAX-RS) application, which you will invoke. Here in the article, I have used Hyperic HQ Enterprise Server for examples.
Article Prerequisites
- You must have setup all required tools and application as mentioned in article “Introduction, developing, implementing RESTful Web Services in Java”.
- Solid experience in Java Programming, including object-oriented Java and the Java streams model, is essential.
- Some experience with Java EE development, will be very helpful, but is not strictly required.
- Some experience with Eclipse.
- Experience or knowledge on RESTful Web Services. You can learn RESTful Web Service using article “Introduction, developing, implementing RESTful Web Services in Java”.
- I’ll assume that you’re comfortable installing Eclipse and Eclipse plugins.
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.
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:
[sourcecode language=’java’]
/**
* 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 Bhavesh Thaker
*
*/
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;
}
}
[/sourcecode]
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:
[sourcecode language=’java’]
/**
* 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 Bhavesh Thaker
*
*/
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
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();
}
}
}
[/sourcecode]
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.
Downloads
SecureRestClientDemo.zip contains the SecureRestClientDemo project we created in this tutorial.
Back to the top
Resources
- SecureRestClientDemo.zip contains the SecureRestClientDemo project we created in this tutorial.
- Read Presentation: RESTful Java Web Services With JAX-RS
- Read Article: Introduction, developing, implementing RESTful Web Services in Java
- Read Article: Sending / Transfering / Pushing Files in MultiParts / Chunks from Server to Client with RESTful Web Services in Java
- JSR 311- JAX-RS: Java API for RESTful Web Services.
- Project Jersey is the JAX-RS reference implementation.
- RESTful Web Services Developer’s Guide
- Architectural Styles and the Design of Network-based Software Architectures, by Roy Thomas Fielding
- Read chapter 5 of Roy Fielding’s dissertation, “Architectural Styles and the Design of Network-based Software Architectures.”
- Java API for XML Web Services (JAX-WS)
- JSR 224: Java API for XML-Based Web Services (JAX-WS) 2.0
- Web Application Description Language (WADL)
- Get more information about RFC 2616: Hypertext Transfer Protocol — HTTP/1.1
- Read the book RESTful Web Services.
- Download Restlet, the REST framework for Java.
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.
Hello resourceResponse gives error , Iwould like to use Raritan third party API but unable to call I have SSL issues ..
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.
The article is very nice….Thanks for the post…. Waiting for more information on JAX-RS secutrity
Thanks for knowledge sharing.Can you please publish an article for JAXRS or JAXWS security related.It is most usefull for me……
The article on secure REST web services is really good. Similar articles are really appreciated.
Thanks I did webserive without keystore and truststore.
I want to create webservice with keystore and truststore.
plz help me
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.
Thanks a lot !!, this was really useful.
awesome. it helped a lot!!