我正在尝试使用我在使用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
数据在请求主体中设置而不是设置为实体。这有什么不同吗?这会产生正确的请求标题吗?
答案 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
。
因此,要么将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]