在使用HttpWebRequest访问需要登陆的页面时必然会涉及到Cookies,但是HttpWebRequest对象和相关方法在设计时还是存在一些问题
比如:
- 访问页面A,得到Cookie o1包含jspsessionid;
- 把o1给HttpWebRequest然后登陆页面B,得到一个新的Cookies o2,里面包含了很多相关信息;
- 把o2给HttpWebRequest然后登陆页面C.
一般情况下你会使用如下代码:
HttpWebRequestoRequest
=
(HttpWebRequest)HttpWebRequest.Create(oHead.Host
+
oHead.Action);
oRequest.ProtocolVersion
=
new
Version(
"
1.1
"
);
oRequest.Referer
=
oHead.Referer;
oRequest.Accept
=
"
image/gif,image/x-xbitmap,image/jpeg,image/pjpeg,application/x-shockwave-flash,application/vnd.ms-excel,application/vnd.ms-powerpoint,application/msword,application/xaml+xml,application/vnd.ms-xpsdocument,application/x-ms-xbap,application/x-ms-application,*/*
"
;
oRequest.CookieContainer
=
new
CookieContainer();
oRequest.CookieContainer.Add(o2)
oRequest.UserAgent
=
"
blogmove.cn
"
;
oRequest.Credentials
=
CredentialCache.DefaultCredentials;
上面的oRequest.CookieContainer.Add(o2)基本上没有错,而且按照道理来说也不会有错
但是事实上,Micosoft在设计这一部分是存在缺陷的,或者“Microsoft有独立的定位”,也许还有我不知道的地方
上文的代码一般情况下不会有错,Cookies值会被正常传递给服务器,但是如果o2的内容是下面的内容的话,上面的代码就可能会存在缺陷:
Set-Cookie: JSESSIONID=555287820C8B46311649EF947F77DF12; Path=/control
Set-Cookie: Code=b4874b74; Domain=blogmove.cn; Path=/
Set-Cookie: mc=1%2cplatform%2c0; Domain=blogmove.cn; Path=/
(注意这里是HttpHeader方式)
上面的这段Head假设是在访问http://file.blogmove.cn/t1.aspx 时,服务器写给浏览器的。
o2被传递给oRequest,oRequest访问http://file.blogmove.cn/test.aspx 时,上面三个cookie,只有第一个被oRequest传递给了服务器,服务器收不到后面两个cookies,Test.aspx页面就会返回错误的结果。
原因就是Cookie是有Domain的,
第一个Cookie的Domain是默认http://file.blogmove.cn;
第二和三个Cookie的Domain是blogmove.cn;
oRequest在上行Cookie时只上行了当前Domain=http://file.blogmove.cn的Cookie,而放弃了Domin=blogmove.cn的Cookie,oRequest分辨了Uri;
这种行为和我们正常预想的不符,因为我们平常是按照浏览器的行为在思考:应该上行所有blogmove.cn下的所有Cookies.
按照道理来说,我认为Request对象应该自动分辨和解析Cookies里面的domain.
因此为了保证oRequest能够达到我们的目的,所以应该修改上面的C#代码如下:
public
string
Send(
ref
SendHeadoHead)

...
{
HttpWebResponseoResponse=null;
HttpWebRequestoRequest=(HttpWebRequest)HttpWebRequest.Create(oHead.Host+oHead.Action);
oRequest.ProtocolVersion=newVersion("1.1");
oRequest.Referer=oHead.Referer;
oRequest.Accept="image/gif,image/x-xbitmap,image/jpeg,image/pjpeg,application/x-shockwave-flash,application/vnd.ms-excel,application/vnd.ms-powerpoint,application/msword,application/xaml+xml,application/vnd.ms-xpsdocument,application/x-ms-xbap,application/x-ms-application,*/*";
oRequest.CookieContainer=newCookieContainer();
if(oHead.Cookies!=null)

...{
stringcookiesValue="";
foreach(CookieoinoHead.Cookies)

...{
cookiesValue+=o.Name+"="+o.Value+",";
}
oRequest.CookieContainer.SetCookies(newUri(oHead.Host),cookiesValue);
}
//oRequest.CookieContainer.SetCookies(oRequest.RequestUri,cookies[].
oRequest.UserAgent="NutsSoft.com.cn";
oRequest.Credentials=CredentialCache.DefaultCredentials;

//设置POST数据
if(oHead.Method.ToLower()=="post")

...{
oRequest.Method="POST";
byte[]byteData=ASCIIEncoding.ASCII.GetBytes(oHead.PostData);
oRequest.ContentType="application/x-www-form-urlencoded";
oRequest.ContentLength=byteData.Length;
StreamWriteStream=oRequest.GetRequestStream();
WriteStream.Write(byteData,0,byteData.Length);
WriteStream.Close();
}
try

...{
oResponse=(HttpWebResponse)oRequest.GetResponse();
}
catch(WebExceptionex)

...{
oResponse=(HttpWebResponse)ex.Response;
}
oResponse.Cookies=oRequest.CookieContainer.GetCookies(oRequest.RequestUri);
StreamdataStream=oResponse.GetResponseStream();

stringen=oResponse.CharacterSet;
if(en==null)en="gb2312";
if(en.ToLower()=="iso-8859-1")en="gb2312";
StreamReaderreader=newStreamReader(dataStream,Encoding.GetEncoding(en));
stringresponseFromServer=reader.ReadToEnd();
Cookies=oRequest.CookieContainer.GetCookies(oRequest.RequestUri);
oHead.Cookies=oRequest.CookieContainer.GetCookies(oRequest.RequestUri);
reader.Close();
dataStream.Close();
oResponse.Close();
returnoHead.Html=responseFromServer;
}
这是一个相当完整的Send方法。不做过多的解释.
PS:这个Cookies上行问题耗费了一天时间来找出原因。
另:本文言语有点混乱。