2010-09-07 11 views
21

Quiero acceder a un sitio que primero requiere una autenticación (servidor Tomcat) y luego iniciar sesión con una solicitud POST y mantener a ese usuario para ver las páginas del sitio. Yo uso HttpClient 4.0.1Httpclient 4, error 302. ¿Cómo redirigir?

La primera autenticación funciona bien, pero no es el inicio de sesión que siempre se queja acerca de este error: "302 Movido temporalmente"

guardo las galletas & que mantienen un contexto y sin embargo nada. En realidad, parece que el inicio de sesión funciona, porque si escribo parámetros incorrectos o la contraseña del usuario, veo la página de inicio de sesión. Así que supongo que lo que no funciona es la redirección automática.

Siguiendo mi código, que siempre lanza el 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 
     } 
    } 
+2

"La primera autenticación funciona bien, pero no es el inicio de sesión que siempre se queja acerca de este error". Una redirección 302 no es una queja del servidor; es una indicación de que el usuario-agente debe proceder ahora a la nueva página indicada en la respuesta. –

+0

Pensé eso, pero ¿cómo? Intento una solicitud GET pero fue en vano. – juanmirocks

Respuesta

36

Para la versión 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; 
     } 
    }); 
+3

No creo que esto deba volverse falso, creo que debería devolver isRedirect. Cuando hice este cambio, este código funcionó. ¡Gracias! –

+3

Funciona, pero en la mayoría de los casos, las solicitudes POST se cambian a solicitudes GET por parte del servidor http. Y si el objetivo (por ejemplo, un servlet) solo acepta solicitudes POST, la redirección automática falla con el código de estado 405 (Método no permitido). ¿Alguna sugerencia? –

+0

Oye, intenté esto, aunque esto funciona bien en un proyecto de Java, lo probé en Android y me sale algo similar a lo que se describe aquí http://stackoverflow.com/questions/9255150/android-app-not-recognizing -setredirectstrategy ¿Qué sugieres? He importado las bibliotecas httpclient 4.2 –

1
httpclient.setRedirectHandler(new DefaultRedirectHandler()); 

Ver HttpClient Javadoc

+1

Eso no funciona. ¿Alguna otra idea? – juanmirocks

5

Hay que poner en práctica manejador de redirección a medida que nos indicará que la respuesta al post es una redirección . Esto puede hacerse anulando el método isRedirectRequested() como se muestra a continuación.

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

En versión posterior de HttpClient, el nombre de clase es DefaultRedirectStrategy, pero solución similar se puede utilizar allí.

+0

el retorno debe ser isRedirect y no falso – Shaybc

+0

Gracias. He actualizado la respuesta. –

1

redirecciones no son manejados automáticamente por HttpClient 4.1 por otros métodos distintos GET y PUT.

17

En versiones posteriores de HttpClient (4.1 +), que sólo puede hacer esto:

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

LaxRedirectStrategy redirigirá automáticamente HEAD, GET y POST peticiones. Para una implementación más estricta, use DefaultRedirectStrategy.

+1

Esto no se introdujo en 4.1, se introdujo en 4.2. –

0
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. 
16

Para HttpClient 4.3.x:

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