Httpclient 4, erro 302. Como redirect?

Desejo acessar um site que primeiro requer uma autenticação (tomcat server) e, em seguida, efetue login com uma solicitação POST e mantenha esse usuário para ver as páginas do site. Eu uso o Httpclient 4.0.1

A primeira autenticação funciona bem, mas não o logon que sempre reclama desse erro: “302 movido temporariamente”

Eu mantenho cookies e mantenho um contexto e ainda nada. Na verdade, parece que o logon funciona, porque se eu escrever parâmetros incorretos ou a senha do usuário, eu vejo a página de login. Então eu acho que o que não funciona é o redirecionamento automático.

Seguindo meu código, que sempre lança a 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 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 formparams = new ArrayList(); 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 } } 

Para a versão 4.1:

 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; } }); 

Em versões posteriores do HttpCLient (4.1+), você pode fazer isso:

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

O LaxRedirectStrategy redirectá automaticamente as solicitações HEAD, GET e POST. Para uma implementação mais rigorosa, use DefaultRedirectStrategy.

Para o HttpClient 4.3.x:

 HttpClient httpClient = HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy()).build(); 

Você precisa implementar o manipulador de redirecionamento personalizado que indicará que a resposta ao POST é um redirecionamento. Isso pode ser feito sobrescrevendo o método isRedirectRequested () como mostrado abaixo.

 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; } }); 

Na versão posterior do HttpClient, o nome da class é DefaultRedirectStrategy, mas uma solução semelhante pode ser usada lá.

 httpclient.setRedirectHandler(new DefaultRedirectHandler()); 

Veja HttpClient Javadoc

Redirecionamentos não são tratados automaticamente pelo HttpClient 4.1 para outros methods além de GET e PUT.

 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.