【问题标题】:CookieContainer handling of paths (Who ate my cookie?)CookieContainer 处理路径(谁吃了我的 cookie?)
【发布时间】:2011-04-12 13:59:02
【问题描述】:

我正在从事一个涉及一些基本网络抓取的项目。我一直在非常成功地使用 HttpWebRequest 和 HttpWebResponse。对于 cookie 处理,我每次只有一个 CookieContainer 分配给 HttpWebRequest.CookieContainer 。我每次都会自动填充新的 cookie,不需要我进行额外的处理。这一切都运行良好,直到不久前曾经工作的网站之一突然停止工作。我有理由确定这是 cookie 的问题,但我没有记录 cookie 从它过去工作时起的记录,所以我不能 100% 确定。

我已经设法使用以下代码模拟了这个问题:

CookieContainer cookieJar = new CookieContainer();

Uri uri1 = new Uri("http://www.somedomain.com/some/path/page1.html");
CookieCollection cookies1 = new CookieCollection();
cookies1.Add(new Cookie("NoPathCookie", "Page1Value"));
cookies1.Add(new Cookie("CookieWithPath", "Page1Value", "/some/path/"));

Uri uri2 = new Uri("http://www.somedomain.com/some/path/page2.html");
CookieCollection cookies2 = new CookieCollection();
cookies2.Add(new Cookie("NoPathCookie", "Page2Value"));
cookies2.Add(new Cookie("CookieWithPath", "Page2Value", "/some/path/"));

Uri uri3 = new Uri("http://www.somedomain.com/some/path/page3.html");

// Add the cookies from page1.html
cookieJar.Add(uri1, cookies1);

// Add the cookies from page2.html
cookieJar.Add(uri2, cookies2);

// We should now have 3 cookies
Console.WriteLine(string.Format("CookieJar contains {0} cookies", cookieJar.Count));

Console.WriteLine(string.Format("Cookies to send to page1.html: {0}", cookieJar.GetCookieHeader(uri1)));
Console.WriteLine(string.Format("Cookies to send to page2.html: {0}", cookieJar.GetCookieHeader(uri2)));
Console.WriteLine(string.Format("Cookies to send to page3.html: {0}", cookieJar.GetCookieHeader(uri3)));

这模拟访问两个页面,这两个页面都设置了两个 cookie。然后它会检查哪些 cookie 将被设置到三个页面中的每一个。

在两个cookie中,一个没有指定路径,另一个指定了路径。当未指定路径时,我假设 cookie 将被发送回该域中的任何页面,但它似乎只会被发送回该特定页面。我现在假设这是正确的,因为它是一致的。

对我来说主要问题是处理带有指定路径的 cookie。当然,如果指定了路径,则应该将 cookie 发送到该路径中包含的任何页面。因此,在上面的代码中,'CookieWithPath' 应该对 /some/path/ 中的任何页面都有效,包括 page1.html、page2.html 和 page3.html。当然,如果您注释掉两个“NoPathCookie”实例,那么“CookieWithPath”会像我预期的那样发送到所有三个页面。但是,如上包含 'NoPathCookie',则 'CookieWithPath' 只会被发送到 page2.html 和 page3.html,而不是 page1.html。

为什么会这样,是否正确?

在搜索这个问题时,我遇到了关于 CookieContainer 中域处理问题的讨论,但没有找到任何关于路径处理的讨论。

我正在使用 Visual Studio 2005 / .NET 2.0

【问题讨论】:

    标签: c# .net cookies httpwebrequest cookiecontainer


    【解决方案1】:

    当未指定路径时,我曾假设 cookie 将被发送回该域中的任何页面,但它似乎只会被发送回该特定页面。我现在假设这是正确的,因为它是一致的。

    是的,没错。无论何时未指定域或路径,它都取自当前 URI。

    好的,我们来看看CookieContainer。有问题的方法是InternalGetCookies(Uri)。这是有趣的部分:

    while (enumerator2.MoveNext())
    {
        DictionaryEntry dictionaryEntry = (DictionaryEntry)enumerator2.get_Current();
        string text2 = (string)dictionaryEntry.get_Key();
        if (!uri.AbsolutePath.StartsWith(CookieParser.CheckQuoted(text2)))
        {
            if (flag2)
            {
                break;
            }
            else
            {
                continue;
            }
        }
        flag2 = true;
        CookieCollection cookieCollection2 = (CookieCollection)dictionaryEntry.get_Value();
        cookieCollection2.TimeStamp(CookieCollection.Stamp.Set);
        this.MergeUpdateCollections(cookieCollection, cookieCollection2, port, flag, i < 0);
        if (!(text2 == "/"))
        {
            continue;
        }
        flag3 = true;
        continue;
    }
    

    enumerator2 这是一个(排序的)cookie 路径列表。它的排序方式是,更具体的路径(如/directory/subdirectory/)排在不太具体的路径(如/directory/)之前,否则 - 按字典顺序排列(/directory/page1 排在/directory/page2 之前)。

    代码实际上做了以下事情:它遍历这个 cookie 路径列表,直到找到第一个路径,即请求的 URI 路径的前缀。然后它在该路径下添加一个cookie到输出并将flag2设置为true,这意味着“好的,我终于在列表中找到了与请求的URI实际相关的位置”。之后,第一个遇到的路径(不是请求的 URI 路径的前缀)被认为是相关路径的结尾,因此代码通过执行 break 停止搜索 cookie。

    显然,这是一种防止扫描整个列表的优化,如果没有路径指向具体页面,它显然可以工作。现在,对于您的情况,路径列表如下所示:

    /some/path/page1.html
    /some/path/page2.html
    /some/path/
    

    您可以使用调试器检查,在监视窗口中查找 ((System.Net.PathList)(cookieJar.m_domainTable["www.somedomain.com"])).m_list

    因此,对于 'page1.html' URI,代码在 page2.html 项目上中断,也没有机会处理 /some/path/ 项目。

    总结:这显然是 CookieContainer 中的另一个错误。我认为应该在 connect 上报告。

    PS:每个班级的错误太多了。我只希望为这个课程编写测试的那个 MS 的人已经被解雇了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-03
      • 2012-12-20
      • 1970-01-01
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多