skip to Main Content

Total newbie to SSL. I know I should use HTTPS SSL (/ TLS?) to send my data to my server from my client application. Or at least that’s what I want to do.

My previous implementation in Java used HttpURLConnection and looked something like this:

    HttpURLConnection conn = null;

    try
    {
        URL url = new URL(urlString);
        conn = (HttpURLConnection) url.openConnection();
        conn.setDoOutput(true);
        conn.setRequestMethod("POST");
        OutputStream os = conn.getOutputStream();
        OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
        osw.write(dataString);
        osw.flush();
        osw.close();
        os.close();
        conn.connect();

        if(conn.getResponseCode() != 200)
            throw new MyServerException();

        BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
        String output;
        StringBuilder sb = new StringBuilder();

        while ((output = br.readLine()) != null) {
            sb.append(output);
        }

        if(conn != null)
            conn.disconnect();

        return sb.toString();
    }
    catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    catch (ProtocolException e) {
        e.printStackTrace();
    }
    catch (MalformedURLException e) {
        e.printStackTrace();
    }
    catch (IOException e) {
        e.printStackTrace();
    }
    catch (Exception e) {
        e.printStackTrace();
    }
    finally {
        if(conn != null)
            conn.disconnect();
    }

    throw new MyServerException();

… and this works just fine. I found this web page which kind of suggests all I need to do is switch my HttpURLConnection to HttpsURLConnection and everything should work fine.

On the other hand, on my server’s cPanel I found a Lets Encrypt section which enabled me to apply certificates to my server domains.

Setting this up produced, amongst other things, PEM-Encoded Certificate and PEM-Encoded Issuer certificates.

But then I’m a bit stumped. Do I just assume my code above updated to use HttpsURLConnection works? How do I know it’s working. For example, if I remove the issued certificates from my cPanel, then the above code still works…

Things I’ve found out since posting

If I make my urlString a http it throws and exception, whereas if it’s an https address it does not, so that’s good I guess.

Also, this this post would suggest I am on the right track, as I’m not getting any errors as suggested there, and nobody has mentioned that way is the wrong way to do it.

Of possible interest, which actually points out that “SSL is now called Transport Layer Security (TLS),” which simplifies things already.

This looks like a great article. I also notice this mentions we have to set up SSL/TLS on the cPanel too, in addition to the Lets Encrypt option. Makes sense really, didn’t see that originally. More: Turns out Lets Encrypt is a free service which provides you with an automatic certificate to use, rather than buying one from a service provider. However, you can also sign your own certificates which are free, but then not “recognised” by any trusted Certificate Authority (CA).

2

Answers


  1. I’ve usually used method like make https url connection trust any certificate as follows.

    try {
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, new X509TrustManager[]{new X509TrustManager() {
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
    
            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
    
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
        }}, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
    } catch(NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch(KeyManagementException e) {
        e.printStackTrace();
    }
    

    And make a secure request to a server with certificates that do not have host name.

    HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    });
    

    Then, you can get a HttpURLConnection object as a HttpsURLConnection object.

    HttpURLConnection connection = null;
    try
    {
        URL _url = new URL(url);
        String scheme = _url.getProtocol();
    
        if(scheme.equals("https")) {
           connection = (HttpsURLConnection)new URL(url).openConnection();
        }
     }catch(...){} 
    
    Login or Signup to reply.
  2. Ok I finally worked this out after a full day altogether. Firslty SSL and TLS generally mean the same think, with TLS the replacement for the older SSL. Next up, to get a secure connection you need to install a certificate on your server. This is actually very easy via the cPanel. In fact I recommend using Lets Encrypt, which offers free certificates which last 90 days. You can automatically renew your certificates server side by setting up a crontab job, so not only are they free but they are also perpetual.

    Once your certificate is set up, you can establish a secure connection and POST using the following code:

        SSLContext sc = null;
        HttpsURLConnection conn = null;
    
        try {
            URL httpsURL = new URL(urlString);
            sc = SSLContext.getInstance("TLSv1.2");
            sc.init(null, null, new java.security.SecureRandom());
            conn  = (HttpsURLConnection) httpsURL.openConnection();
            conn.setSSLSocketFactory(sc.getSocketFactory());
    
            conn.setDoOutput(true);
            conn.setRequestMethod("POST");
            OutputStream os = conn.getOutputStream();
            OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
            osw.write(dataString);
            osw.flush();
            osw.close();
            os.close();
            conn.connect();
    
            if(conn.getResponseCode() != 200)
                throw new MyServerException();
    
            BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
            String output;
            StringBuilder sb = new StringBuilder();
    
            while ((output = br.readLine()) != null) {
                sb.append(output);
            }
    
            if(conn != null)
                conn.disconnect();
    
            return sb.toString();
        }
        catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        catch (KeyManagementException e) {
            e.printStackTrace();
        }
        catch (MalformedURLException e) {
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    
        if(conn != null)
            conn.disconnect();
    
        throw new MyServerException();
    

    Nice and easy really. Perhaps I also need some kind of host name verifier like @tommybee mentioned in his answer.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search