title: Consuming RESTful service over https with certificate using Java
body: <p>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.</p>
  
  <p>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).</p>
  
  <p>I've read lot of posts over here, and I've followed the answer on this topic:
  <a href="https://stackoverflow.com/questions/1757295/using-https-with-rest-in-java">Using HTTPS with REST in Java</a></p>
  
  <p>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.</p>
  
  <p>This is my simple connection code for local tests.</p>
  
  <pre><code>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();
  }
  }
  </code></pre>
  
  <p>I'v read about using system set properties to specify path to keystore with this code:</p>
  
  <pre><code>System.setProperty("javax.net.ssl.keyStore", "/path/to/keystore.jks");
  System.setProperty("javax.net.ssl.keyStorePassword", "password");
  </code></pre>
  
  <p>I still get 401 Error on connection to the remote server.</p>
  
  <p>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: <a href="https://stackoverflow.com/questions/859111/how-do-i-accept-a-self-signed-certificate-with-a-java-httpsurlconnection">How can I use different certificates on specific connections?</a></p>
  
  <p>I've managed to retrieve my cert from keystore with this code.. now I just need to know how to use it in connection:</p>
  
  <pre><code>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);
        }
      }
  </code></pre>
  
  <p>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. </p>
  
  <pre><code>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());
  
   }
  }
  </code></pre>