C#HttpClient或使用CookieContainer模擬登陸後HttpRequest不發送cookie的解決方法及原因

解決辦法

在發送包含用戶名和密碼的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+?

發佈了25 篇原創文章 · 獲贊 25 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章