Tuesday 20 December 2016

POST request with android on https page with htaccess



I've been looking quite everywhere and the infos I have found didn't worked with my case.
Could someone help me please with this :
I need to send a POST request to a specific url on a server with an Android application.
The target page is using https encryption and is protected by an htaccess.
Last things : the server listen on a random port like 14000 and in the certificate the hostname is different from the hostname's url.
I know that is quite challenging but nothing i've tried is working.

Curently i try this :



private void process() {
new Thread(new Runnable() {
public void run() {
String httpsURL = "https://login:password@z-cloud.z-wave.me/ZWaveAPI/Data/0";
HttpResponse httpResponse;
HttpPost httpQuery = new HttpPost(httpsURL);
CustomHttpClient myClient = new CustomHttpClient(myContext);
Log.v("exec", "ready...");

try {
httpResponse = myClient.execute(httpQuery);
if (httpResponse.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_OK) {
Log.v("exec", "it works ?");
}
Log.v("exec", httpResponse.getStatusLine().getStatusCode()+"");
} catch (Exception ex) {
Log.d("httpError", ex.getMessage());
}
}

}).start();
}


and the CustomHttpClient class :



public class CustomHttpClient extends DefaultHttpClient {

private static Context appContext = null;
private static Scheme httpsScheme = null;

private static Scheme httpScheme = null;
private static String TAG = "MyHttpClient";

public CustomHttpClient(Context myContext) {

appContext = myContext;

if (httpScheme == null || httpsScheme == null) {
httpScheme = new Scheme("http", PlainSocketFactory.getSocketFactory(), 80);
httpsScheme = new Scheme("https", mySSLSocketFactory(), 14000);

}

getConnectionManager().getSchemeRegistry().register(httpScheme);
getConnectionManager().getSchemeRegistry().register(httpsScheme);

}

@SuppressWarnings("finally")
private SSLSocketFactory mySSLSocketFactory() {
SSLSocketFactory ret = null;

try {
final KeyStore ks = KeyStore.getInstance("BKS");

final InputStream inputStream = appContext.getResources().openRawResource(R.raw.certs);

ks.load(inputStream, appContext.getString(R.string.store_pass).toCharArray());
inputStream.close();
ret = new SSLSocketFactory(ks);
ret.setHostnameVerifier(myhostnameVerifier);
} catch (UnrecoverableKeyException ex) {

Log.d(TAG, ex.getMessage());
} catch (KeyStoreException ex) {
Log.d(TAG, ex.getMessage());
} catch (KeyManagementException ex) {
Log.d(TAG, ex.getMessage());
} catch (NoSuchAlgorithmException ex) {
Log.d(TAG, ex.getMessage());
} catch (IOException ex) {
Log.d(TAG, ex.getMessage());
} catch (Exception ex) {

Log.d(TAG, ex.getMessage());
} finally {
return ret;
}
}

X509HostnameVerifier myhostnameVerifier = new X509HostnameVerifier() {

@Override
public void verify(String arg0, SSLSocket arg1) throws IOException {

Log.v("X509", "verified "+arg0);
if("z-cloud.z-wave.me" != arg0)
{
//throw new SSLException("Mismatching hostname");
}
}

@Override
public void verify(String arg0, X509Certificate arg1)
throws SSLException {

Log.v("X509", "called 2");
}

@Override
public void verify(String arg0, String[] arg1, String[] arg2)
throws SSLException {
Log.v("X509", "called 3");
}

@Override

public boolean verify(String host, SSLSession session) {
Log.v("X509", "called 4");
return false;
}
};
}


I don't know why but i'm getting an error 401 but m'y login and password are good.
I'm not really sure that the certificate i use is correct, but do i really need it ?

Please help me, i'm getting really tired trying to send a simple post request...


Answer



The best way to do this is indeed to use a custom TrustStore containing the server's certificate. It's probably not necessary to validate the hostname - the certificate should be all that's needed.



Rather than trying to debug your code, I'll point you to a blog posting that I did a while back that has a full working example of how to do this. Take a look at http://blog.chariotsolutions.com/2013/01/https-with-client-certificates-on.html



Edit - the example shows how to use a client certificate, which you don't need - just ignore that part.


No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...