【问题标题】:SetCookie method of CookieContainer throws exceptionCookieContainer 的 SetCookie 方法抛出异常
【发布时间】:2014-03-21 21:08:57
【问题描述】:

我在 Set-Cookie 标头中从网络服务器返回了这个 cookie:

PHPSESSID=462rutd8g0sbg9sinh3hqa2ol6; 路径=/,wordpress_test_cookie=WP+Cookie+检查; 路径=/,wordpress_ca07030412dd7fcd4dbeaae0bd9f5df9=testemail@example.com; expires=星期日,2012 年 7 月 1 日 05:11:02 GMT;路径=/wp-内容/插件; httponly,wordpress_ca07030412dd7fcd4dbeaae0bd9f5df9=testemail@example.com; expires=星期日,2012 年 7 月 1 日 05:11:02 GMT;路径=/wp-admin; httponly,wordpress_logged_in_ca07030412dd7fcd4dbeaae0bd9f5df9=testemail@example.com; expires=星期日,2012 年 7 月 1 日 05:11:02 GMT;路径=/;仅限http

我正在尝试使用CookieContainer.SetCookies(new Uri(url),cookie);

但它会抛出异常'{“解析Uri 'http://www.smallbizads.us/'的Cookie标头时发生错误。”} System.FormatException {System.Net.CookieException'

一些挖掘表明 SetCookies 使用 , 来分解 cookie。但这显然行不通,因为我有 Expires 标头,它也有 ,

知道如何解决这个问题吗?

注意:由于 Wordpress 问题,我只能通过从 Set-Cookie 标头获取 cookie 来使用此方法。所以请不要建议任何其他选择。

【问题讨论】:

    标签: c# .net wordpress httpwebrequest webrequest


    【解决方案1】:

    我花了一些时间来剖析它。

    据我所知,您希望为多个路径设置由 WordPress 为一个域 (.smallbizads.us) 生成的 PHPSESSID(PHP 会话 ID)。有效期始终相同。

    首先获取 cookie 标头:

    string cookieHeader = "PHPSESSID=462rutd8g0sbg9sinh3hqa2ol6; ...etc;"
    

    用';'分割它分隔符。

    var cookies = cookieHeader.Split(new[] {';'}).ToList();
    

    你最终得到了一个包含 12 个项目的列表。例如:

    • “PHPSESSID=462rutd8g0sbg9sinh3hqa2ol6”
    • " path=/,wordpress_test_cookie=WP+Cookie+check"
    • " expires=Sun, 01-Jul-2012 05:11:02 GMT"
    • ...

    到期日期在此列表中多次显示,但始终具有相同的值。 只需获取第一个到期日期并将其转换为 DateTime。

    var expiresValue = (from c in cookies
                        where c.Trim().StartsWith("expires")
                        select c).First();
    var expiresOn = DateTime.Parse(expiresValue.Substring(expiresValue.IndexOf('=') + 1));
    

    好的,现在让我们获取 cookie 的值。会话 ID:

    var sessionId = (from c in cookies
                     where c.Trim().StartsWith("PHPSESSID")
                     select c).Single();
    sessionId = sessionId.Substring(sessionId.IndexOf('=') + 1);
    

    现在获取需要设置 cookie 的路径。

    var paths = (from c in cookies
                 where c.Trim().StartsWith("path=")
                 select c).ToList();
    

    现在您可以使用 CookieContainer 和 System.Net.Cookie 类设置 cookie。

    foreach (var path in paths)
    {
        var cookie = new Cookie();
        cookie.Name = "PHPSESSID";
        cookie.Value = sessionId;
        cookie.Domain = ".smallbizads.us";
        cookie.Expires = expiresOn;
        cookie.HttpOnly = true;
    
        var container = new CookieContainer();
    
        var startIndex = path.IndexOf('=') + 1;
        var stopIndex = path.Contains(',') ? path.IndexOf(',') : path.Length;
        cookie.Path = path.Substring(startIndex, stopIndex - startIndex);
    
        container.Add(cookie);
    }
    

    【讨论】:

      【解决方案2】:

      请注意,星期几不会添加任何额外信息,并且可以在没有它的情况下解析日期,我们可以使用正则表达式来删除日期和逗号。这是用于代替CookieContainer.SetCookies() 的扩展方法。

      /// <summary>
      /// Although it's invalid, in the wild we sometimes see a Set-Cookie header with the form "Name=Value; expires=Sun, 23-Dec-2012 12:25:37 GMT".
      /// Multiple cookies can be set with one header, comma separated, so CookieContainer.SetCookies() can't parse this due to the comma in the date.
      /// Fortunately, the DayOfWeek provides no useful information, and the date can be parsed without it, so this removes the day and comma.
      /// </summary>
      public static void SetCookiesWithExpires(this CookieContainer cookies, Uri uri, String cookieHeader) {
          // Note: The Regex may be created more than once in different threads. No problem; all but the last will be garbage collected.
          Regex expiresEqualsDay = _expiresEqualsDay ?? (_expiresEqualsDay = new Regex(EXPIRES_EQUALS_DAY_PATTERN, RegexOptions.IgnoreCase | RegexOptions.Compiled));
          cookies.SetCookies(uri, expiresEqualsDay.Replace(cookieHeader, EXPIRES_EQUALS));
      }
      private static Regex _expiresEqualsDay;     // Lazy-initialized.
      private const String EXPIRES_EQUALS_DAY_PATTERN = "; *expires=[A-Za-z]+, *";
      private const String EXPIRES_EQUALS = "; Expires=";
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-10-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-17
        相关资源
        最近更新 更多