I'm a new user to REST services. I need to consume a RESTful API service generated with Jersey. The problem comes because that service is hosted on remote host and it requires https access with certificate.
I got my certificate from the organization and i'm able to access that REST API service with any of my browsers (with certificate set on them).
I've read lot of posts over here, and I've followed the answer on this topic: Using HTTPS with REST in Java
Now I've my certificate setup on my Java Keystore. But i don't know how to use that on my Java program so it uses exactly the certificate i need to do the https connection.
This is my simple connection code for local tests.
package rest.test.first;
import java.net.URI;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
public class TestClient{
public static void main(String[]args){
ClientConfig config= new DefaultClientConfig();
Client client=Client.create(config);
WebResource service=client.resource(getBaseURI());
//Fluentinterfaces
System.out.println(service.path("rest").path("hello").accept(MediaType.TEXT_PLAIN).get(ClientResponse.class).toString());
//Getplaintext
System.out.println(service.path("rest").path("hello").accept(MediaType.TEXT_PLAIN).get(String.class));
//GetXML
System.out.println(service.path("rest").path("hello").accept(MediaType.TEXT_XML).get(String.class));
//TheHTML
System.out.println(service.path("rest").path("hello").accept(MediaType.TEXT_HTML).get(String.class));
}
private static URI getBaseURI(){
return UriBuilder.fromUri("http://localhost:8080/rest.test").build();
}
}
I'v read about using system set properties to specify path to keystore with this code:
System.setProperty("javax.net.ssl.keyStore", "/path/to/keystore.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "password");
I still get 401 Error on connection to the remote server.
But then i don't know how to make SSL connection using my certificate on keystore. I've been also reading about using sslSocketFactory for this purpose but i couldn't make it work as explained on this post: How can I use different certificates on specific connections?
I've managed to retrieve my cert from keystore with this code.. now I just need to know how to use it in connection:
package rest.test.first;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.cert.Certificate;
public class keystore {
public static void main(String[] args) throws Exception {
String keystoreFilename = "/usr/lib/jvm/jdk1.6.0_32/jre/lib/security/cacerts";
char[] password = "changeit".toCharArray();
String alias = "remote_https_server";
FileInputStream fIn = new FileInputStream(keystoreFilename);
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(fIn, password);
Certificate cert = keystore.getCertificate(alias);
System.out.println(cert);
}
}
Ok that's the last script I've wrote. I can connect to https sites but i still can't connect to https sites which require to send my certificate to authenticate.
package rest.test.first;
import java.io.*;
import java.net.*;
import java.security.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
public class urlConnection{
public static void main(String args[]) throws Exception {
System.setProperty("javax.net.ssl.trustStore", "/usr/lib/jvm/jdk1.6.0_32/jre/lib/security/cacerts");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
//TrustStore..
char[] passphrase = "changeit".toCharArray(); //password
KeyStore keystore = KeyStore.getInstance("JKS");
//KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(new FileInputStream("/usr/lib/jvm/jdk1.6.0_32/jre/lib/security/cacerts"), passphrase); //path
//TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); //instance
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keystore);
SSLContext context = SSLContext.getInstance("TLS");
TrustManager[] trustManagers = tmf.getTrustManagers();
context.init(null, trustManagers, null);
SSLSocketFactory sf = context.getSocketFactory();
URL url = new URL("https://www.google.es");
HttpsURLConnection httpsCon = (HttpsURLConnection) url.openConnection();
httpsCon.setSSLSocketFactory(sf);
httpsCon.setRequestMethod("GET");
/*InputStream inStrm = httpsCon.getInputStream();
System.out.println("\nContent at " + url);
int ch;
while (((ch = inStrm.read()) != -1)){
System.out.print((char) ch);
inStrm.close();
}*/
System.out.println("Response Message is " + httpsCon.getResponseMessage());
}
}
cacerts
truststore? I would suggest importing your certificate into its own JKS and using that in the call toSystem.setProperty("javax.net.ssl.keyStore", "...")
. – Liquor