2

我正在使用HttpWebRequestHttpWebResponse抓取一个网站。我CookieContainer对每个请求都使用相同的,以确保自动处理 cookie。

但是,其中一个请求需要特定的 cookie,该 cookie 在先前的响应中设置。虽然这存在于集合中,但其Path属性似乎不正确。根据RFC2109(第 7 页),当 cookie 设置为空白路径(就像这个一样)时,路径应设置为请求的 URL,直到但不包括最后的斜杠。实际发生的情况是它被设置为整个URL 路径,这意味着 cookie 不能随后被同一子域中的不同 URL 读取。

一个例子:

  1. 我在http://www.myserver.com/sub/mypage.php请求页面
  2. 响应包含一个Set-Cookie标头,其内容为mycookie=12345; 到期=格林威治标准时间 2012 年 6 月 27 日星期三 16:20:00
  3. cookie 被添加到 .NET CookieCollection。由于没有设置路径,路径被错误地初始化为/sub/mypage.php
  4. 我请求同一子域下的另一个页面,但它需要 mycookie cookie,例如http://www.myserver.com/sub/anotherpage.php
  5. .NET 不提供 cookie,因为路径不完全匹配。如果路径是/sub,它将被正确地提供

我使用带有 Firebug 和 Firecookie 扩展的 Firefox 浏览器执行了相同的导航步骤。在实际浏览器会话中,路径设置正确,即子域。

任何人都可以确认这一点并可能指出我解决此问题的方法或解决方法吗?非常感谢。

4

1 回答 1

3

这是有问题的内部代码。看起来不像是一个意外的错误。如果问题不符合标准,您应该报告问题。

switch (this.m_cookieVariant)
{
    case CookieVariant.Plain:
        this.m_path = absolutePath;
        break;

    case CookieVariant.Rfc2109:
        this.m_path = absolutePath.Substring(0, absolutePath.LastIndexOf('/'));
        break;

    default:
        this.m_path = absolutePath.Substring(0, absolutePath.LastIndexOf('/') + 1);
        break;
}

因此,除非 cookie 本身另有说明,否则它使用普通 cookie 变体。

您将不得不遍历所有 cookie 检查。真的,这是我讨厌 .net 的 cookie 处理的众多原因之一。无法轻松获取所有域/cookie。最简单的解决方法是执行以下操作。但是,您最终会得到重复的 cookie。因此,您可能希望通过 uri 获取 cookie。

public static CookieCollection FixCookies(CookieCollection collection)
{
    foreach (Cookie cookie in collection)
    {
        if (string.IsNullOrEmpty(cookie.Path))
            continue;

        int idx = cookie.Path.LastIndexOf('/');
        if (idx == -1)
            continue;

        cookie.Path = cookie.Path.Substring(0, idx);
    }
    return collection;
}

[STAThread]
private static void Main(string[] args)
{
    var http = (HttpWebRequest)WebRequest.Create("http://localhost/test/test.php");
    http.CookieContainer = new CookieContainer();
    var resp = (HttpWebResponse)http.GetResponse();
    http.CookieContainer.Add(FixCookies(resp.Cookies));
}
于 2012-06-27T18:07:38.923 回答