Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change HTTP post request to HTTPS post request:

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.

like image 893
Emil Adz Avatar asked May 05 '13 21:05

Emil Adz


People also ask

Can we send request from HTTP to HTTPS?

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.

How do I send a HTTPS POST request?

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.

What is HTTPS POST form?

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.

Does HTTPS use GET and POST?

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.


2 Answers

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

like image 188
user2340612 Avatar answered Sep 21 '22 06:09

user2340612


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);
like image 42
nemezis Avatar answered Sep 23 '22 06:09

nemezis