Connect over secure rest web service for mobile application on android

In the last article, we developed application for android to get the data from rest web service (geo-names). Previous approach works fine for http rest web service but it doesn’t work over SSL secure connection. We were developing android application for a client whose rest web services are running over secure connection. Initially we thought it would be much simple to connect to secure rest web service because we already have the framework to connect to http connection. When we use it and there was exception “javax.net.ssl.SSLException: Not trusted server certificate” all over the application.
We didn’t loose our patience and asked our truly friends google and stackoverflow. We found various solution to intercept the connection and use self certificate but we wanted a solution which just by pass the authorization of the certificates. After checking various sites and reading the article, we found a solution which fit our requirements.

Create Easy SSL Socket Factory and create httpclient instance

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.conn.ssl.SSLSocketFactory;
public class EasySSLSocketFactory extends SSLSocketFactory {
        SSLContext sslContext = SSLContext.getInstance("TLS");

        public EasySSLSocketFactory(KeyStore truststore)
                        throws NoSuchAlgorithmException, KeyManagementException,
                        KeyStoreException, UnrecoverableKeyException {
                super(truststore);

                TrustManager tm = new X509TrustManager() {
                        public void checkClientTrusted(X509Certificate[] chain,
                                        String authType) throws CertificateException {
                        }

                        public void checkServerTrusted(X509Certificate[] chain,
                                        String authType) throws CertificateException {
                        }

                        public X509Certificate[] getAcceptedIssuers() {
                                return null;
                        }
                };

                sslContext.init(null, new TrustManager[] { tm }, null);
        }

        @Override
        public Socket createSocket(Socket socket, String host, int port,
                        boolean autoClose) throws IOException, UnknownHostException {
                return sslContext.getSocketFactory().createSocket(socket, host, port,
                                autoClose);
        }

        @Override
        public Socket createSocket() throws IOException {
                return sslContext.getSocketFactory().createSocket();
        }

}

We shall be using this ssl socket factory to access the secure connection to rest web service.

import java.security.KeyStore;

import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;

public class HttpUtils {
        public static HttpClient getNewHttpClient() {
            try {
                KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
                trustStore.load(null, null);

                SSLSocketFactory sf = new EasySSLSocketFactory(trustStore);
                sf.setHostnameVerifier(
                       SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

                HttpParams params = new BasicHttpParams();
                HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
                HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

                SchemeRegistry registry = new SchemeRegistry();
                registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
                registry.register(new Scheme("https", sf, 443));

                ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

                return new DefaultHttpClient(ccm, params);
            } catch (Exception e) {
                return new DefaultHttpClient();
            }
        }
}

Back to our original rest client code

// Create a new RestTemplate instance
				RestTemplate restTemplate = new RestTemplate();

				// The HttpComponentsClientHttpRequestFactory uses the
				// org.apache.http package to make network requests
				restTemplate
						.setRequestFactory(new HttpComponentsClientHttpRequestFactory(
								HttpUtils.getNewHttpClient()));

				// The URL for making the GET request
				final String url = "https://xxx.xxx.xxx.xxx";
                                // Initiate the HTTP GET request, expecting an array of
				// objects in response
				Object result = restTemplate.getForObject(url, Object.class);

Finally we were able to make connection over secure rest web service android application.

Feel free to comment or ask questions.

Useful resources

Connect over secure rest web service for mobile application on android was last modified: March 7th, 2016 by Kapil Jain