Http Client form based authentication

In this post i will explain you how to do form based authentication in Http client. For this tutorial i have used http client 4.1.2 (i.e. httpcomponents).

Form based authentication can be done in three steps as described below.

  1. Access secure page on server. In response to this request you will receive login page with http status code 200. Note that you will receive JSESSIONID cookie with this response which is required for next request.
  2. Now create a post request for “/j_security_check”. Pass j_username and j_password along with this request. In response to this request you will receive blank response with http status code 302. Here htpp status code 302 indicates that login is successful. If you provide wrong username/password then you will receive login page with http status code 200.
  3. Now access secure page on server. In response to this request you will get requested page with http status code 200 because you are authenticated.

Sample code to do form based authentication in Java using http client.

package com.elitejavacoder.http.client;

import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

public class HttpClientFormAuthentication {
    public static void main(String[] agrs) {
        String host = "yourhostname.com";
        int port = 8080;
        String protocol = "http";

        DefaultHttpClient client = new DefaultHttpClient();

        try {
            HttpHost httpHost = new HttpHost(host, port, protocol);
            client.getParams().setParameter(ClientPNames.DEFAULT_HOST, httpHost);

            HttpGet securedResource = new HttpGet("/secured/index.jsp");            
            HttpResponse httpResponse = client.execute(securedResource);
            HttpEntity responseEntity = httpResponse.getEntity();
            String strResponse = EntityUtils.toString(responseEntity);
            int statusCode = httpResponse.getStatusLine().getStatusCode();
            EntityUtils.consume(responseEntity);

            System.out.println("Http status code for Unauthenticated Request: " + statusCode);// Statue code should be 200
            System.out.println("Response for Unauthenticated Request: n" + strResponse); // Should be login page
            System.out.println("================================================================n");

            HttpPost authpost = new HttpPost("/j_security_check");
            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
            nameValuePairs.add(new BasicNameValuePair("j_username", "yourusername"));
            nameValuePairs.add(new BasicNameValuePair("j_password", "yourpassword"));
            authpost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

            httpResponse = client.execute(authpost);
            responseEntity = httpResponse.getEntity();
            strResponse = EntityUtils.toString(responseEntity);
            statusCode = httpResponse.getStatusLine().getStatusCode();
            EntityUtils.consume(responseEntity);

            System.out.println("Http status code for Authenticattion Request: " + statusCode);// Status code should be 302
            System.out.println("Response for Authenticattion Request: n" + strResponse); // Should be blank string
            System.out.println("================================================================n");

            httpResponse = client.execute(securedResource);
            responseEntity = httpResponse.getEntity();
            strResponse = EntityUtils.toString(responseEntity);
            statusCode = httpResponse.getStatusLine().getStatusCode();
            EntityUtils.consume(responseEntity);

            System.out.println("Http status code for Authenticated Request: " + statusCode);// Status code should be 200
            System.out.println("Response for Authenticated Request: n" + strResponse);// Should be actual page
            System.out.println("================================================================n");
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

7 comments on “Http Client form based authentication

  1. Anonymous says:

    Hello,

    Thanks for your post. I have a few questions, though.

    – What exactly is "j_security_check"? And how did you know that you had to use it?

    – How come that when you call "httpResponse = client.execute(authpost);" (line 47) you get a different string in "strResponse = EntityUtils.toString(responseEntity);" (line 49) than the string you get when you call "strResponse = EntityUtils.toString(responseEntity);" (line 59) after you call "httpResponse = client.execute(securedResource);" (line 57)? Basically, what changes happen to "client" between lines 47 and 57?

    Thanks a lot.

  2. Hello,

    About your first point:

    The "j_security_check" is a form action so container knows that this request is for authentication and container handles that. Also note that here I have used "j_username" and "j_password" which are name of the request parameter to submit username and password. These three should be named in such a way (i.e. j_security_check, j_username and j_password) so container handles this request as authentication request and it can retrieve required information (i.e. username and password) from the submitted request.

    About your second point:

    At line 47, I have submitted request to authpost which is "HttpPost authpost = new HttpPost("/j_security_check");" (refer line 41). At line 57, I have submitted request to securedResource which is "HttpGet securedResource = new HttpGet("/secured/index.jsp");" (refer line 30) so both are different requests hence call "strResponse = EntityUtils.toString(responseEntity);" returns different responses at line 49 and 59.

    Please let me know if you have any other query.

  3. Anonymous says:

    Thank you. But what physical changes exactly happen to the structure of "client "in between lines 47 and 57?

    Because if I created a new "DefaultHttpClien"t (say "client 2") object right before line 57 (with all the correct host, port, etc.), and called "httpResponse = client2.execute(securedResource);" using "client2", the result entity of line 58 and the result string of line 59 would be different than if I would have just called all those methods with "client".

    You see what I'm trying to say? Something happens to the structure of "client" after line 47 is executed, that it makes is so you can get the secured resource in line 57. I would like to know what are these changes.

    Please let me know if I'm not being clear. Thanks

  4. Hello,

    I believe the "client" object should be authenticated one. See the line "httpResponse = client.execute(authpost);" (line 47). When I access secured resource at 57 using that authenticated client object, It submits authentication data (e.g. sessionId etc.) to server hence server knows that the coming request is authenticated one.

    In your case, you have to repeat two calls (i.e. line 31 & line 47) to authenticate your client object as you are creating new client object. After authenticating your client object, you should be able to use that client object multiple times to access secured resources on server.

  5. Hello

    I appreciate this article, but am getting a weird 408 timeout error in step 2 attempting to authenticate.

    If you have any thoughts to get around it I would greatly appreciate it.

    I am hitting jboss eap 6.

    Thanks.

  6. Hello,

    I had never faced 408 error. I had tested this code against Jboss EAP 6. The server had JASS form based authentication.

    It would be good if you can provide some more details about this problem so I might help you here.

    Thanks.

  7. Anonymous says:

    Hi Atul, thanks for the brilliant post. I always received this
    Document moved
    Document moved
    This document has moved here.

    This is the pattern in my spring security configuration

    Is there anything I missed?
    Thanks

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>