2010-09-07 36 views
21

Tôi muốn truy cập một trang web đầu tiên yêu cầu xác thực (máy chủ tomcat) và sau đó đăng nhập bằng yêu cầu POST và giữ người dùng đó xem các trang của trang web đó. Tôi sử dụng HttpClient 4.0.1Httpclient 4, lỗi 302. Cách chuyển hướng?

Việc xác thực đầu tiên hoạt động tốt nhưng không phải là đăng nhập luôn phàn nàn về lỗi này: "302 Đã tạm thời dời"

tôi giữ cookie & tôi giữ một bối cảnh nhưng không có gì. Trên thực tế, có vẻ như đăng nhập hoạt động, bởi vì nếu tôi viết thông số không chính xác hoặc mật khẩu người dùng ||, tôi sẽ thấy trang đăng nhập. Vì vậy, tôi đoán những gì không hoạt động là chuyển hướng tự động.

Tiếp theo mã của tôi, mà luôn luôn ném 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

"Việc xác thực đầu tiên hoạt động tốt nhưng không phải là đăng nhập luôn phàn nàn về lỗi này". Chuyển hướng 302 không phải do máy chủ khiếu nại; nó là một dấu hiệu cho thấy tác nhân người dùng phải tiến hành trang mới được chỉ ra trong phản hồi. –

+0

Tôi nghĩ vậy, nhưng làm sao? Tôi thử sau đó một yêu cầu GET nhưng vô ích. – juanmirocks

Trả lời

36

Đối với phiên bả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

Tôi không nghĩ rằng điều này sẽ trả về false, tôi nghĩ rằng nó sẽ trở lại isRedirect. Khi tôi thực hiện thay đổi này, mã này đã hoạt động. Cảm ơn! –

+3

Nó hoạt động, nhưng trong hầu hết các trường hợp, các yêu cầu POST được thay đổi thành các yêu cầu GET bởi máy chủ http. Và nếu mục tiêu (ví dụ: một servlet) chỉ chấp nhận các yêu cầu POST, thì chuyển hướng tự động không thành công với mã trạng thái 405 (Phương thức không được phép). Bất kỳ đề xuất? –

+0

Hey Tôi đã thử điều này, trong khi điều này hoạt động tốt trong một dự án java tôi đã thử nó trong Android và tôi nhận được một cái gì đó một cái gì đó tương tự như những gì được mô tả ở đây http://stackoverflow.com/questions/9255150/android-app-not-recognizing -setredirectstrategy Bạn đề nghị gì? Tôi đã nhập khẩu các thư viện httpclient 4.2 –

1
httpclient.setRedirectHandler(new DefaultRedirectHandler()); 

Xem HttpClient Javadoc

+1

Điều đó không hiệu quả. Bạn có ý tưởng nào khác không? – juanmirocks

5

Bạn phải thực hiện xử lý chuyển hướng tùy chỉnh mà sẽ chỉ ra rằng đối phó với POST là một chuyển hướng . Điều này có thể được thực hiện bằng cách ghi đè phương thức isRedirectRequested() như hình dưới đây.

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

Trong phiên bản sau của HttpClient, tên lớp là DefaultRedirectStrategy, nhưng giải pháp tương tự có thể được sử dụng ở đó.

+0

lợi nhuận phải là Chuyển hướng và không sai – Shaybc

+0

Cảm ơn. Tôi đã cập nhật câu trả lời. –

1

Chuyển hướng không được xử lý tự động bởi HttpClient 4.1 cho các phương pháp khác hơn là GET và PUT.

17

Trong các phiên bản sau này của HttpClient (4.1 trở lên), bạn chỉ có thể làm điều này:

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

LaxRedirectStrategy sẽ tự động chuyển hướng HEAD, GET, và yêu cầu POST. Để thực hiện nghiêm ngặt hơn, hãy sử dụng DefaultRedirectStrategy.

+1

Điều này đã không được giới thiệu trong 4.1, nó đã được giới thiệu trong 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

Đối HttpClient 4.3.x:

HttpClient httpClient = HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy()).build(); 
Các vấn đề liên quan