【问题标题】:Parsing cookies解析 cookie
【发布时间】:2015-09-08 05:15:21
【问题描述】:

我有一个自托管的 WCF 服务,其端点设置为使用 WebHttpBinding 侦听 HTTP 请求。我需要访问随这些请求传递的 cookie。我可以获得Cookie: 标头值,但我被实际解析所困。我的实现尝试是使用CookieContainer:

var container = new CookieContainer();
var uri = new Uri("http://localhost/");
container.SetCookies(uri, cookieHeader);
var cookies = container.GetCookies(uri).OfType<Cookie>();
foreach (var cookie in cookies)
{
    Console.WriteLine("{0} = {1}", cookie.Name, cookie.Value);
}

此代码的问题是 CookieContainer 期望 cookie 用逗号 (cookieHeader="c1=v1,c2=v2") 分隔,而浏览器倾向于使用分号 (cookieHeader="c1=v1;c2=v2")。由于RFC 6265 只允许使用分号作为分隔符(但旧的 RFC 允许两者都使用)我有点困惑为什么CookieContainer 只支持逗号。现在,我正在努力为这个似乎很典型的问题寻找替代解决方案。如何正确解析 cookie? ASP.NET 应该能够做到这一点,它是否为此公开了任何可公开使用的类?

【问题讨论】:

    标签: c# wcf cookies


    【解决方案1】:

    ###为什么不起作用?

    据我了解,Set-Cookie:Cookie: 标头的分隔符各不相同。如果存在多个标头,Set-Cookie: 通常会重复,而Cookie: 在单个标头中有多个 cookie。来自RFC6265

    == Server -> User Agent ==
    
    Set-Cookie: SID=31d4d96e407aad42; Path=/; Secure; HttpOnly
    Set-Cookie: lang=en-US; Path=/; Domain=example.com
    
    == User Agent -> Server ==
    
    Cookie: SID=31d4d96e407aad42; lang=en-US
    

    Set-Cookie: 标头 can be combined 通过附加以逗号分隔的每个标头来形成单个字符串:

    Set-Cookie: SID=31d4d96e407aad42; Path=/; Secure; HttpOnly,lang=en-US; Path=/; Domain=example.com
    

    CookieContainer 设计用于客户端(由用户代理),因此SetCookies(Uri, string) 方法仅解析Set-Cookie: 使用的语法。

    ###ASP.Net是怎么做到的

    ASP.Net 使用内部方法来解析Cookie: 标头,并且它似乎没有被任何公共方法公开。见HttpListenerRequest.Cookies:

    private CookieCollection ParseCookies(Uri uri, string setCookieHeader) {
        GlobalLog.Print("HttpListenerRequest#" + ValidationHelper.HashString(this) + "::ParseCookies() uri:" + uri + " setCookieHeader:" + setCookieHeader);
        CookieCollection cookies = new CookieCollection();
        CookieParser parser = new CookieParser(setCookieHeader);
        for (;;) {
            Cookie cookie = parser.GetServer();
            GlobalLog.Print("HttpListenerRequest#" + ValidationHelper.HashString(this) + "::ParseCookies() CookieParser returned cookie:" + ValidationHelper.ToString(cookie));
            if (cookie==null) {
                // EOF, done.
                break;
            }
            if (cookie.Name.Length==0) {
                continue;
            }
            cookies.InternalAdd(cookie, true);
        }
        return cookies;
    }
    

    ###那我该如何解析头部呢?

    Nancy 有一个 very concise parser,如果许可允许,可以使用它:

    private IDictionary<string, string> GetCookieData()
    {
        var cookieDictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
    
        if (!this.Headers.Cookie.Any())
        {
            return cookieDictionary;
        }
    
        var values = this.Headers["cookie"].First().TrimEnd(';').Split(';');
        foreach (var parts in values.Select(c => c.Split(new[] { '=' }, 2)))
        {
            var cookieName = parts[0].Trim();
            string cookieValue;
    
            if (parts.Length == 1)
            {
                //Cookie attribute
                cookieValue = string.Empty;
            }
            else
            {
                cookieValue = parts[1];
            }
    
            cookieDictionary[cookieName] = cookieValue;
        }
    
        return cookieDictionary;
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-03
      • 2023-04-07
      • 2017-01-09
      • 2013-03-07
      • 1970-01-01
      • 1970-01-01
      • 2013-11-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多