3

Following code snippet is to get JSon response from a HTTP URL:

private static void getJson(String location) {
    try {
        try {
            createSSLSocket();
            URL url = new URL(
                    "https://abc.com/key/one");
            HttpURLConnection conn = (HttpURLConnection) url
                    .openConnection();
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Accept", "application/json");
            if (conn.getResponseCode() != 200) {
                throw new RuntimeException("Failed : HTTP error code : "
                        + conn.getResponseCode());
            }
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    (conn.getInputStream())));
            String output;
            System.out.println("Output from Server .... \n");
            while ((output = br.readLine()) != null) {
                System.out.println(output);
            }
            conn.disconnect();

        } catch (MalformedURLException e) {
            e.printStackTrace();

        } catch (IOException e) {
            e.printStackTrace();

        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }

}

But it is throwing SSLHandshaking exception because i didn't added self signed certification exception to the code. I have done this in C# but not in java. What steps should i perform? Need your suggestion :)

Thanks in advance.

Amit Pal
  • 10,604
  • 26
  • 80
  • 160
  • Do you mean that the server certificate is self-signed and that's why the connection failed? What is the failure reason contained in the SSLHandshakeException? – Jcs Dec 07 '13 at 16:56
  • @jcs Yes the server side connection is self signed and here is the error:`unable to find valid certification path to requested target` – Amit Pal Dec 07 '13 at 16:59
  • @Jcs can we do it progammatically? – Amit Pal Dec 07 '13 at 17:03
  • Yes, I added an answer with a code snippet. – Jcs Dec 07 '13 at 17:27

2 Answers2

4

To add trust for a self signed certificate, you can create a truststore java keystore file and set the javax.net.ssl.trustStore property to point at this file. The openConnection method will check the truststore to see if the certificate can be trusted.

To create a truststore file you can use the keytool command which is part of the JDK and should be in your JAVA_HOME/bin directory.

keytool -import -file yourcert.cert -alias abc -keystore truststore.jks

The command will prompt you for a password which you will need if you want to edit the truststore. After entering the password it will create a truststore.jks file. To programmatically set the truststore in Java you can either pass it as a property with -Djavax.net.ssl.trustStore=/path/truststore.jks or you can call System.setProperty

System.setProperty("javax.net.ssl.trustStore", "/path/truststore.jks");

To have a look at ssl properties used by Java have a look here.

cyon
  • 9,340
  • 4
  • 22
  • 26
3

You can configure the HttpsURLConnection socket factory to accept all certificate without any validation:

private class TrustAll implements X509TrustManager
{
    public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException
    {
    }

    public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException
    {
    }

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

SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, new TrustManager[] { new TrustAll() }, null);
HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());

UPDATE

You just have to call this code once at the start of the application. All HTTPS connections opened with URL.openConnection() will use this socket factory. Another solution could be adding this code in the createSSLSocket() method body.

Jcs
  • 13,279
  • 5
  • 53
  • 70