Отображение строки cookie заголовка в CookieCollection и наоборот - PullRequest
12 голосов
/ 25 января 2011

Рассмотрим веб-ответ с этим заголовком:

Set-Cookie: sample=testCookie; Domain=.sample.com; Expires=Tue, 25-Jan-2012 00:49:29 GMT; Path=/

этот заголовок будет сопоставлен с CookieCollection в .NET. А также, когда мы имеем дело с CookieCollection, он, наконец, преобразуется в такой header string.

Я ищу способ сделать это преобразование двумя способами. Конечно, .NET есть во внутренней библиотеке. Я считаю, что любой класс, который строит объектную модель из текста и наоборот, должен поддерживать два метода (здесь CookieCollection):

// Creating cookie collection from header text
CookieCollection.TryParse(cookieHeaderString, out myCookieCollection);
// and getting the final header which would be sent by request
String cookieHeaderString = myCookieCollection.GetCookieHeaderString();

Как мне добиться этого с CookieCollection?

Ответы [ 3 ]

19 голосов
/ 28 февраля 2014

Я знаю, что на этот вопрос уже дан ответ, но вы можете использовать этот код: http://snipplr.com/view/4427/

Я выкладываю это здесь на случай, если ссылка в какой-то момент выйдет из строя:

public static CookieCollection GetAllCookiesFromHeader(string strHeader, string strHost)
{
    ArrayList al = new ArrayList();
    CookieCollection cc = new CookieCollection();
    if (strHeader != string.Empty)
    {
        al = ConvertCookieHeaderToArrayList(strHeader);
        cc = ConvertCookieArraysToCookieCollection(al, strHost);
    }
    return cc;
}


private static ArrayList ConvertCookieHeaderToArrayList(string strCookHeader)
{
    strCookHeader = strCookHeader.Replace("\r", "");
    strCookHeader = strCookHeader.Replace("\n", "");
    string[] strCookTemp = strCookHeader.Split(',');
    ArrayList al = new ArrayList();
    int i = 0;
    int n = strCookTemp.Length;
    while (i < n)
    {
        if (strCookTemp[i].IndexOf("expires=", StringComparison.OrdinalIgnoreCase) > 0)
        {
            al.Add(strCookTemp[i] + "," + strCookTemp[i + 1]);
            i = i + 1;
        }
        else
        {
            al.Add(strCookTemp[i]);
        }
        i = i + 1;
    }
    return al;
}


private static CookieCollection ConvertCookieArraysToCookieCollection(ArrayList al, string strHost)
{
    CookieCollection cc = new CookieCollection();

    int alcount = al.Count;
    string strEachCook;
    string[] strEachCookParts;
    for (int i = 0; i < alcount; i++)
    {
        strEachCook = al[i].ToString();
        strEachCookParts = strEachCook.Split(';');
        int intEachCookPartsCount = strEachCookParts.Length;
        string strCNameAndCValue = string.Empty;
        string strPNameAndPValue = string.Empty;
        string strDNameAndDValue = string.Empty;
        string[] NameValuePairTemp;
        Cookie cookTemp = new Cookie();

        for (int j = 0; j < intEachCookPartsCount; j++)
        {
            if (j == 0)
            {
                strCNameAndCValue = strEachCookParts[j];
                if (strCNameAndCValue != string.Empty)
                {
                    int firstEqual = strCNameAndCValue.IndexOf("=");
                    string firstName = strCNameAndCValue.Substring(0, firstEqual);
                    string allValue = strCNameAndCValue.Substring(firstEqual + 1, strCNameAndCValue.Length - (firstEqual + 1));
                    cookTemp.Name = firstName;
                    cookTemp.Value = allValue;
                }
                continue;
            }
            if (strEachCookParts[j].IndexOf("path", StringComparison.OrdinalIgnoreCase) >= 0)
            {
                strPNameAndPValue = strEachCookParts[j];
                if (strPNameAndPValue != string.Empty)
                {
                    NameValuePairTemp = strPNameAndPValue.Split('=');
                    if (NameValuePairTemp[1] != string.Empty)
                    {
                        cookTemp.Path = NameValuePairTemp[1];
                    }
                    else
                    {
                        cookTemp.Path = "/";
                    }
                }
                continue;
            }

            if (strEachCookParts[j].IndexOf("domain", StringComparison.OrdinalIgnoreCase) >= 0)
            {
                strPNameAndPValue = strEachCookParts[j];
                if (strPNameAndPValue != string.Empty)
                {
                    NameValuePairTemp = strPNameAndPValue.Split('=');

                    if (NameValuePairTemp[1] != string.Empty)
                    {
                        cookTemp.Domain = NameValuePairTemp[1];
                    }
                    else
                    {
                        cookTemp.Domain = strHost;
                    }
                }
                continue;
            }
        }

        if (cookTemp.Path == string.Empty)
        {
            cookTemp.Path = "/";
        }
        if (cookTemp.Domain == string.Empty)
        {
            cookTemp.Domain = strHost;
        }
        cc.Add(cookTemp);
    }
    return cc;
}

Этот код работает лучше, чем собственный анализатор файлов cookie от Microsoft, и это действительно то, что должен делать официальный анализатор файлов cookie. Я понятия не имею, почему Microsoft еще не исправила это, поскольку это очень распространенная проблема. Он будет читать файлы cookie, разделенные запятыми, и правильно анализировать все части каждого файла cookie, включая имя, срок действия, путь, значение и домен.

12 голосов
/ 25 января 2011

Я думаю, что вы ищете CookieContainer . См. Метод SetCookies.

3 голосов
/ 19 августа 2016

Вот мой класс расширения, который я использую для этого.

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Net;
using System.Text.RegularExpressions;
using System.Web;

namespace YourProjectName.Extensions
{
     public static class HttpCookieExtension
    {
         static Regex rxCookieParts = new Regex(@"(?<name>.*?)\=(?<value>.*?)\;|(?<name>\bsecure\b|\bhttponly\b)", RegexOptions.Compiled |RegexOptions.Singleline|RegexOptions.IgnoreCase);
         static Regex rxRemoveCommaFromDate = new Regex(@"\bexpires\b\=.*?(\;|$)", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.Multiline);
         public static bool GetHttpCookies(this NameValueCollection collection, int index , out List<HttpCookie> cookies)
         {
             cookies = new List<HttpCookie>();

             if (collection.AllKeys[index].ToLower() != "set-cookie") return false;
             try
             {

                 string rawcookieString = rxRemoveCommaFromDate.Replace(collection[index],  new MatchEvaluator(RemoveComma));

                 string[] rawCookies = rawcookieString.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

                 foreach (var rawCookie in rawCookies)
                 {
                    cookies.Add(rawCookie.ToHttpCookie());
                 }
                 return true;
             }
             catch (Exception)
             {

                 return false;
             }
         }


         public static bool GetHttpCookiesFromHeader(this string cookieHeader, out CookieCollection cookies)
         {
             cookies = new CookieCollection();


             try
             {

                 string rawcookieString = rxRemoveCommaFromDate.Replace(cookieHeader, new MatchEvaluator(RemoveComma));

                 string[] rawCookies = rawcookieString.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);

                 if (rawCookies.Length == 0)
                 {
                     cookies.Add(rawcookieString.ToCookie());
                 }
                 else
                 {
                    foreach (var rawCookie in rawCookies)
                    {
                        cookies.Add(rawCookie.ToCookie());
                    }
                 }

                 return true;
             }
             catch (Exception)
             {
                 throw;
             }
         }




         public static Cookie ToCookie(this string rawCookie)
         {

             if (!rawCookie.EndsWith(";")) rawCookie += ";";

             MatchCollection maches = rxCookieParts.Matches(rawCookie);

             Cookie cookie = new Cookie(maches[0].Groups["name"].Value.Trim(), maches[0].Groups["value"].Value.Trim());

             for (int i = 1; i < maches.Count; i++)
             {
                 switch (maches[i].Groups["name"].Value.ToLower().Trim())
                 {
                     case "domain":
                         cookie.Domain = maches[i].Groups["value"].Value;
                         break;
                     case "expires":

                         DateTime dt;

                         if (DateTime.TryParse(maches[i].Groups["value"].Value, out dt))
                         {
                             cookie.Expires = dt;
                         }
                         else
                         {
                             cookie.Expires = DateTime.Now.AddDays(2);
                         }
                         break;
                     case "path":
                         cookie.Path = maches[i].Groups["value"].Value;
                         break;
                     case "secure":
                         cookie.Secure = true;
                         break;
                     case "httponly":
                         cookie.HttpOnly = true;
                         break;
                 }
             }
             return cookie;


         }

         public static HttpCookie ToHttpCookie(this string rawCookie)
         {
             MatchCollection maches = rxCookieParts.Matches(rawCookie);

             HttpCookie cookie = new HttpCookie(maches[0].Groups["name"].Value, maches[0].Groups["value"].Value);

             for (int i = 1; i < maches.Count; i++)
             {
                 switch (maches[i].Groups["name"].Value.ToLower().Trim())
                 {
                     case "domain":
                         cookie.Domain = maches[i].Groups["value"].Value;
                         break;
                     case "expires":

                         DateTime dt;

                         if (DateTime.TryParse(maches[i].Groups["value"].Value, out dt))
                         {
                             cookie.Expires = dt;
                         }
                         else
                         {
                             cookie.Expires = DateTime.Now.AddDays(2);
                         }
                         break;
                     case "path":
                         cookie.Path = maches[i].Groups["value"].Value;
                         break;
                     case "secure":
                         cookie.Secure = true;
                         break;
                     case "httponly":
                         cookie.HttpOnly = true;
                         break;
                 }
             }
             return cookie;
         }

         private static KeyValuePair<string, string> SplitToPair(this string input)
         {
            string[]  parts= input.Split(new char[] {'='},StringSplitOptions.RemoveEmptyEntries);
            return new KeyValuePair<string, string>(parts[0],parts[1]);
         }

         private static string RemoveComma(Match match)
         {
             return match.Value.Replace(',', ' ');
         }
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...