CookieContainer错误?

我很困惑CookieContainer如何处理域,所以我创建了这个测试。 此测试显示cookieContainer不返回“example.com”的任何cookie,但根据RFC,它应返回至少2个cookie。

这不是一个bug吗?

如何使它工作?

以下是对此错误的讨论:

http://social.msdn.microsoft.com/Forums/en-US/ncl/thread/c4edc965-2dc2-4724-8f08-68815cf1dce6

    CookieContainer getContainer() { CookieContainer result = new CookieContainer(); Uri uri = new Uri("http://sub.example.com"); string cookieH = @"Test1=val; domain=sub.example.com; path=/"; result.SetCookies(uri, cookieH); cookieH = @"Test2=val; domain=.example.com; path=/"; result.SetCookies(uri, cookieH); cookieH = @"Test3=val; domain=example.com; path=/"; result.SetCookies(uri, cookieH); return result; } void Test() { CookieContainer cookie = getContainer(); lblResult.Text += "
Total cookies count: " + cookie.Count + "    expected: 3"; Uri uri = new Uri("http://sub.example.com"); CookieCollection coll = cookie.GetCookies(uri); lblResult.Text += "
For " + uri + " Cookie count: " + coll.Count + "    expected: 2"; uri = new Uri("http://other.example.com"); coll = cookie.GetCookies(uri); lblResult.Text += "
For " + uri + " Cookie count: " + coll.Count + "    expected: 2"; uri = new Uri("http://example.com"); coll = cookie.GetCookies(uri); lblResult.Text += "
For " + uri + " Cookie count: " + coll.Count + "    expected: 2"; } protected void Page_Load(object sender, EventArgs e) { Test(); } CookieContainer Test Page

我刚刚找到了这个bug的修复程序并在这里讨论过: http : //dot-net-expertise.blogspot.com/2009/10/cookiecontainer-domain-handling-bug-fix.html

这是解决方案:

  1. 不要使用.Add(Cookie),仅使用.Add(Uri,Cookie)方法。
  2. 每次向容器添加cookie时或在使用.GetCookie之前或系统使用容器之前,都要调用BugFix_CookieDomain。

     private void BugFix_CookieDomain(CookieContainer cookieContainer) { System.Type _ContainerType = typeof(CookieContainer); Hashtable table = (Hashtable)_ContainerType.InvokeMember("m_domainTable", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Instance, null, cookieContainer, new object[] { }); ArrayList keys = new ArrayList(table.Keys); foreach (string keyObj in keys) { string key = (keyObj as string); if (key[0] == '.') { string newKey = key.Remove(0, 1); table[newKey] = table[keyObj]; } } } 

最后他们会修复它: https : //connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeededID = 478521

 //bug fix, exists only in 3.5 FW, please wrap it with defines //http://dot-net-expertise.blogspot.com/2009/10/cookiecontainer-domain-handling-bug-fix.html if(!value.Contains("://www.")) //we are going to hit the bug { string urlWWW = value.Replace("://", "://www."); Uri uriWWW = new Uri(urlWWW); foreach (Cookie c in _cookieContainer.GetCookies(uriWWW)) if (c.Domain.StartsWith(".")) request.Headers["Cookies"] += c.Name + "=" + c.Value + ";"; //manually add the cookies } //~bug fix 

这个问题让我失去了一天。 CallMeLaNN的回复对我没有帮助(我正在使用.Net 4.5)。 在我的情况下,问题是为了设置请求和设置cookie的主体。

在这种情况下,cookie不会发送到服务器:

  var response = (HttpWebRequest)WebRequest.Create("http://localhost:4433/"); using (var requestStream = response.GetRequestStream()) { using (var streamWriter = new StreamWriter(requestStream)) { requestStream.Write(RequestContent); } } response.CookieContainer.Add(new Cookie("Name", "Value")); await response.GetResponseAsync(); 

要使其工作,需要更改订单:

  var response = (HttpWebRequest)WebRequest.Create("http://localhost:4433/"); response.CookieContainer.Add(new Cookie("Name", "Value")); await response.GetResponseAsync(); using (var requestStream = response.GetRequestStream()) { using (var streamWriter = new StreamWriter(requestStream)) { requestStream.Write(RequestContent); } } 

我已经针对此问题创建了一个适用于Windows 10 / UWP / .NET Core应用程序的修复程序。 问题是CookieContainer的内部结构是不同的,但就像它们在.NET Framework中一样糟糕。 因此,已接受的解决方案不再适用。

但是我没有“修复” CookieContainer ,而是编写了一个GetCookies()版本, GetCookies()使用字符串获取特定域的所有cookie,无论它们的“安全”状态如何,或者它们都带有一个前缀。 您可以根据自己的需要随意修改它,我将看到在未来的.NET Core版本中实现它的一个版本。

 using System.Collections.Generic; using System.Reflection; namespace System.Net { ///  /// Contains extensions for the  class. ///  public static class CookieContainerExtensions { ///  /// Uses Reflection to get ALL of the Cookies where  /// contains part of the specified string. Will return cookies for any subdomain, as well as dotted-prefix cookies. ///  /// The  to extract the Cookies from. /// The string that contains part of the domain you want to extract cookies for. ///  public static IEnumerable GetCookies(this CookieContainer cookieContainer, string domain) { var domainTable = GetFieldValue(cookieContainer, "_domainTable"); foreach (var entry in domainTable) { string key = GetPropertyValue(entry, "Key"); if (key.Contains(domain)) { var value = GetPropertyValue(entry, "Value"); var internalList = GetFieldValue>(value, "_list"); foreach (var li in internalList) { foreach (Cookie cookie in li.Value) { yield return cookie; } } } } } ///  /// Gets the value of a Field for a given object instance. ///  /// The  you want the value to be converted to when returned. /// The Type instance to extract the Field's data from. /// The name of the Field to extract the data from. ///  internal static T GetFieldValue(object instance, string fieldName) { BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static; FieldInfo fi = instance.GetType().GetField(fieldName, bindFlags); return (T)fi.GetValue(instance); } ///  /// Gets the value of a Property for a given object instance. ///  /// The  you want the value to be converted to when returned. /// The Type instance to extract the Property's data from. /// The name of the Property to extract the data from. ///  internal static T GetPropertyValue(object instance, string propertyName) { var pi = instance.GetType().GetProperty(propertyName); return (T)pi.GetValue(instance, null); } } } 

这是一个克服这个错误的黑客: http : //social.microsoft.com/Forums/en-US/netfxnetcom/thread/1297afc1-12d4-4d75-8d3f-7563222d234c它使用reflection。