2010-09-07 66 views
21

我想要訪問首先需要(tomcat服務器)身份驗證的一個站點,然後使用POST請求登錄並讓該用戶查看該站點的頁面。我使用的HttpClient 4.0.1Httpclient 4,錯誤302.如何重定向?

第一認證工作正常,但並不總是抱怨這個錯誤的登錄:「302臨時移動」

我把餅乾&我保持一個方面,但一無所獲。實際上,登錄似乎有效,因爲如果我寫入不正確的參數或用戶||密碼,我會看到登錄頁面。所以我猜想什麼是不工作的自動重定向。

繼我的代碼,它總是拋出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

「第一認證工作正常,但並不總是抱怨這個錯誤登錄」。 302重定向不是服務器的投訴;這表示用戶代理現在必須進入響應中指示的新頁面。 – 2010-09-07 12:48:11

+0

我以爲那可是如何?我嘗試一個GET請求,但無濟於事。 – juanmirocks 2010-09-07 13:19:11

回答

36

對於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

我不認爲這應該返回false,我認爲它應該返回isRedirect。當我做出這個改變時,這段代碼起作用了。謝謝! – 2011-04-23 18:09:54

+3

它可以工作,但在大多數情況下,POST請求會被http服務器更改爲GET請求。如果目標(例如servlet)僅接受POST請求,則自動重定向失敗,並顯示狀態碼405(方法不允許)。有什麼建議麼? – 2012-08-24 02:36:45

+0

嘿,我試過這個,雖然這在一個java項目中效果很好,但我在Android中嘗試了它,並且得到了類似於此處描述的內容的東西http://stackoverflow.com/questions/9255150/android-app-not-recognizing -setredirectstrategy你有什麼建議?我已經導入了httpclient 4.2庫 – 2012-12-16 17:18:25

1
httpclient.setRedirectHandler(new DefaultRedirectHandler()); 

見的HttpClient Javadoc

+1

這不起作用。任何其他想法? – juanmirocks 2010-09-07 13:05:48

5

你要實現自定義的重定向處理程序,將指示POST這種反應是重定向。這可以通過覆蓋isRedirectRequested()方法來完成,如下所示。

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

在以後的HttpClient的版本,類名是DefaultRedirectStrategy,但類似的解決方案可以在那裏使用。

+0

返回的應該是isRedirect而不是false – Shaybc 2011-11-19 12:02:32

+0

謝謝。我已經更新了答案。 – 2011-11-19 13:11:22

1

重定向不會自動的HttpClient 4.1其他方法比GET和PUT處理。

17

在HttpClient的更高版本(4.1以上版本),你可以這樣做:

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

LaxRedirectStrategy將自動重定向HEAD,GET,和POST請求。對於更嚴格的實現,請使用DefaultRedirectStrategy。

+1

這不是4.1中引入的,它是在4.2中引入的。 – 2013-05-28 22:06:10

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

對於HttpClient的版本4.3.x:

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