帮助.NET CookieContainer

时间:2009-12-02 17:30:36

标签: c# cookies

我最近遇到了CookieContainer的一些问题。要么我做了严重的错误,要么有一些与CookieContainer对象有关的错误。它似乎没有使用某些Set-Cookie标头更新cookie集合。

这可能是一个冗长的帖子,我道歉,但我希望尽可能地做到这一点,所以我将列出我的HTTP嗅探日志以及我的实际实现代码。

    public bool SendRequest(HttpWebRequest request, IDictionary<string, string> data, int retries)
    {
        // copy request in case request instance already failed
        HttpWebRequest newRequest = (HttpWebRequest)HttpWebRequest.Create(request.RequestUri);
        newRequest.Method = request.Method;

        // if POST data was provided, write it to the stream
        if (data != null && data.Count != 0)
        {
            StreamWriter writer = new StreamWriter(newRequest.GetRequestStream());
            writer.Write(createPostString(data));
            writer.Close();
        }

        // set request with global cookie container
        newRequest.CookieContainer = this.cookieJar;

        try
        {
            using (HttpWebResponse resp = (HttpWebResponse)newRequest.GetResponse())
            {
                //CookieCollection newCooks = getCookies(resp.Headers);
                //updateCookies(newCooks);
                this.cookieJar = newRequest.CookieContainer;
                this.Html = getResponseString(resp);

             /* remainder snipped */


所以有代码,这里有两个我在Fiddler中嗅到的回复请求:


请求1

POST /login/ HTTP/1.1
Host: www.site.com
Content-Length: 47
Expect: 100-continue
Connection: Keep-Alive

回复1

HTTP/1.1 200 OK
Date: Wed, 02 Dec 2009 17:03:35 GMT
Server: Apache
Set-Cookie: tcc=one; path=/
Set-Cookie: cust_id=2702585226; domain=.site.com; path=/; expires=Mon, 01-Jan-2011 00:00:00 GMT
Set-Cookie: cust_session=12%2F2%2F2009%20%2012%3A3%3A35; domain=.site.com; path=/; expires=Wed 2-Dec-2009  17:33:35
Set-Cookie: refer_id_persistent=0000; domain=.site.com; path=/; expires=Fri 2-Dec-2011  17:3:35
Set-Cookie: refer_id=0000; domain=.site.com; path=/
Set-Cookie: private_browsing_mode=off; domain=.site.com; path=/; expires=Fri, 01-Jan-2010 17:03:35 GMT
Set-Cookie: member_session=UmFuZG9tSVYL%5BS%5D%5BP%5DfhH77bYaVoS9j9Yd8ySRkyHHz%5BS%5Dk0S8MVsQ6AyraNlcdcCRC0RkB%5BP%5DfBYVM4vn6JQ3HlJxT3GlJi1RZiMGQaITg7HN9dpu9oRbZgMjhJlXXa%5BP%5D7pFSjqDIZWRr3LAfnhh3btv4E3rvVH42CeOP%5BS%5Dx6kDyvrokQEHyIHPGi7zswZbuHrUdx2XKEKKJzw1unDWfw0LZWjoehAs0QgSOz6Nzp8P4Hp8hqrULdIMch6acPT%5BS%5DbKV8zwugBIcjr5dI3rVR%5BP%5Dv42rsTtQB7dyb%5BP%5DRKb8Y83cGqhHM33hP%5BP%5DUtmbDC1PPfr%5BS%5DPC23lAO%5BS%5DmQ3mOy9x4pgQSOfp40XSfzgVg3EavITaxHBeI5nO3%5BP%5D%5BS%5D2rSDthDfuEm4sT9i6UF3sYd1vlOL0IC9ZsVatV1yhhpQ%5BE%5D%5BE%5D; domain=.site.com; path=/; expires=Fri, 01-Jan-2010 17:03:35 GMT
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8

请求2

GET /test?search=jjkjf HTTP/1.1
Host: www.site.com
Cookie: tcc=one; cust_id=2702585226; private_browsing_mode=off; member_session=UmFuZG9tSVYL%5BS%5D%5BP%5DfhH77bYaVoS9j9Yd8ySRkyHHz%5BS%5Dk0S8MVsQ6AyraNlcdcCRC0RkB%5BP%5DfBYVM4vn6JQ3HlJxT3GlJi1RZiMGQaITg7HN9dpu9oRbZgMjhJlXXa%5BP%5D7pFSjqDIZWRr3LAfnhh3btv4E3rvVH42CeOP%5BS%5Dx6kDyvrokQEHyIHPGi7zswZbuHrUdx2XKEKKJzw1unDWfw0LZWjoehAs0QgSOz6Nzp8P4Hp8hqrULdIMch6acPT%5BS%5DbKV8zwugBIcjr5dI3rVR%5BP%5Dv42rsTtQB7dyb%5BP%5DRKb8Y83cGqhHM33hP%5BP%5DUtmbDC1PPfr%5BS%5DPC23lAO%5BS%5DmQ3mOy9x4pgQSOfp40XSfzgVg3EavITaxHBeI5nO3%5BP%5D%5BS%5D2rSDthDfuEm4sT9i6UF3sYd1vlOL0IC9ZsVatV1yhhpQ%5BE%5D%5BE%5D

<小时/> 正如您所看到的,用于每个请求的CookieContainer(this.cookieJar)都没有为refer_id,cust_session,refer_id_persistent选择Set-Cookie标头。然而它确实接收了cust_id,private_browsing_mode,tcc和member_session ...任何想法为什么会这样?

6 个答案:

答案 0 :(得分:8)

只是想更新这篇文章以防其他人遇到这个帖子。问题是.NET符合cookie标签的RFC规范,但不是所有站点都遵守。因此,问题最终不是微软或.NET。 (虽然,IE,管理cookie很好,所以最好使用相同的解析方法重写他们的.NET cookie解析方法)问题是不遵循RFC specifications的网站。

尽管如此,我经常遇到的一个问题是网站会在其Cookie中的过期日期使用逗号。 .NET将这些解释为不同cookie字段之间的分隔符,并在cookie结束后删除结尾和所有内容。

RFC spec:“Cookie:,后跟逗号分隔的一个或多个Cookie列表。”对于此问题,一个简单的解决方案是Web服务器根据RFC文档用逗号分隔值。但是,没有RFC警察,所以我们只能希望人们遵守规则。

答案 1 :(得分:3)

MSDN SetCookies: SetCookies从HTTP cookie头中提取所有HTTP cookie,为每个cookie构建一个Cookie,然后将每个Cookie添加到与URI关联的内部CookieCollection中。 CookieHeader字符串中的HTTP Cookie必须以逗号分隔

MSDN GetCookieHeader GetCookieHeader返回一个字符串,其中包含uri指定的Cookie实例的HTTP cookie标头。通过添加与uri关联的每个Cookie的字符串表示来构建HTTP标头。请注意,字符串的确切格式取决于Cookie符合的RFC。与uri关联的所有Cookie实例的字符串将合并为以分号分隔。

此字符串的格式不正确,无法用作SetCookies方法的第二个参数。

答案 2 :(得分:1)

这只是对您的代码进行快速扫描,但您似乎在发送请求中的Cookie之前发送了帖子数据。

   if (data != null && data.Count != 0)
    {
        StreamWriter writer = new StreamWriter(newRequest.GetRequestStream());
        writer.Write(createPostString(data));
        writer.Close();
    }

    // set request with global cookie container
    newRequest.CookieContainer = this.cookieJar;

当您将发布数据写入流时,可能会发生这种情况,并将其发送到远程服务器。但是,要设置cookie,必须在任何postdata之前将其发送到服务器。简单的解决方案就是这样交换:

 // set request with global cookie container
 newRequest.CookieContainer = this.cookieJar;

 if (data != null && data.Count != 0)
    {
        StreamWriter writer = new StreamWriter(newRequest.GetRequestStream());
        writer.Write(createPostString(data));
        writer.Close();
    }

答案 3 :(得分:1)

CookieContainer有两个我遇到的主要问题,无论是设计还是我不知道的bug。

1)未收到在302帖子上设置的Cookie。 实施例

 Post to site
  302 redirect response
  Load New page which sets cookie

解  将autoredirect设置为false并手动跟踪重定向并自行设置cookie

2).Net对于在字符串中使用逗号的incorectly形成cookie字符串非常挑剔。这实际上是正确的,但偶尔cookie的日期设置包括一个逗号,它会停止所有设置的cookie。

解  手动解析cookie字符串并添加自己。一项可怕的任务。我有一个乱糟糟的黑客功能,循环和ifs但最终的结果是它适用于我迄今为止抛出的所有情况。 IT并不漂亮,但它可以完成工作

不确定以上是你的问题,但也许。如果不是一些值得思考的东西

答案 4 :(得分:1)

我的解决方案:将“UTC”替换为“GMT”。

答案 5 :(得分:0)

尝试使用CookieContainer.GetCookieHeader和CookieContainer.SetCookies

YourCookieContainer.GetCookieHeader(new Uri("your url"));

YourCookieContainer.SetCookies(new Uri("your url"), "string from GetCookieHeader");