HttpClient 4.x如何使用cookies?

时间:2012-01-09 22:15:43

标签: java http cookies httpclient

我正在尝试使用我在使用HttpClient 4.0.3的帖子方法回复中获得的Cookie;

这是我的代码:

public void generateRequest()
{
    DefaultHttpClient httpclient = new DefaultHttpClient();
    HttpPost httppost = new HttpPost("http://mysite.com/login");
    httpclient.getParams().setParameter("http.useragent", "Custom Browser");
    httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION,
            HttpVersion.HTTP_1_1);
    httpclient.getParams().setParameter(ClientPNames.COOKIE_POLICY,
            CookiePolicy.BROWSER_COMPATIBILITY);

    CookieStore cookieStore = new BasicCookieStore();
    HttpContext localContext = new BasicHttpContext();
    localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

    try
    {
        LOG.info("Status Code: sending");
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
        nameValuePairs.add(new BasicNameValuePair("email", "john%40gmail.com"));
        nameValuePairs.add(new BasicNameValuePair("password", "mypassword"));
        httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
        httppost.setHeader("ContentType", "application/x-www-form-urlencoded");
        HttpResponse response = httpclient.execute(httppost, localContext);
        HttpEntity entity = response.getEntity();
        if (entity != null)
        {
            entity.consumeContent();
        }
        iterateCookies(httpclient);

    }
    catch (ClientProtocolException e)
    {
        LOG.error("ClientProtocolException", e);
    }
    catch (IOException e)
    {
        LOG.error("IOException", e);
    }
}

private void iterateCookies(DefaultHttpClient httpclient)
{
    List<Cookie> cookies = httpclient.getCookieStore().getCookies();
    if (cookies.isEmpty())
    {
        System.out.println("No cookies");
    }
    else
    {
        for (Cookie c : cookies)
        {
            System.out.println("-" + c.toString());
        }
    }
}

但即使我使用web-sniffer.net,我仍然会将No cookies注销,但我得到了回复:

Status:            HTTP/1.1 302 Found
Cache-Control:     private, no-store    
Content-Type:      text/html; charset=utf-8 
Location:          http://www.mysite.com/loginok.html   
Server:            Microsoft-IIS/7.0    
X-AspNet-Version:  2.0.50727    
Set-Cookie:        USER=DDA5FF4E1C30661EC61CFA; domain=.mysite.com; expires=Tue, 08-Jan-2013     18:39:53 GMT; path=/   
Set-Cookie:        LOGIN=D6CC13A23DCF56AF81CFAF; domain=.mysite.com; path=/ Date: Mon, 09     Jan 2012 18:39:53 GMT 
Connection:        close    
Content-Length:    165

我在网上找到的任何有用的例子都参考了HttpClient 3.x,您可以将CookiePolicy设置为IGNORE并手动处理Set-Cookie标题。我无法理解为什么在4.x中这么难。出于多种原因,我需要访问USER哈希。任何人都可以告诉我,我怎么能访问它?

更新

我找到了以下C#代码,它们执行相同的操作并正常工作。

private static string TryGetCookie(string user, string pass, string baseurl)
    {
        string body = string.Format("email={0}&password={1}", user, pass);
        byte[] bodyData = StringUtils.StringToASCIIBytes(body);

        HttpWebRequest req = WebRequest.Create(baseurl) as HttpWebRequest;

        if (null != req.Proxy)
        {
            req.Proxy.Credentials = CredentialCache.DefaultCredentials;
        }

        req.AllowAutoRedirect = false;
        req.Method = "Post";
        req.ContentType = "application/x-www-form-urlencoded";
        req.ContentLength = bodyData.Length;

        using (Stream reqBody = req.GetRequestStream())
        {
            reqBody.Write(bodyData, 0, bodyData.Length);
            reqBody.Close();
        }

        HttpWebResponse resp1 = req.GetResponse() as HttpWebResponse;

        string cookie = resp1.Headers["Set-Cookie"];

        if( string.IsNullOrEmpty(cookie))
        {
            if (0 < resp1.ContentLength)
            {
                // it's probably not an event day, and the server is returning a singlecharacter
                StreamReader stringReader = new StreamReader(resp1.GetResponseStream());

                return stringReader.ReadToEnd();
            }

            return null;
        }

        return ParseCookie(cookie);
    }

我相信我的java代码没有正确形成post请求,因为当我使用URLConnection并从web-sniffer.net打印请求头时:

POST /reg/login HTTP/1.1[CRLF]
Host: live-timing.formula1.com[CRLF]
Connection: close[CRLF]
User-Agent: Web-sniffer/1.0.37 (+http://web-sniffer.net/)[CRLF]
Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7[CRLF]
Cache-Control: no-cache[CRLF]
Accept-Language: de,en;q=0.7,en-us;q=0.3[CRLF]
Referer: http://web-sniffer.net/[CRLF]
Content-type: application/x-www-form-urlencoded[CRLF]
Content-length: 53[CRLF]
[CRLF]
email=john%40gmail.com&password=mypassword

我从包含set-cookies标头的服务器收到回复。我的java代码是否没有像web-sniffer.net那样生成请求?

我见过使用此代码生成的post方法:

PostMethod authPost = new PostMethod("http://localhost:8000/webTest/j_security_check");
// authPost.setFollowRedirects(false);
NameValuePair[] data = {
new NameValuePair("email", "john%40gmail.com"),
new NameValuePair("password", "mypassword")
};
authPost.setRequestBody(data);
status = client.executeMethod(authPost); 

这里的主要区别是NameValuePair数据在请求主体中设置而不是设置为实体。这有什么不同吗?这会产生正确的请求标题吗?

3 个答案:

答案 0 :(得分:3)

两个cookie看起来都很可疑。两者都使用过时的Netscape cookie草稿格式。两者都具有无效的域属性值。 LOGIN显示格式错误(路径属性后面缺少分号)。因此,很可能两个cookie都被HttpClient拒绝了。

您可以通过运行HttpClient并启用上下文日志记录来查明是否是这种情况,如下所述: http://hc.apache.org/httpcomponents-client-ga/logging.html

最后一句话。通常,在使用HttpClient 4.x时,不应该干扰cookie策略。默认的BEST_MATCH策略将根据Set-Cookie标头值的组成自动将cookie处理委派给特定的cookie规范实现。为了完全禁用cookie处理,应该从协议处理链中删除cookie处理协议拦截器。

希望这有帮助。

答案 1 :(得分:0)

我认为问题在于你在这里混合了两种“风格”:一方面你创建了自己的BasicCookieStore并将其放在你的HttpContext中;另一方面,当打印cookie时,你会在DefaultHttpClient

中遍历cookie商店

因此,要么将iterateCookies更改为使用本地cookie存储,要么只使用DefaultHttpClient提供的存储。正如您在DefaultHttpClient的{​​{3}}中看到的那样,它应该会自动将响应Cookie添加到其内部Cookie存储区。

答案 2 :(得分:0)

这总是一个简单的答案!在调试了C#和我找到的另一个C程序之后。我正在跳枪并在电子邮件地址上进行自己的编码以删除@字符。这是问题!!!没有其他任何东西似乎有所不同是否存在!代码现在看起来像:

public void postData(final String email, final String password)
{
    DefaultHttpClient client = new DefaultHttpClient();
    HttpPost post = new HttpPost(LOGIN_URL);
    client.getParams().setParameter("http.useragent", "Custom Browser");
    client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);

    try
    {
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
        nameValuePairs.add(new BasicNameValuePair("email", email));
        nameValuePairs.add(new BasicNameValuePair("password", password));
        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(nameValuePairs, HTTP.UTF_8);
        entity.setContentType("application/x-www-form-urlencoded");
        post.setEntity(entity);

        printHeaders(client.execute(post));
        printCookies(client.getCookieStore());
    }
    catch (ClientProtocolException e)
    {
        LOG.error("ClientProtocolException", e);
    }
    catch (IOException e)
    {
        LOG.error("IOException", e);
    }
}

现在输出如下:

Response Headers:
-Cache-Control: private, no-store
-Content-Type: text/html; charset=utf-8
-Server: Microsoft-IIS/7.0
-X-AspNet-Version: 2.0.50727
-Set-Cookie: USER=3D907C0EB817FD7...92F79616E6E96026E24; domain=.mysite.com; expires=Thu, 10-Jan-2013 20:22:16 GMT; path=/
-Set-Cookie: LOGIN=7B7028DC2DA82...5CA6FB6CD6C2B1; domain=.mysite.com; path=/
-Date: Wed, 11 Jan 2012 20:22:16 GMT
-Content-Length: 165
-Cookie::   [version: 0][name: USER][value: 3D907C0E...E26E24][domain: .mysite.com][path: /][expiry: Thu Jan 10 20:22:16 GMT 2013]
-Cookie::   [version: 0][name: LOGIN][value: 7B7028D...D6C2B1][domain: .mysite.com][path: /][expiry: null]