Httpclient 4,错误302。如何重定向?

24

我想访问一个需要(tomcat服务器)认证的网站,然后使用POST请求登录并保持该用户以查看网站页面。 我使用Httpclient 4.0.1

第一次身份验证正常工作,但是登录始终会抱怨此错误:“302暂时移动”

我保留cookie和上下文,但仍然无法访问。 实际上,似乎登录已经成功,因为如果我写入不正确的参数或用户名||密码,则会看到登录页面。 所以我猜自动重定向是不起作用的。

以下是我的代码,它总是抛出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重定向不是服务器的投诉;它是一个指示,用户代理现在必须继续响应中指示的新页面。 - Vineet Reynolds
我也曾这么想,但该怎么做呢?我尝试了GET请求,但没有成功。 - juanmirocks
7个回答

37

对于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。当我进行此更改时,这段代码就可以工作了。谢谢! - Ben Flynn
3
它可以工作,但大多数情况下,HTTP服务器会将POST请求更改为GET请求。如果目标(如Servlet)仅接受POST请求,则自动重定向将以状态码405(不允许的方法)失败。有什么建议吗? - James Selvakumar
嘿,我尝试了这个,在Java项目中它运行良好,但在Android中我遇到了类似于此处所描述的问题:http://stackoverflow.com/questions/9255150/android-app-not-recognizing-setredirectstrategy。你有什么建议吗?我已经导入了httpclient 4.2库。 - Shikhar Shrivastav

21

对于HttpClient 4.3.x:

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

17

在HttpCLient的后续版本(4.1+)中,您可以仅执行以下操作:

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

LaxRedirectStrategy将自动重定向HEAD、GET和POST请求。 若要更严格的实现,请使用DefaultRedirectStrategy。


2
这不是在4.1中引入的,而是在4.2中引入的。 - user4903

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,但是类似的解决方案也可以在那里使用。


返回应该是 isRedirect 而不是 false。 - Shaybc

1
httpclient.setRedirectHandler(new DefaultRedirectHandler());

请参阅 HttpClient Javadoc


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.

1

HttpClient 4.1 对于除 GET 和 PUT 以外的其他方法,不会自动处理重定向。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接