4

I am updating the web service URL of the android application, we are using https protocol. I see that my current https URL is working but now we are migrating to new domain then it is creating problem.

I have checked many threads on stackoverflow like javax.net.ssl.SSLException: hostname in certificate didn't match android but didn't find any good answer mostly are answering bypass this security or allow all.

javax.net.ssl.SSLException: hostname in certificate didn't match:

//HttpGet getMethod = new HttpGet(String.format(httpURL));
HttpGet getMethod = new HttpGet(httpURL);
DefaultHttpClient client = new DefaultHttpClient();
ResponseHandler<String> responseHandler = new BasicResponseHandler();
HttpParams params = client.getParams();
params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 60000);
params.setParameter(CoreConnectionPNames.SO_TIMEOUT, 60000);
client.setParams(params);
responseBody = client.execute(getMethod, responseHandler);
responseBody = responseBody.trim();

Thanks in advance.

Community
  • 1
  • 1
N Sharma
  • 33,489
  • 95
  • 256
  • 444

3 Answers3

7

It seems that the best solution to this is to use HttpsUrlConnection instead of HttpGet.

URL url = new Url(httpURL);
HttpURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setReadTimeout(60000);
urlConnection.setConnectTimeout(60000);
urlConnection.setRequestMethod("GET");
urlConnection.setDoInput(true);

urlConnection.connect();

Then use InputStream to get the response body.

InputStream inputStream = urlConnection.getInputStream();
mattfred
  • 2,689
  • 1
  • 22
  • 38
5

If it works in the browser but not in the app it might be a problem with missing SNI support, see Why does android get the wrong ssl certificate? (two domains, one server).

Community
  • 1
  • 1
Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • Yes it is working in the browser not in the app. Do we have to keep some certificate also in the app also for this ssl connection ? – N Sharma Oct 05 '14 at 09:37
  • No, you have to use something which supports SNI or you have to have a separate IP address for the HTTPS server, so that you don't need to use SNI. See the linked question for more details. – Steffen Ullrich Oct 05 '14 at 10:58
2

Thanks to Make HTTPS / HTTP Request in Android

Add a Java class CustomSSLSocketFactory.java

 import java.io.IOException;
 import java.net.Socket;
 import java.net.UnknownHostException;
 import java.security.KeyManagementException;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
 import java.security.UnrecoverableKeyException;
 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 CustomSSLSocketFactory extends SSLSocketFactory{
SSLContext sslContext = SSLContext.getInstance("TLS");
/**
 * Generate Certificate for ssl connection
 * @param truststore
 * @throws NoSuchAlgorithmException
 * @throws KeyManagementException
 * @throws KeyStoreException
 * @throws UnrecoverableKeyException
 */
public CustomSSLSocketFactory(KeyStore truststore)
        throws NoSuchAlgorithmException, KeyManagementException,
        KeyStoreException, UnrecoverableKeyException {
    super(truststore);
    TrustManager tm = new X509TrustManager(){
        @Override
        public void checkClientTrusted(X509Certificate[] arg0, String arg1)
                throws CertificateException {
        }
        @Override
        public void checkServerTrusted(X509Certificate[] chain,
                                       String authType) throws CertificateException {
        }
        @Override
        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();
}
 }

in your code

    String cloud_url="https://www.google.com";
    HttpClient client = new DefaultHttpClient();
        if(cloud_url.toLowerCase().contains("https://")){
            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            trustStore.load(null, null);
            SSLSocketFactory sf = new CustomSSLSocketFactory(trustStore);
            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

            HttpParams params = new BasicHttpParams();
            SchemeRegistry registry = new SchemeRegistry();
            registry.register(new Scheme("https", sf, 443));

            ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
            client= new DefaultHttpClient(ccm, params);
        }


        HttpGet request= new HttpGet( );
        request.setURI(new URI( cloud_url));
        HttpResponse response = client.execute(request);
Joshy Francis
  • 340
  • 7
  • 13