CookieContainer处理路径(谁吃了我的cookie?)

And*_*ndy 9 .net c# cookies httpwebrequest cookiecontainer

我正在开发一个涉及一些基本网络爬行的项目.我已经非常成功地使用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)));
Run Code Online (Sandbox Code Playgroud)

这模拟访问两个页面,两个页面都设置了两个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

tor*_*vin 2

当未指定路径时,我假设 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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

/some/path/page1.html
/some/path/page2.html
/some/path/
Run Code Online (Sandbox Code Playgroud)

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

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

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

PS:每一类的错误太多了。我只希望 MS 为这门课编写测试的人已经被解雇了。