14

We have an Android application that requires the user to enter an answer to a Captcha. The Captcha is generated on our server. When the replies, it is sent to the server for verifying.

Problem is that since I have to close the HttpURLConnection after the request for the Captcha I then find that the reply is running on a different session on the sever. Because of this the Captcha check fails since it is session dependant.

Is there a way to keep the connection alive or should I be following a different path? I know that in the equivalent iPhone application they remain "connected" and thus have the same sessionid.

Edit:

    CookieManager cookieManager = new CookieManager();  
    CookieHandler.setDefault(cookieManager);

    URL urlObj = new URL(urlPath);
    conn = (HttpURLConnection) urlObj.openConnection();

    if (urlPath.toLowerCase().startsWith("https:")) {
        initializeHttpsConnection((HttpsURLConnection) conn);
    }
    conn.setRequestMethod("POST");
    conn.setRequestProperty("Content-Language", "en-US");
    conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
    conn.setRequestProperty("Content-Length", Integer.toString(bodyData.length));
    if (_sessionIdCookie != null) {
        conn.setRequestProperty("Cookie", _sessionIdCookie);
    }
    // Connect
    conn.setDoInput(true);
    conn.setDoOutput(true);
    conn.connect();
theblitz
  • 6,683
  • 16
  • 60
  • 114

2 Answers2

14

To maintain session using HttpURLConnection you need to execute this part

CookieManager cookieManager = new CookieManager();  
CookieHandler.setDefault(cookieManager);

only once and not on every connection. Good candidate can be on application launch inside Application.onCreate();

Grigori A.
  • 2,628
  • 1
  • 21
  • 19
13

Normally, sessions are not kept based on the http connection itself. That wouldn't make any sense. Sessions are normally kept alive through a cookie on the client side and session information on the server side. What you gotta do is save the cookie(s) you're receiving and then setting that(those) cookie(s) next time you connect to the server.

To learn more about how to work with sessions and cookies with the HttpUrlConnection class, read the documentation: http://developer.android.com/reference/java/net/HttpURLConnection.html

Here a little excerpt to get you started:

To establish and maintain a potentially long-lived session between client and server, HttpURLConnection includes an extensible cookie manager. Enable VM-wide cookie management using CookieHandler and CookieManager:

CookieManager cookieManager = new CookieManager();  
CookieHandler.setDefault(cookieManager);

EDIT:

For those working with API levels 8 or lower, you'll need to use Apache's library!

Here's some reference code:

 // Create a local instance of cookie store
    CookieStore cookieStore = new BasicCookieStore();

    // Create local HTTP context
    HttpContext localContext = new BasicHttpContext();
    // Bind custom cookie store to the local context
    localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

    HttpGet httpget = new HttpGet("http://www.google.com/"); 

    System.out.println("executing request " + httpget.getURI());

    // Pass local context as a parameter
    HttpResponse response = httpclient.execute(httpget, localContext);

The code above was taken from the Apache's library examples. It can be found here: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/httpclient/src/examples/org/apache/http/examples/client/ClientCustomContext.java

EDIT 2: Making it clear:

For the Apache library you need to somehow "connect" the cookie management object with the connection object and you do that through the HttpContext object.

In HttpUrlConnection's case that's not necessary. when you use CookieHandler's static method setDefault, you're setting the system-wide cookieHandler. Below is an excerpt from CookieHandler.java. Note the variable name (from the Android Open Source Project's (AOSP) repository):

 37 /**
 38      * Sets the system-wide cookie handler.
 39      */
 40     public static void setDefault(CookieHandler cHandler) {
 41         systemWideCookieHandler = cHandler;
 42     }
DallaRosa
  • 5,737
  • 2
  • 35
  • 53
  • Once I have defined the "CookieManager" do I then add one that holds the sessionid? – theblitz May 23 '12 at 07:39
  • Ok, I have an important question for you: Are you using API 9+ (2.3+)? IF yes, you just add that before connecting it you should be ok. If you're using 2.2 or less you should use the HttpClient from the org.apache package. If you're doing for 2.2 I'll add some example code. – DallaRosa May 23 '12 at 08:12
  • At the moment it is set to 2.3 but not sure we are going to leave it like that. Might drop it down top 2.2 but not sure. Seems that 99% of devices here are 2.3+ so should be ok. – theblitz May 23 '12 at 08:17
  • Ok. So you should be good. Try that and let me know if it worked. I'll add code to be used with the Apache library for the sake of the next person that stumbles upon this – DallaRosa May 23 '12 at 08:18
  • Still not sure how it should work. Do I need to connect to cookie manager to the connection somehow? I have edited to include my code. – theblitz May 23 '12 at 08:36
  • CookieHandler.setDefault(cookieManager); The line above sets the cookieManager object you created to be the default cookieHandler for all connections. – DallaRosa May 23 '12 at 08:48
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/11628/discussion-between-dallarosa-and-theblitz) – DallaRosa May 23 '12 at 08:49