我正在尝试使用通过 HttpClient 4.0.3
响应我的 post 方法而获得的 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());
}
}
}
但我不断收到 No cookies
即使当我使用 web-sniffer.net 时也已注销,我收到以下响应:
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
手动 header 。我不明白为什么这在 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 打印请求 header 时:
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
的响应 header 。我的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
数据设置在请求正文中,而不是设置为实体。这有什么区别吗?这会产生正确的请求 header 吗?
最佳答案
两个 cookie 看起来都很可疑。两者都使用过时的 Netscape cookie 草稿格式。两者都有无效的域属性值。除此之外,LOGIN 显示格式错误(路径属性后缺少分号)。因此,很可能两个 cookie 都被 HttpClient 拒绝。
您可以通过在打开上下文日志记录的情况下运行 HttpClient 来查明是否属于这种情况,如下所述: http://hc.apache.org/httpcomponents-client-ga/logging.html
最后一点。一般来说,在使用 HttpClient 4.x 时不应干预 cookie 策略。默认的 BEST_MATCH 策略将根据 Set-Cookie
header 值的组成自动将 cookie 的处理委托(delegate)给特定的 cookie 规范实现。为了完全禁用 cookie 处理,应该从协议(protocol)处理链中删除 cookie 处理协议(protocol)拦截器。
希望这有帮助。
关于java - HttpClient 4.x 如何使用cookie?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8795911/