I am attempting to connect to a local HTTPS server using the apache DefaultHttpClient on a Android device.
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://192.168.1.121:4113/services");
... header and content filling in ...
HttpResponse response = httpclient.execute(httppost);
I am getting an error of "javax.net.ssl SSLException: Not trusted server certificate" when the .execute runs. I want to simply allow any certificate to work, regardless of if it is or is not in the android key chain.
I have spent about 40 hours researching and trying to figure out a workaround for this issue. I have seen many examples of how to do this but none so far have worked in Android; they seem to only work for JAVA. Does anyone know how to configure, or override the certificate validation used by the Apache HttpClient in Android so that it will just approve all certificates for a DefaultHttpClient connection?
I thank you for your kind response
If anyone is still trying to figure this out I ended up going with the solution here:
HTTPS GET (SSL) with Android and self-signed server certificate
Scroll down to the solution by SimonJ. It is a simple straight forward solution to this problem.
Look at this tutorial http://blog.antoine.li/index.php/2010/10/android-trusting-ssl-certificates/
The tutorial is based on Apache's HttpClient and explains how to use the SSLSocketFactory to trust the defined certificates in your own keystore (also explained how you can create it with the BouncyCastle provider).
I've tested it and it works great. In my opinion this is the secure way.
Related
I know that this question is answered several times but i couldn't figure out how should i do this.
How should i send critical information like passwords etc. My Host provider grants SSL certification.
Should i do it with HttpPost or it needs to be more secured.
Here is my POST snippet.
HttpPost post = new HttpPost("http://example.com/");
NameValuePair[] data = {
new NameValuePair("a", "b"),
new NameValuePair("c", "d")
};
post.setRequestBody(data);
InputStream in = post.getResponseBodyAsStream();
Any help would be appreciated.
You are confusing the request type (POST, GET, etc) with the transport method (HTTP, HTTPS).
If you have been provided with an SSL cert you should set your server up to listen on a secure connection (usually 443 for HTTPS, but not necessarily for a server).
Your calls should then be routed to https://[your_server]/. They will then be secure.
And really, you should look into using a library for making requests. You are probably going to hit the 'network traffic on the main thread' warning quite soon. Look into 'Fast Android Networking' or 'Volley'.
Recently I acquired a new domain name to use with an existing Android application. I also bought SSL certificate from a trusted CA (Comodo). When I browse to the new domain with a web browser, everything works as expected - no errors about SSL certificate. Same with HttpUrlConnection, but for some reason Apaches HttpClient generates an SSLException:
javax.net.ssl.SSLException: hostname in certificate didn't match: my.new.domain != my.old.domain OR my.old.domain
What's more interesting, some of the devices that I tried with worked fine for about a week after the change, and stopped working after that. Other devices stopped working right away.
If I use the old domain name in client code, everything works correctly.
I'm using version 4.3.3 from here of the HttpClient for Android. I realize that converting to HttpUrlConnection would indeed solve my problem, but I'm interested in WHY this is happening - from where does the HttpClient pick up the old domain name? Is it some misconfiguration on the server, or does Apaches HttpClient have some sort of internal dns cache? Testing with a fresh emulator instance raised the same exception, so the problem is not related to caching.
My own investigations got stuck - all I could find was instructions for disabling hostname verification completely, or instructions for self-signed certificates.
That's probably because Apache HttpClient does not support SNI (server name indication), where you can have multiple certificates behind the same IP address. This means, that it does not send the target hostname inside the SSL handshake and thus the server has only the target IP address to decide which certificate it should use and just uses the default certificate for the IP - which is probably the wrong one.
I'm trying to hit an https url with my app. I've followed this tutorial. The store I've created has the correct CA. However, when I try to make the connection, I get the following error:
ERROR/IOException(1843): webPost: javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
I've done some reading about this error and people have decided to allow their apps to accept all certificates. I don't think that's really acceptable. What should I check next to see what the issue is?
You can configure your device to ignore SSL certificates:
http://www.virtualzone.de/2011-02-27/how-to-use-apache-httpclient-with-httpsssl-on-android/(dead link)
UPDATE: Much better answer is visible here:
Trusting all certificates using HttpClient over HTTPS
Or do things specific to your HttpClient version:
HttpGet with HTTPS : SSLPeerUnverifiedException
I'm using the Apache HttpClient library to setup a https connection. Unfortunately Android gives me a "Not trusted server certificate" error. If I browse to the site with the phone's browser it validates the certificate correctly, which leads me to believe that I need to make the HttpClient 'aware' of the root certificates on the phone. This is my HttpClient setup code:
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout( params, 20000 );
HttpConnectionParams.setSoTimeout( params, 20000 );
HttpProtocolParams.setVersion( params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset( params, HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue( params, false);
SchemeRegistry schReg = new SchemeRegistry();
schReg.register( new Scheme( "http", PlainSocketFactory.getSocketFactory(), 80 ) );
schReg.register( new Scheme( "https", SSLSocketFactory.getSocketFactory(), 443 ) );
ClientConnectionManager conMgr = new ThreadSafeClientConnManager( params, schReg );
DefaultHttpClient defaultHttpClient = new DefaultHttpClient( conMgr, params );
return ( defaultHttpClient );
As you can see I do nothing special with the SSLSocketFactory. How can I make the HttpClient library validate my site without adding a custom certificate in the keystore?. Should I create a custom SSLSocketFactory and load the cacerts.bks from the Android phone? In that case I might get problems with different passwords for the keystore on different phones?
Please let me know if you need further information. This SSL stuff is pretty difficult for me.
I believe your certificate doesn't contain all intermediate certificates necessary to validate path to a system trusted root certificate. It can be reported as incomplete certificate chain by some SSL config validation tools.
A certificate can contain a special Authority Information Access extension (RFC-3280) with URL to issuer's certificate. Most browsers can use the AIA extension to download missing intermediate certificate to complete the certificate chain. But some clients (mobile browsers, OpenSSL) don't support this extension, so they report such certificate as untrusted.
You can solve the incomplete certificate chain issue manually by concatenating all certificates from the certificate to the trusted root certificate (exclusive, in this order), to prevent such issues. Note, the trusted root certificate should not be there, as it is already included in the system’s root certificate store.
You should be able to fetch intermediate certificates from the issuer and concat them together by yourself. I have written a script to automate the procedure, it loops over the AIA extension to produce output of correctly chained certificates. https://github.com/zakjan/cert-chain-resolver
Following up on zakjan's answer, I had a problem when I tried to use jquery to do an AJAX request on my newly secure server, in an android webview. It worked in the browser, but not in my app.
I used this site: https://certificatechain.io/
I pasted in the text of my signed .crt file I got back from Comodo (positiveSSL), and it gave me back a concatination of everything I needed. I saved it as my domain + "chain.crt" (see below)
Then, in my apache configs, I entered something like this for that particular virtual host:
SSLEngine On
SSLCertificateFile /etc/ssl/localcerts/example_com.crt
SSLCertificateKeyFile /etc/ssl/localcerts/example.com.key
SSLCACertificateFile /etc/ssl/localcerts/example.com.chain.crt
After that, my Android app's webview did not have a problem using ajax to POST to my server. I tried it on 2 real-world devices, one running 2.3.4, one running 4.something. And on the emulator running 2.3. All worked.
I hope this helps.
i have same problem before..
you can use this answer, it works for me nicely..
Trusting all certificates using HttpClient over HTTPS
I am developing an app in Android, and the emulator is not connecting to my localhost.
I have researched the issue and found some ideas but nothing seems to be working.
Below is the code i have been using:,
HttpClient httpclient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("http://10.0.2.2/YES_BUTTON.php");
httpclient.execute(httpPost);
I have also tried a connection using "http://10.0.2.2:3128/YES_BUTTON.php";
The code would run a php file, but nothing happens, I have also checked the server access log and no connection was ever made with the Apache server from the emulator.
This is my first time building an app, and was wondering if there was something I haven't done, do I need to map the emulator port with the 3128 port on Apache, disable the firewall? I am developing the app on a laptop,with the Apache Server on the laptop also, so everything is being done on the same machine. Is there anything I havent done that needs to be done?
I bet you forgot to add the INTERNET permission :)
INTERNET