I'm using HttpClient on my android application to connect to my PHP API in the server. The problem is that everyone with the URL can access my MySQL database contents Using API, which is not a good thing. I have come across Cloudflare API shield but another problem is that there is no proper documentation or any information on how to implement it in android applications. I have attempted to modify my HttpClient request library code like below to make it work but the android application throws 403 Unexpected response code, I have tested the certificate in the browser it works but not in the android application HttpClient request.
This code is where I initialize the certificate.jks and pass it to SSLSocketFactory
private SSLSocketFactory newSslSocketFactory() {
try {
// Get an instance of the Bouncy Castle KeyStore format
KeyStore trusted = KeyStore.getInstance(KeyStore.getDefaultType());
// Get the raw resource, which contains the keystore with
// your trusted certificates (root and any intermediate certs)
InputStream in = context.getResources().openRawResource(R.raw.certificate);
try {
// Initialize the keystore with the provided trusted certificates
// Also provide the password of the keystore
trusted.load(in, "DummyPass".toCharArray());
} finally {
in.close();
}
// Pass the keystore to the SSLSocketFactory. The factory is responsible
// for the verification of the server certificate.
SSLSocketFactory sf = new SSLSocketFactory(trusted);
// Hostname verification from certificate
// http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
return sf;
} catch (Exception e) {
throw new AssertionError(e);
}
}
And here I pass the SSLSocketFactory to the registerer to pass it with parameters to the server.
public void execute() {
runner = new ProgressTask() {
@Override
protected ResponseData doInBackground(Void... params) {
DefaultHttpClient httpclient = new DefaultHttpClient();
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("https", newSslSocketFactory(), 443));
SingleClientConnManager mgr = new SingleClientConnManager(httpclient.getParams(), registry);
httpclient = new DefaultHttpClient(mgr, httpclient.getParams());
// Set verifier
HttpsURLConnection.setDefaultHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
try {
logging("URL: " + method + " " + url.toString(), DEBUG);
printHeaders();
printParams();
HttpRequestBase hrb = buildRequest();
HttpParams httpParams = httpclient.getParams();
HttpConnectionParams.setConnectionTimeout(httpParams, timeout);
HttpConnectionParams.setSoTimeout(httpParams, timeout);
HttpResponse response = httpclient.execute(hrb);
int responseCode = response.getStatusLine().getStatusCode();
BufferedInputStream bis;
if (response.getEntity() == null) {
String jsonString = "{\"status\":\"No server entity.\"}";
InputStream is = new ByteArrayInputStream(jsonString.getBytes());
bis = new BufferedInputStream(is, BUFF_SIZE);
} else {
bis = new BufferedInputStream(response.getEntity().getContent(), BUFF_SIZE);
}
StringBuilder sb = new StringBuilder();
byte[] buffer = new byte[BUFF_SIZE];
int bytesRead;
while ((bytesRead = bis.read(buffer)) > 0) {
sb.append(new String(buffer, 0, bytesRead, "UTF-8"));
}
bis.close();
ResponseData responseData = new ResponseData(responseCode, sb.toString().getBytes());
return responseData;
} catch (IOException e) {
logging("Error trying to perform request", ERROR, e);
if (requestListener != null) {
requestListener.onConnectionError(e);
}
} catch (URISyntaxException e) {
logging("Error parsing url", ERROR, e);
}
return null;
}
};
runner.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}