解決辦法
在發送包含用戶名和密碼的POST請求後,得到了包含”Set-cookie”的HttpWebResponse,隨後應當添加如下代碼
//Cookies爲CookieContainer對象,Response爲HttpWebResponse對象
Uri Host = new Uri("http://example.cn");
foreach (Cookie cookie in Response.Cookies)
cookies.SetCookies(Host, ("" + cookie.Name + "=" + cookie.Value));
原因
簡單的說,這個問題的原因源於CookieContainer的設計不足,魯棒性不夠強。
這裏我們來簡單瞭解一下Cookie方面的知識,rfc6265第5.3節定義了瀏覽器存放每個Cookie時應該包括這些字段:name、value、expiry-time、domain等等,但並不是每個網站都設計在Set-cookie時向用戶返回所有的字段,比如下圖的情況就只返回了name、value、expiry三個字段
重點在於,如上圖的Set-Cookie頭缺省了domain字段,對於一般瀏覽器來說,當接收到了缺省domain的Set-Cookie字段時,會主動添加本次請求地址的Host上去。而CookieContainer設計之初並沒有打算主動幫助用戶添加被請求Url的Host進Cookies(大家都不知道爲毛),於是在CookieContainer中發生的事情就是,當CookieContainer看到了domain缺省的Set-Cookie字段,就直接把request的Url添加進了Cookie。
這會造成什麼結果?我們假設有一個Host爲Http://example.cn ,當我們登陸時會向/user/login.php POST一段信息,然後該地址返回Cookies,但由於CookieContainer將該完整地址保存給了這些Cookies,於是這些Cookies會並且只會在訪問Http://example.cn/user/login.php時被髮送。這就造成了題目所說的問題。
而上面的代碼做的工作就是爲現有的CookieContainer手動添加在Host下設置的cookie,這樣當我們訪問/user/home.php或者任何其他子節點的時候,Cookies就能夠正常發送了。
關於HttpClient
HttpClient類型保存Cookies時用的是一個Flag爲Protect的CookieContainer對象,所以HttpClient也會遇到一模一樣的問題,而且由於在這裏對象是Protect的,所以不能手動修改,暫時不知道如何在HttpClient中解決這一問題。
參考鏈接
1、HttpWebRequest and CookieContainer - login to a website
2、HttpWebRequest with CookieContainer problem in .NET 4+?