I have this method:
public static String getReportMetadata (String reportId, String sessionId, String url) throws Exception{
Map<String, Object> jsonValues = new HashMap<String, Object>();
jsonValues.put("reportID", reportId);
jsonValues.put("sessionID", sessionId);
JSONObject json = new JSONObject(jsonValues);
DefaultHttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url + GET_REPORT_METADATA_ACTION);
AbstractHttpEntity entity = new ByteArrayEntity(json.toString().getBytes("UTF8"));
entity.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
post.setEntity(entity);
HttpResponse response = client.execute(post);
return getContent(response);
}
that perform a HTTP
Post request which of-course I run using AsyncTask
to get data from the server.
My Question:
could some one please explain to me in a simple way what are the steps I need to perform to change this connection type to a secure connection(a.k.a using HTTPS
).
Only from android point of view (meaning the client application).
UPDATE: As suggested I have tried to change only the link and add https instead of http but it doesn't return an answer. As I understand I do need to get and store a self sign certificate in order to connect to server side
UPDATE2: The solution that works for me:
EasySSLSocketFactory:
public class EasySSLSocketFactory implements SocketFactory, LayeredSocketFactory {
private SSLContext sslcontext = null;
private static SSLContext createEasySSLContext() throws IOException {
try {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, new TrustManager[] { new EasyX509TrustManager(null) }, null);
return context;
} catch (Exception e) {
throw new IOException(e.getMessage());
}
}
private SSLContext getSSLContext() throws IOException {
if (this.sslcontext == null) {
this.sslcontext = createEasySSLContext();
}
return this.sslcontext;
}
/**
* @see org.apache.http.conn.scheme.SocketFactory#connectSocket(java.net.Socket, java.lang.String, int,
* java.net.InetAddress, int, org.apache.http.params.HttpParams)
*/
public Socket connectSocket(Socket sock, String host, int port, InetAddress localAddress, int localPort,
HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
int soTimeout = HttpConnectionParams.getSoTimeout(params);
InetSocketAddress remoteAddress = new InetSocketAddress(host, port);
SSLSocket sslsock = (SSLSocket) ((sock != null) ? sock : createSocket());
if ((localAddress != null) || (localPort > 0)) {
// we need to bind explicitly
if (localPort < 0) {
localPort = 0; // indicates "any"
}
InetSocketAddress isa = new InetSocketAddress(localAddress, localPort);
sslsock.bind(isa);
}
sslsock.connect(remoteAddress, connTimeout);
sslsock.setSoTimeout(soTimeout);
return sslsock;
}
/**
* @see org.apache.http.conn.scheme.SocketFactory#createSocket()
*/
public Socket createSocket() throws IOException {
return getSSLContext().getSocketFactory().createSocket();
}
/**
* @see org.apache.http.conn.scheme.SocketFactory#isSecure(java.net.Socket)
*/
public boolean isSecure(Socket socket) throws IllegalArgumentException {
return true;
}
/**
* @see org.apache.http.conn.scheme.LayeredSocketFactory#createSocket(java.net.Socket, java.lang.String, int,
* boolean)
*/
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException,
UnknownHostException {
return getSSLContext().getSocketFactory().createSocket(socket, host, port, autoClose);
}
// -------------------------------------------------------------------
// javadoc in org.apache.http.conn.scheme.SocketFactory says :
// Both Object.equals() and Object.hashCode() must be overridden
// for the correct operation of some connection managers
// -------------------------------------------------------------------
public boolean equals(Object obj) {
return ((obj != null) && obj.getClass().equals(EasySSLSocketFactory.class));
}
public int hashCode() {
return EasySSLSocketFactory.class.hashCode();
}
}
EasyX509TrustManager:
public class EasyX509TrustManager implements X509TrustManager {
private X509TrustManager standardTrustManager = null;
/**
* Constructor for EasyX509TrustManager.
*/
public EasyX509TrustManager(KeyStore keystore) throws NoSuchAlgorithmException, KeyStoreException {
super();
TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
factory.init(keystore);
TrustManager[] trustmanagers = factory.getTrustManagers();
if (trustmanagers.length == 0) {
throw new NoSuchAlgorithmException("no trust manager found");
}
this.standardTrustManager = (X509TrustManager) trustmanagers[0];
}
/**
* @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],String authType)
*/
public void checkClientTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
standardTrustManager.checkClientTrusted(certificates, authType);
}
/**
* @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],String authType)
*/
public void checkServerTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
if ((certificates != null) && (certificates.length == 1)) {
certificates[0].checkValidity();
} else {
standardTrustManager.checkServerTrusted(certificates, authType);
}
}
/**
* @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
*/
public X509Certificate[] getAcceptedIssuers() {
return this.standardTrustManager.getAcceptedIssuers();
}
}
And I added this method: getNewHttpClient()
public static HttpClient getNewHttpClient() {
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", sf, 443));
ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
return new DefaultHttpClient(ccm, params);
} catch (Exception e) {
return new DefaultHttpClient();
}
}
Finally for every place in my code that I had:
DefaultHttpClient client = new DefaultHttpClient();
I replace it with:
HttpClient client = getNewHttpClient();
I'm able now to receive the data from server side, last question is: is what I did is secure? or it's accepts each self-signed certificate? if this is the case what should be done to change it?
Any help would be appreciated.
You can't. Browsers prevents this by default as otherwise it would be insecure to allow it. The remote server must have a valid SSL certificate and use HTTPS.
Under HTTP request settings: Enter a URL in the field provided. Select either Use HTTP GET or Use HTTP POST. Enter HTTPS instead of HTTP in the URL to send the information using HTTPS.
POST is an HTTP method designed to send data to the server from an HTTP client. The HTTP POST method requests the web server accept the data enclosed in the body of the POST message. HTTP POST method is often used when submitting login or contact forms or uploading files and images to the server.
GET and POST method in HTTP and HTTPS are two most popular methods used to transfer data from client to server using HTTP(HyperText Transfer Protocol) protocol.
From the Apache HttpClient SSL guide:
secure HTTP communication over SSL should be as simple as plain HTTP communication.
So you simply should change the http://XXXX to https://XXXX
EDIT: I've just seen @Barend 's answer which is more complete
First of all you need to create SchemeRegistry object and register new Scheme using SSLSocketFactory:
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
Then you can create your SingleClientConnManager using SchemeRegistry object:
SingleClientConnManager mgr = new SingleClientConnManager(schemeRegistry);
And finally you create your DefaultHttpClient with SingleClientConnManager:
HttpClient client = new DefaultHttpClient(mgr);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With