Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# CookieContainer bug?_C#_Cookiecontainer - Fatal编程技术网

C# CookieContainer bug?

C# CookieContainer bug?,c#,cookiecontainer,C#,Cookiecontainer,我不知道CookieContainer是如何处理域的,所以我创建了这个测试。 此测试显示cookieContainer不会返回“example.com”的任何cookie,但根据RFC,它应该返回至少2个cookie 这不是一只虫子吗 如何使它工作 以下是有关此错误的讨论: CookieContainer getContainer() { CookieContainer结果=新建CookieContainer(); Uri=新的Uri(“http://sub.example.com"); 字

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

这不是一只虫子吗

如何使它工作

以下是有关此错误的讨论:


CookieContainer getContainer()
{
CookieContainer结果=新建CookieContainer();
Uri=新的Uri(“http://sub.example.com");
字符串cookieH=@“Test1=val;domain=sub.example.com;path=/”;
结果:SetCookies(uri,cookieH);
cookieH=@“Test2=val;domain=.example.com;path=/”;
结果:SetCookies(uri,cookieH);
cookieH=@“Test3=val;domain=example.com;path=/”;
结果:SetCookies(uri,cookieH);
返回结果;
}
无效测试()
{
CookieContainer cookie=getContainer();
lblResult.Text+=“
cookies总数:”+cookie.count+“预期为3”; Uri=新的Uri(“http://sub.example.com"); CookieCollection coll=cookie.GetCookies(uri); lblResult.Text+=“+uri+”Cookie计数的“
”:“+coll.count+”应为:2”; uri=新的uri(“http://other.example.com"); coll=cookie.GetCookies(uri); lblResult.Text+=“+uri+”Cookie计数的“
”:“+coll.count+”应为:2”; uri=新的uri(“http://example.com"); coll=cookie.GetCookies(uri); lblResult.Text+=“+uri+”Cookie计数的“
”:“+coll.count+”应为:2”; } 受保护的无效页面加载(对象发送方、事件参数e) { Test(); } CookieContainer测试页面
以下是一个绕过此错误的方法: 它使用反射。

最后他们将修复它:

我刚刚找到了此错误的修复方法,并在此处进行了讨论:

以下是解决方案:

  • 不要使用.Add(Cookie),只使用.Add(Uri,Cookie)方法
  • 每次向容器或应用程序添加cookie时,请调用BugFix_CookieDomain 在使用.GetCookie之前或在系统使用容器之前

    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];
            }
        }
    }
    

  • 在这个问题上我失去了一天。CallMeLaNN的回答对我没有帮助(我正在使用.NET4.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核心应用程序上运行。问题在于
    CookieContainer
    的内部结构不同,但与.NET框架中的内部结构一样糟糕。因此,公认的解决方案不再有效

    但是,我没有“修复”CookieContainer,而是编写了一个版本的
    GetCookies()
    ,它用一个字符串获取特定域的所有Cookie,而不管它们的“安全”状态如何,或者它们是否以点为前缀。您可以根据自己的需要随意修改它,我将考虑在未来的.NET核心版本中实现它的一个版本

    using System.Collections.Generic;
    using System.Reflection;
    
    namespace System.Net
    {
    
        /// <summary>
        /// Contains extensions for the <see cref="CookieContaner"/> class.
        /// </summary>
        public static class CookieContainerExtensions
        {
    
            /// <summary>
            /// Uses Reflection to get ALL of the <see cref="Cookie">Cookies</see> where <see cref="Cookie.Domain"/> 
            /// contains part of the specified string. Will return cookies for any subdomain, as well as dotted-prefix cookies. 
            /// </summary>
            /// <param name="cookieContainer">The <see cref="CookieContainer"/> to extract the <see cref="Cookie">Cookies</see> from.</param>
            /// <param name="domain">The string that contains part of the domain you want to extract cookies for.</param>
            /// <returns></returns>
            public static IEnumerable<Cookie> GetCookies(this CookieContainer cookieContainer, string domain)
            {
                var domainTable = GetFieldValue<dynamic>(cookieContainer, "_domainTable");
                foreach (var entry in domainTable)
                {
                    string key = GetPropertyValue<string>(entry, "Key");
    
                    if (key.Contains(domain))
                    {
                        var value = GetPropertyValue<dynamic>(entry, "Value");
    
                        var internalList = GetFieldValue<SortedList<string, CookieCollection>>(value, "_list");
                        foreach (var li in internalList)
                        {
                            foreach (Cookie cookie in li.Value)
                            {
                                yield return cookie;
                            }
                        }
                    }
                }
            }
    
            /// <summary>
            /// Gets the value of a Field for a given object instance.
            /// </summary>
            /// <typeparam name="T">The <see cref="Type"/> you want the value to be converted to when returned.</typeparam>
            /// <param name="instance">The Type instance to extract the Field's data from.</param>
            /// <param name="fieldName">The name of the Field to extract the data from.</param>
            /// <returns></returns>
            internal static T GetFieldValue<T>(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);
            }
    
            /// <summary>
            /// Gets the value of a Property for a given object instance.
            /// </summary>
            /// <typeparam name="T">The <see cref="Type"/> you want the value to be converted to when returned.</typeparam>
            /// <param name="instance">The Type instance to extract the Property's data from.</param>
            /// <param name="propertyName">The name of the Property to extract the data from.</param>
            /// <returns></returns>
            internal static T GetPropertyValue<T>(object instance, string propertyName)
            {
                var pi = instance.GetType().GetProperty(propertyName);
                return (T)pi.GetValue(instance, null);
            }
    
        }
    
    }
    
    使用System.Collections.Generic;
    运用系统反思;
    命名空间系统.Net
    {
    /// 
    ///包含类的扩展。
    /// 
    公共静态类CookieContaineExtensions
    {
    /// 
    ///使用反射获取所有cookie,其中
    ///包含指定字符串的一部分。将返回任何子域的Cookie以及虚线前缀Cookie。
    /// 
    ///要从中提取Cookies的。
    ///包含要为其提取Cookie的域的一部分的字符串。
    /// 
    公共静态IEnumerable GetCookies(此CookieContainer CookieContainer,字符串域)
    {
    var domainTable=GetFieldValue(cookieContainer,“\u domainTable”);
    foreach(域中的var条目)
    {
    字符串键=GetPropertyValue(输入,“键”);
    if(key.Contains(域))
    {
    var值=GetPropertyValue(输入,“值”);
    var internalList=GetFieldValue(值“_list”);
    foreach(内部列表中的var li)
    {
    foreach(li.Value中的Cookie)
    {
    收益率;
    }
    }
    }
    }
    }
    /// 
    ///获取给定对象实例的字段值。
    /// 
    ///返回时要将值转换为的值。
    ///要从中提取字段数据的类型实例。
    ///要从中提取数据的字段的名称。
    /// 
    内部静态T GetFieldValue(对象实例,字符串fieldName)
    {
    BindingFlags bindFlags=BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
    FieldInfo fi=instance.GetType().GetField(fieldName,bindFlags);
    返回(T)fi.GetValue(实例);
    }
    /// 
    ///获取给定对象实例的属性值。
    /// 
    ///返回时要将值转换为的值。
    ///要从中提取属性数据的类型实例。
    ///要从中提取数据的属性的名称。
    /// 
    内部静态T GetPropertyValue(对象实例,字符串propertyName)
    {
    var pi=instance.GetType().GetProperty(propertyName);
    返回(T)pi.GetValue(实例,null);
    }
    }
    }
    
    我以前也尝试过很多次。最后我自己读取了cookie头并将其存储在其他地方。我必须使用CookieContainer,因为这是将cookie发送到HttpWebRequest的唯一方法。真不敢相信我最终出现了一个场景,将框架从4.0更改为3.5(我没有使用4.0的东西)破坏了我的程序。我是这么想的
                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);
                   }
                }
    
    using System.Collections.Generic;
    using System.Reflection;
    
    namespace System.Net
    {
    
        /// <summary>
        /// Contains extensions for the <see cref="CookieContaner"/> class.
        /// </summary>
        public static class CookieContainerExtensions
        {
    
            /// <summary>
            /// Uses Reflection to get ALL of the <see cref="Cookie">Cookies</see> where <see cref="Cookie.Domain"/> 
            /// contains part of the specified string. Will return cookies for any subdomain, as well as dotted-prefix cookies. 
            /// </summary>
            /// <param name="cookieContainer">The <see cref="CookieContainer"/> to extract the <see cref="Cookie">Cookies</see> from.</param>
            /// <param name="domain">The string that contains part of the domain you want to extract cookies for.</param>
            /// <returns></returns>
            public static IEnumerable<Cookie> GetCookies(this CookieContainer cookieContainer, string domain)
            {
                var domainTable = GetFieldValue<dynamic>(cookieContainer, "_domainTable");
                foreach (var entry in domainTable)
                {
                    string key = GetPropertyValue<string>(entry, "Key");
    
                    if (key.Contains(domain))
                    {
                        var value = GetPropertyValue<dynamic>(entry, "Value");
    
                        var internalList = GetFieldValue<SortedList<string, CookieCollection>>(value, "_list");
                        foreach (var li in internalList)
                        {
                            foreach (Cookie cookie in li.Value)
                            {
                                yield return cookie;
                            }
                        }
                    }
                }
            }
    
            /// <summary>
            /// Gets the value of a Field for a given object instance.
            /// </summary>
            /// <typeparam name="T">The <see cref="Type"/> you want the value to be converted to when returned.</typeparam>
            /// <param name="instance">The Type instance to extract the Field's data from.</param>
            /// <param name="fieldName">The name of the Field to extract the data from.</param>
            /// <returns></returns>
            internal static T GetFieldValue<T>(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);
            }
    
            /// <summary>
            /// Gets the value of a Property for a given object instance.
            /// </summary>
            /// <typeparam name="T">The <see cref="Type"/> you want the value to be converted to when returned.</typeparam>
            /// <param name="instance">The Type instance to extract the Property's data from.</param>
            /// <param name="propertyName">The name of the Property to extract the data from.</param>
            /// <returns></returns>
            internal static T GetPropertyValue<T>(object instance, string propertyName)
            {
                var pi = instance.GetType().GetProperty(propertyName);
                return (T)pi.GetValue(instance, null);
            }
    
        }
    
    }