1

我在 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;路径=/; httponly

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

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

一些挖掘显示 SetCookies 使用 , 来分解 cookie。但这显然不起作用,因为我有 Expires 标头,它也有,

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

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

4

2 回答 2

3

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

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

首先,您获取 cookie 标头:

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

用';'分割它 分隔符。

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

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

  • “PHPSESSID=462rutd8g0sbg9sinh3hqa2ol6”
  • " 路径=/,wordpress_test_cookie=WP+Cookie+检查"
  • “ expires=星期日,2012 年 7 月 1 日 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);
}
于 2012-06-17T06:28:55.147 回答
0

请注意,星期几不会添加其他信息,并且可以在没有它的情况下解析日期,我们可以使用正则表达式来删除日期和逗号。这是用于代替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=";
于 2012-12-26T15:41:06.043 回答