【发布时间】:2011-11-09 22:35:39
【问题描述】:
我尝试通过使用所需参数执行 POST 来访问 ba.com(实际 url:“https://www.britishairways.com/travel/loginr/public/en_us?eId=109001),它以 3XX 重定向回复,该重定向指向带有 Set-Cookie 标头的 url https://www.britishairways.com/cookie.html。我尝试使用请求头 Cookie 和 key=value;key=value ... 进行 GET,此时它返回一个 2XX 表示 cookie 未启用。
对于 gmail.com,当我使用所需参数进行 POST 时,它直接返回带有 Set-Cookie 标头的 2XX 响应,并声明未启用 cookie。
我的问题是:
- 通常情况下,客户端和服务器之间的 HTTP(S) 序列用于验证 cookie 是否启用?
- 我的一般用途是通过程序访问我的帐户,登录,并查看有关我的帐户的一些信息。 britshairways.com/gmail.com 可能是一个好的开始。 (这有点像模拟的网络浏览器)
如果有人知道可以完成任务的示例代码,我想学习。谢谢。
下面的非工作示例代码以及调用 britishairways.com/gmail.com 的详细参数
public static void PostToUrlWithCookies(string uri, NameValueCollection nvc, CookieCollection cookies, string cookieHeader = "")
{
// this is what we are sending
string post_data = "";
if (nvc != null)
{
foreach (string key in nvc.Keys)
{
string formitem = string.Format("{0}={1}", key, nvc[key]);
if (post_data == "")
{
post_data += formitem;
}
else
{
post_data += "&" + formitem;
}
}
}
Console.WriteLine("post_data={0}", post_data);
// create a request
HttpWebRequest request = (HttpWebRequest)
WebRequest.Create(uri);
// to accept cookies (and skip 100 response)
//var cookies = new CookieContainer();
ServicePointManager.Expect100Continue = false;
string newCookieHeader = "";
request.CookieContainer = new CookieContainer();
if (cookies.Count > 0)
{
CookieCollection oCookies = cookies;
for (int j = 0; j < oCookies.Count; j++)
{
Cookie oCookie = oCookies[j];
Cookie oC = new Cookie();
// Convert between the System.Net.Cookie to a System.Web.HttpCookie...
oC.Domain = request.RequestUri.Host;
oC.Expires = oCookie.Expires;
oC.Name = oCookie.Name;
oC.Path = oCookie.Path;
oC.Secure = oCookie.Secure;
oC.Value = oCookie.Value;
if (newCookieHeader != "")
{
newCookieHeader += ";";
}
newCookieHeader += oC.Name + "=" + oC.Value;
//request.CookieContainer.Add( oC );
}
}
// Console.WriteLine("request has {0} cookies inside", request.CookieContainer.Count);
if (cookieHeader != "")
{
request.Headers["Cookie"] = newCookieHeader;
Console.WriteLine("request Set-Cookie: {0}", newCookieHeader);
}
// add a fake cookie to request
//Cookie aCookie = new Cookie("lastVisited", DateTime.Now.ToString());
//aCookie.Domain = "ba.com";
//request.CookieContainer.Add(aCookie);
request.KeepAlive = true;
request.ProtocolVersion = HttpVersion.Version11;
if (cookies.Count == 0)
{
request.AllowAutoRedirect = false; // ba.com testing cookies using a 3XX Redirect
request.Method = "POST";
}
else
{
request.AllowAutoRedirect = false;
request.Method = "GET";
}
//
// turn our request string into a byte stream
byte[] postBytes = Encoding.ASCII.GetBytes(post_data);
// this is important - make sure you specify type this way
if (request.Method == "POST")
{
request.ContentType = "application/x-www-form-urlencoded";
request.UserAgent = "Mozilla/5.0 (X11; Linux x86_64; rv:6.0.2) Gecko/20100101 Firefox/6.0.2";
request.ContentLength = postBytes.Length;
Stream requestStream = request.GetRequestStream();
//
// // now send it
if (post_data != "")
{
requestStream.Write(postBytes, 0, postBytes.Length);
}
requestStream.Close();
}
else
{
request.UserAgent = "Mozilla/5.0 (X11; Linux x86_64; rv:6.0.2) Gecko/20100101 Firefox/6.0.2";
}
//
// grab te response and print it out to the console along with the status code
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
foreach (Cookie cook in response.Cookies)
{
// Console.WriteLine("Cookie:");
// Console.WriteLine("{0} = {1}", cook.Name, cook.Value);
cookies.Add(cook);
}
cookieHeader = response.GetResponseHeader("Set-Cookie");
Console.WriteLine("responce-> Set-Cookie: {0}", cookieHeader);
for (int i = 0; i < response.Headers.Count; ++i)
Console.WriteLine("\nHeader Name:{0}, Value :{1}", response.Headers.Keys[i], response.Headers[i]);
if ((int)response.StatusCode >= 300 && (int)response.StatusCode < 400)
{
string cookieUrl = response.Headers["Location"];
Console.WriteLine("about to verify cookie via url {0}", cookieUrl);
// verify the cookie capability
PostToUrlWithCookies(cookieUrl, null /*nvc*/, cookies, cookieHeader);
}
else
{
Console.WriteLine(new StreamReader(response.GetResponseStream()).ReadToEnd());
Console.WriteLine((int)response.StatusCode);
}
}
调用 ba.com(格式:uri、key、value 对):
func "https://www.britishairways.com/travel/loginr/public/en_us?eId=109001","loginText", "Login+ID", "Directional_Login", "%2Ftravel%2Fechome%2Fexecclub%2Fen_us%3FmembershipNumber%3D36436959%26DM1%255FmktgCat%3DEmail%26DM1%255FMktgSubCat%3D2%26DM1%255Fcampaign%3DBBBB5YT0BPKCBBBB5YT0BQBG%26DM1%255FChksm%3D117285700%26DM1_SRC%3D%26utm_source%3DeD%26utm_medium%3DEmail%26utm_campaign%3DEmail%26utm_term%3DBBBB5YT0BQBG%26utm_content%3DBBBB5YT0BPKC", "membershipNumber", "XXXXXX", "password", "XXXXXX", "passwordtext", "XXXXXXX"
致电 gmail.com
"https://accounts.google.com/ServiceLoginAuth", "continue", "http%3A%2F%2Fwww.google.com%2F", "dsh", "7157339180374789215", "hl", "en", "GALX", "f9V9sU8AY6c", "pstMsg", "1", "dnConn", "", "timeStmp", "", "secTok", "", "Email", "XXXXXXX@gmail.com", "Passwd", "XXXXXXX", "signIn", "Sign+in", "rmShown", "1"
【问题讨论】:
-
你试过
WebClient吗?不确定它是否内置了 cookie 支持,但我认为是的 -
您使用什么类/库来访问
https://www.ba.com。你的代码是什么样子的? -
郑重声明,这违反了网站的服务条款:“特别是,您同意,您不得……使用‘屏幕抓取’、任何自动化算法、设备、方法、系统、软件或手动过程来访问、使用、搜索、复制、监控或从或通过使用本网站提取材料(全部或部分),除非我们已明确书面同意;” britishairways.com/travel/termcn/public/en_us
-
我还注意到 ba.com 存在安全问题,因为证书与域不匹配(ba.com 重定向到 britishairways.com 但 ba.com 做错了事,并尝试提供服务相同的内容。),证书错误可能会导致 WebClient 或 WebRequest 出现问题
-
我实际使用的是“britishairways.com”,见帖子中的参数列表。很抱歉造成混乱,它不是 ba.com,我把它放在那里只是为了方便。
标签: c# cookies httpclient