views:

2767

answers:

4

I'm trying to make Https connections on the Android phones, using HttpClient. Trouble is that since the certificate isn't signed I keep getting "javax.net.ssl.SSLException: Not trusted server certificate".

Now I've seen a bunch of solutions where you simply accept all certificates, but what if I want to ask the user? I want to get a dialog similar to that of the browser, letting the user decide to continue or not.

Preferably I'd like to use the same certificatestore as the browser. Any ideas?

+1  A: 

The default HTTPClient setup doesn't handle self signed certs. You will need to modify the SSL handling or use one of the prebuilt factories. The instructions for HTTPClient 3.x (bundled with Android can be found here.

http://hc.apache.org/httpclient-3.x/sslguide.html

Just scroll down the page until you get to "Customizing SSL in HTTPClient". For what you want to do you may well be able to just use the EasySSLProtocolSocketFactory also linked to from there. Customising is quite trivial though I haven't done it in a while.

Good luck

Pandalover
I don't know how this answer is accepted. HttpClient in Android doesn't have a getHostConfiguration method, which is what is used in all the examples in the link.http://developer.android.com/reference/org/apache/http/client/HttpClient.html
noah
A: 

I'm not sure about Android to be honest, but if it's similar enough to the way it works in Java, you can set the SSLContext with Apache Http Client 4. This should allow you to use your own TrustManager to achieve what you want.

(Note that the link on the previous (accepted) answer points to Apache Http Client 3, not 4: things have changed).

To do this in Java, once you've created your SSLContext, something along these lines should work in Java:

import org.apache.http.conn.ssl.SSLSocketFactory;
// ...

SSLSocketFactory sslSocketFactory = new SSLSocketFactory(sslContext);
SchemeRegistry schemeRegistry = new SchemeRegistry();
httpclient.getConnectionManager().getSchemeRegistry()
    .register(new Scheme("https", sslSocketFactory, 443));

Maybe it can work with Android...

Bruno
A: 

Below code works for me:


        HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;

        DefaultHttpClient client = new DefaultHttpClient();

        SchemeRegistry registry = new SchemeRegistry();
        SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
        socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
        registry.register(new Scheme("https", socketFactory, 443));
        SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
        DefaultHttpClient http = new DefaultHttpClient(mgr, client.getParams());

        HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);

Nikolay Moskvin
A: 

Also found a good tutorial.

This solution also doesn't compromise certificate checking and explains how to add the trusted certs in your own keystore. It uses HttpClient 4

http://blog.antoine.li/index.php/2010/10/android-trusting-ssl-certificates/

saxos