2013-02-27 32 views
21

我很努力弄清楚這裏有什麼問題。我發送登錄信息,我可以看到標題中的Set-Cookie具有正確的值,但Cookies集合沒有被填充。HttpWebResponse.Cookies儘管設置Cookie標頭(不重定向)

這是HTTPS,登錄自動重定向,但我用AllowAutoRedirect = false禁用它以嘗試解決此問題。

在此屏幕截圖中,您可以很容易地看到調試信息,並且Cookie應該被設置。我將我的httpWebRequest.Cookie設置爲一個新的CookieCollection。

Right click and select view image to see full-size.

HttpWebRequest httpRequest; 
CookieContainer reqCookies = new CookieContainer(); 
string url = "https://example.com"; 
string[] email = user.Split('@'); 
email[0] = System.Web.HttpUtility.UrlEncode(email[0]); 
user = email[0] + "@" + email[1]; 
pass = System.Web.HttpUtility.UrlEncode(pass); 

string postData = "email=" + user + "&password=" + pass; 
byte[] byteData = Encoding.UTF8.GetBytes(postData); 

httpRequest = (HttpWebRequest)WebRequest.Create(url); 
httpRequest.Method = "POST"; 
httpRequest.Referer = url; 
httpRequest.CookieContainer = reqCookies; 
httpRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1003.1 Safari/535.19"; 
httpRequest.Accept = "text/html, application/xhtml+xml, */*"; 
httpRequest.ContentType = "application/x-www-form-urlencoded"; 
httpRequest.ContentLength = byteData.Length; 
using (Stream postStream = httpRequest.GetRequestStream()) 
{ 
    postStream.Write(byteData, 0, byteData.Length); 
    postStream.Close(); 
} 

httpRequest.AllowAutoRedirect = false; 
HttpWebResponse b = (HttpWebResponse)httpRequest.GetResponse(); 

試圖連接到http://www.yahoo.com完全相同的代碼和餅乾放入我的收藏...啊...

這裏是設置Cookie標頭值:

s = 541E2101-B768-45C8-B814-34A00525E50F;域= example.com;路徑= /; 版本= 1

+0

您確定您從服務器設置了正確的域名?它是domain.com還是.domain.com,它們都是不同的。你可以發佈你的ASP.NET你的代碼? – 2013-08-04 12:30:30

回答

14

我發現這個問題爲好,當由C#ASP.NET應用程序...創建,在C#讀取Cookie;)

不知道是否有什麼關係,但是我發現在我的情況下設置的兩個Cookie被寫入一個Set-Cookie頭中,Cookie的有效載荷用逗號分隔。所以我調整了AppDeveloper的解決方案來處理這個多重Cookie問題,並修復了我在評論中提到的名稱/價值。

private static void fixCookies(HttpWebRequest request, HttpWebResponse response) 
{ 
    for (int i = 0; i < response.Headers.Count; i++) 
    { 
     string name = response.Headers.GetKey(i); 
     if (name != "Set-Cookie") 
      continue; 
     string value = response.Headers.Get(i); 
     foreach (var singleCookie in value.Split(',')) 
     { 
      Match match = Regex.Match(singleCookie, "(.+?)=(.+?);"); 
      if (match.Captures.Count == 0) 
       continue; 
      response.Cookies.Add(
       new Cookie(
        match.Groups[1].ToString(), 
        match.Groups[2].ToString(), 
        "/", 
        request.Host.Split(':')[0])); 
     } 
    } 
} 
+2

快速修復「coki1 = val1; expires = sat,週一至2017;域名:asdf.com,coki2 = val2; expires = sat,2017年1月;域名:asdf.com,」。逗號也用於過期日期。 (),()|(| | $)|(P | p)ath =( 。+?);「,」「); – 2017-01-06 21:34:49

+0

as @ blackholeearth0_gmail提到,由逗號分割會產生額外的錯誤cookies,因爲'expires' header中有一個逗號'Wed,04-Apr-18' – AaA 2017-04-04 03:15:28

14

這似乎是由網站發送Set-Cookie頭格式(不是典型格式它應該是)。

在這種情況下,您需要手動解析cookie並將其發送到CookieContainer

for (int i = 0; i < b.Headers.Count; i++) 
{ 
    string name = b.Headers.GetKey(i); 
    string value = b.Headers.Get(i); 
    if (name == "Set-Cookie") 
    { 
     Match match = Regex.Match(value, "(.+?)=(.+?);"); 
     if (match.Captures.Count > 0) 
     { 
      reqCookies.Add(new Cookie(match.Groups[1].Value, match.Groups[2].Value, "/", "example.com")); 
     } 
    } 
} 
+0

我做了這件事,忘記包含在我的示例代碼中。 – Brad 2013-02-27 03:18:43

+0

@Brad - 請發佈適當的示例代碼! – 2013-02-27 03:19:10

+0

我的代碼是一個自定義對象,我不得不在這裏修改和簡化它。對不起,留下一條線,我立即修復。 – Brad 2013-02-27 03:19:57

1

我知道這個問題是舊的,但我遇到了一些代碼,正確解析「Set-Cookie」標題。它處理以逗號分隔的cookie,並提取每個cookie的名稱,過期時間,路徑,值和域。

此代碼比微軟自己的cookie解析器效果更好,這實際上是官方cookie解析器應該做的。我不明白爲什麼微軟還沒有解決這個問題,因爲這是一個非常普遍的問題。

這裏是原代碼: http://snipplr.com/view/4427/

我在這裏張貼的情況下,鏈接出現故障,在某些點:

public static CookieCollection GetAllCookiesFromHeader(string strHeader, string strHost) 
{ 
    ArrayList al = new ArrayList(); 
    CookieCollection cc = new CookieCollection(); 
    if (strHeader != string.Empty) 
    { 
     al = ConvertCookieHeaderToArrayList(strHeader); 
     cc = ConvertCookieArraysToCookieCollection(al, strHost); 
    } 
    return cc; 
} 


private static ArrayList ConvertCookieHeaderToArrayList(string strCookHeader) 
{ 
    strCookHeader = strCookHeader.Replace("\r", ""); 
    strCookHeader = strCookHeader.Replace("\n", ""); 
    string[] strCookTemp = strCookHeader.Split(','); 
    ArrayList al = new ArrayList(); 
    int i = 0; 
    int n = strCookTemp.Length; 
    while (i < n) 
    { 
     if (strCookTemp[i].IndexOf("expires=", StringComparison.OrdinalIgnoreCase) > 0) 
     { 
      al.Add(strCookTemp[i] + "," + strCookTemp[i + 1]); 
      i = i + 1; 
     } 
     else 
     { 
      al.Add(strCookTemp[i]); 
     } 
     i = i + 1; 
    } 
    return al; 
} 


private static CookieCollection ConvertCookieArraysToCookieCollection(ArrayList al, string strHost) 
{ 
    CookieCollection cc = new CookieCollection(); 

    int alcount = al.Count; 
    string strEachCook; 
    string[] strEachCookParts; 
    for (int i = 0; i < alcount; i++) 
    { 
     strEachCook = al[i].ToString(); 
     strEachCookParts = strEachCook.Split(';'); 
     int intEachCookPartsCount = strEachCookParts.Length; 
     string strCNameAndCValue = string.Empty; 
     string strPNameAndPValue = string.Empty; 
     string strDNameAndDValue = string.Empty; 
     string[] NameValuePairTemp; 
     Cookie cookTemp = new Cookie(); 

     for (int j = 0; j < intEachCookPartsCount; j++) 
     { 
      if (j == 0) 
      { 
       strCNameAndCValue = strEachCookParts[j]; 
       if (strCNameAndCValue != string.Empty) 
       { 
        int firstEqual = strCNameAndCValue.IndexOf("="); 
        string firstName = strCNameAndCValue.Substring(0, firstEqual); 
        string allValue = strCNameAndCValue.Substring(firstEqual + 1, strCNameAndCValue.Length - (firstEqual + 1)); 
        cookTemp.Name = firstName; 
        cookTemp.Value = allValue; 
       } 
       continue; 
      } 
      if (strEachCookParts[j].IndexOf("path", StringComparison.OrdinalIgnoreCase) >= 0) 
      { 
       strPNameAndPValue = strEachCookParts[j]; 
       if (strPNameAndPValue != string.Empty) 
       { 
        NameValuePairTemp = strPNameAndPValue.Split('='); 
        if (NameValuePairTemp[1] != string.Empty) 
        { 
         cookTemp.Path = NameValuePairTemp[1]; 
        } 
        else 
        { 
         cookTemp.Path = "/"; 
        } 
       } 
       continue; 
      } 

      if (strEachCookParts[j].IndexOf("domain", StringComparison.OrdinalIgnoreCase) >= 0) 
      { 
       strPNameAndPValue = strEachCookParts[j]; 
       if (strPNameAndPValue != string.Empty) 
       { 
        NameValuePairTemp = strPNameAndPValue.Split('='); 

        if (NameValuePairTemp[1] != string.Empty) 
        { 
         cookTemp.Domain = NameValuePairTemp[1]; 
        } 
        else 
        { 
         cookTemp.Domain = strHost; 
        } 
       } 
       continue; 
      } 
     } 

     if (cookTemp.Path == string.Empty) 
     { 
      cookTemp.Path = "/"; 
     } 
     if (cookTemp.Domain == string.Empty) 
     { 
      cookTemp.Domain = strHost; 
     } 
     cc.Add(cookTemp); 
    } 
    return cc; 
} 
3

使用CookieContainerthis answer。 什麼絆倒這些正則表達式對我來說是一個逗號expires=Tue, ...

5

尋找其他答案我改進了不正確的cookie處理。與這些答案不同,這個自動處理所有Cookie屬性(如過期,安全等)。)並且可以處理所有範圍的cookie(即使有超過1個不正確的cookie)。

它實現爲擴展方法,可以通過以下方式使用:

//... 
      using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 
      { 
       request.FixCookies(response); 
//... 

FixCookies()擴展方法:

using System; 
using System.Collections.Generic; 
using System.Net; 

namespace AG.WebHelpers 
{ 
    static public class ExtensionMethods 
    { 
     static public void FixCookies(this HttpWebRequest request, HttpWebResponse response) 
     { 
      for (int i = 0; i < response.Headers.Count; i++) 
      { 
       string name = response.Headers.GetKey(i); 
       if (name != "Set-Cookie") 
        continue; 
       string value = response.Headers.Get(i); 
       var cookieCollection = ParseCookieString(value,() => request.Host.Split(':')[0]); 
       response.Cookies.Add(cookieCollection); 
      } 
     } 

     static private CookieCollection ParseCookieString(string cookieString, Func<string> getCookieDomainIfItIsMissingInCookie) 
     { 
      bool secure = false; 
      bool httpOnly = false; 

      string domainFromCookie = null; 
      string path = null; 
      string expiresString = null; 

      Dictionary<string, string> cookiesValues = new Dictionary<string, string>(); 

      var cookieValuePairsStrings = cookieString.Split(';'); 
      foreach(string cookieValuePairString in cookieValuePairsStrings) 
      { 
       var pairArr = cookieValuePairString.Split('='); 
       int pairArrLength = pairArr.Length; 
       for (int i = 0; i < pairArrLength; i++) 
       { 
        pairArr[i] = pairArr[i].Trim(); 
       } 
       string propertyName = pairArr[0]; 
       if (pairArrLength == 1) 
       { 
        if (propertyName.Equals("httponly", StringComparison.OrdinalIgnoreCase)) 
         httpOnly = true; 
        else if (propertyName.Equals("secure", StringComparison.OrdinalIgnoreCase)) 
         secure = true; 
        else 
         throw new InvalidOperationException(string.Format("Unknown cookie property \"{0}\". All cookie is \"{1}\"", propertyName, cookieString)); 
        continue; 
       } 

       string propertyValue = pairArr[1]; 
       if (propertyName.Equals("expires", StringComparison.OrdinalIgnoreCase)) 
        expiresString = propertyValue; 
       else if (propertyName.Equals("domain", StringComparison.OrdinalIgnoreCase)) 
        domainFromCookie = propertyValue; 
       else if (propertyName.Equals("path", StringComparison.OrdinalIgnoreCase)) 
        path = propertyValue; 
       else 
        cookiesValues.Add(propertyName, propertyValue); 
      } 

      DateTime expiresDateTime; 
      if (expiresString != null) 
      { 
       expiresDateTime = DateTime.Parse(expiresString); 
      } 
      else 
      { 
       expiresDateTime = DateTime.MinValue; 
      } 
      if (string.IsNullOrEmpty(domainFromCookie)) 
      { 
       domainFromCookie = getCookieDomainIfItIsMissingInCookie(); 
      } 

      CookieCollection cookieCollection = new CookieCollection(); 
      foreach (var pair in cookiesValues) 
      { 
       Cookie cookie = new Cookie(pair.Key, pair.Value, path, domainFromCookie); 
       cookie.Secure = secure; 
       cookie.HttpOnly = httpOnly; 
       cookie.Expires = expiresDateTime; 

       cookieCollection.Add(cookie); 
      } 
      return cookieCollection; 
     } 
    } 
} 
+0

您正在將cookie值分成'=' - 這是一個潛在的陷阱如果該值是base64編碼的字符串 – 2018-03-06 09:21:53

2

這可能是有點晚了,但你可以使用函數SetCookies

var cHeader = responce.Headers.Get("Set-Cookie"); 
var cookie = new CookieContainer(); 
cookie.SetCookies(new Uri("[...]"), cHeader); 
+0

如果'set-cookie'包含'path = /' – Salar 2017-02-22 07:25:40