24

I want to access one site that first requires an (tomcat server) authentication and then log in with a POST request and keep that user to see the site's pages. I use Httpclient 4.0.1

The first authentication works fine but not the logon that always complains about this error: "302 Moved Temporarily"

I keep cookies & I keep a context and yet nothing. Actually, it seems that the logon works, because if I write incorrect parameters or user||password, I see the login page. So I guess what doesn't work is the automatic redirection.

Following my code, which always throws the IOException, 302:

    DefaultHttpClient httpclient = new DefaultHttpClient();
    CookieStore cookieStore = new BasicCookieStore();
    httpclient.getParams().setParameter(
      ClientPNames.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY); 
    HttpContext context = new BasicHttpContext();
    context.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
    //ResponseHandler<String> responseHandler = new BasicResponseHandler();

    Credentials testsystemCreds = new UsernamePasswordCredentials(TESTSYSTEM_USER,  TESTSYSTEM_PASS);
    httpclient.getCredentialsProvider().setCredentials(
            new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT),
            testsystemCreds);

    HttpPost postRequest = new HttpPost(cms + "/login");
    List<NameValuePair> formparams = new ArrayList<NameValuePair>();
    formparams.add(new BasicNameValuePair("pUserId", user));
    formparams.add(new BasicNameValuePair("pPassword", pass));
    postRequest.setEntity(new UrlEncodedFormEntity(formparams, "UTF-8"));
    HttpResponse response = httpclient.execute(postRequest, context);
    System.out.println(response);

    if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
        throw new IOException(response.getStatusLine().toString());

    HttpUriRequest currentReq = (HttpUriRequest) context.getAttribute( 
            ExecutionContext.HTTP_REQUEST);
    HttpHost currentHost = (HttpHost)  context.getAttribute( 
            ExecutionContext.HTTP_TARGET_HOST);
    String currentUrl = currentHost.toURI() + currentReq.getURI();        
    System.out.println(currentUrl);

    HttpEntity entity = response.getEntity();
    if (entity != null) {
        long len = entity.getContentLength();
        if (len != -1 && len < 2048) {
            System.out.println(EntityUtils.toString(entity));
        } else {
            // Stream content out
        }
    }
juanmirocks
  • 4,786
  • 5
  • 46
  • 46
  • 2
    "The first authentication works fine but not the logon that always complains about this error". A 302 redirect is not a complaint by the server; it is an indication that the user-agent must now proceed to the new page indicated in the response. – Vineet Reynolds Sep 07 '10 at 12:48
  • I thought that, but how? I try then a GET request but to no avail. – juanmirocks Sep 07 '10 at 13:19

7 Answers7

37

For 4.1 version:

DefaultHttpClient  httpclient = new DefaultHttpClient();
    httpclient.setRedirectStrategy(new DefaultRedirectStrategy() {                
        public boolean isRedirected(HttpRequest request, HttpResponse response, HttpContext context)  {
            boolean isRedirect=false;
            try {
                isRedirect = super.isRedirected(request, response, context);
            } catch (ProtocolException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            if (!isRedirect) {
                int responseCode = response.getStatusLine().getStatusCode();
                if (responseCode == 301 || responseCode == 302) {
                    return true;
                }
            }
            return isRedirect;
        }
    });
tucuxi
  • 17,561
  • 2
  • 43
  • 74
fvisticot
  • 7,936
  • 14
  • 49
  • 79
  • 3
    I don't think this should return false, I think it should return isRedirect. When I made this change, this code worked. Thanks! – Ben Flynn Apr 23 '11 at 18:09
  • 3
    It works, but in most cases the POST requests are changed to GET requests by the http server. And if the target (for e.g a servlet) accepts only POST requests, then the auto redirect fails with the status code 405 (Method not allowed). Any suggestions? – James Selvakumar Aug 24 '12 at 02:36
  • Hey I tried this, while this works well in a java project I tried it in Android and I get an something something similar to what is described here http://stackoverflow.com/questions/9255150/android-app-not-recognizing-setredirectstrategy What do you suggest? I have imported the httpclient 4.2 libraries – Shikhar Shrivastav Dec 16 '12 at 17:18
21

For HttpClient 4.3.x :

HttpClient httpClient = HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy()).build();
Alix Lourme
  • 1,135
  • 1
  • 11
  • 21
17

In later versions of HttpCLient (4.1+), you can just do this:

DefaultHttpClient client = new DefaultHttpClient()
client.setRedirectStrategy(new LaxRedirectStrategy())

LaxRedirectStrategy will automatically redirect HEAD, GET, and POST requests. For a stricter implementation, use DefaultRedirectStrategy.

paradoxbomb
  • 414
  • 5
  • 8
5

You have to implement custom redirection handler that will indicate that response to POST is a redirection. This can be done by overriding isRedirectRequested() method as shown below.

DefaultHttpClient client = new DefaultHttpClient();
client.setRedirectHandler(new DefaultRedirectHandler() {                
    @Override
    public boolean isRedirectRequested(HttpResponse response, HttpContext context) {
        boolean isRedirect = super.isRedirectRequested(response, context);
        if (!isRedirect) {
            int responseCode = response.getStatusLine().getStatusCode();
            if (responseCode == 301 || responseCode == 302) {
                return true;
            }
        }
        return isRedirect;
    }
});

In later version of HttpClient, the class name is DefaultRedirectStrategy, but similar solution can be used there.

Shashikant Kore
  • 4,952
  • 3
  • 31
  • 40
1
Extend the DefaultRedirectStrategy class and override the methods.
@Override
    protected URI createLocationURI(String arg0) throws ProtocolException {
        // TODO Auto-generated method stub
        return super.createLocationURI(arg0);
    }

    @Override
    protected boolean isRedirectable(String arg0) {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public URI getLocationURI(HttpRequest arg0, HttpResponse arg1,
            HttpContext arg2) throws ProtocolException {
        // TODO Auto-generated method stub
        return super.getLocationURI(arg0, arg1, arg2);
    }

    @Override
    public HttpUriRequest getRedirect(HttpRequest request,
            HttpResponse response, HttpContext context)
            throws ProtocolException {
          URI uri = getLocationURI(request, response, context);
          String method = request.getRequestLine().getMethod();
          if (method.equalsIgnoreCase(HttpHead.METHOD_NAME)) {
              return new HttpHead(uri);
          } else {
              return new HttpPost(uri);
          }

    }

    @Override
    public boolean isRedirected(HttpRequest request, HttpResponse response,
            HttpContext context) throws ProtocolException {
        // TODO Auto-generated method stub
        return super.isRedirected(request, response, context);
    }

in this case isRedirectable method will always return true and getRedirect method will return post request in place of get request.
nat
  • 557
  • 2
  • 11
  • 25
1
httpclient.setRedirectHandler(new DefaultRedirectHandler());

See HttpClient Javadoc

Vivien Barousse
  • 20,555
  • 2
  • 63
  • 64
1

Redirects are not handled automatically by HttpClient 4.1 for other methods than GET and PUT.

Alin
  • 1,176
  • 1
  • 12
  • 15