2013-04-13 1 views
16

나는 Newtonsoft.Json를 사용하여 JSON에 CookieContainer를 내보낼하지만 불행히도 CookieContainer하는 열거 나 물건을 가지고하지, 그래서 그것을 순환을 할 수 없습니다CookieContainer의 쿠키를 모두 얻으려면 어떻게해야합니까? 내 게시 된 솔루션을</strong>는 것 :</p> <p><strong>편집 ...

private static void Main(string[] args) 
{ 
    CookieContainer cookieContainer = new CookieContainer(); 
    cookieContainer.Add(new Cookie("name1", "value1", "/", ".testdomain1.com")); 
    cookieContainer.Add(new Cookie("name2", "value1", "/path1/", ".testdomain1.com")); 
    cookieContainer.Add(new Cookie("name2", "value1", "/path1/path2/", ".testdomain1.com")); 
    cookieContainer.Add(new Cookie("name1", "value1", "/", ".testdomain2.com")); 
    cookieContainer.Add(new Cookie("name2", "value1", "/path1/", ".testdomain2.com")); 
    cookieContainer.Add(new Cookie("name2", "value1", "/path1/path2/", ".testdomain2.com")); 

    CookieCollection cookies = GetAllCookies(cookieContainer); 

    Console.WriteLine(JsonConvert.SerializeObject(cookies, Formatting.Indented)); 
    Console.Read(); 
} 
+1

리플렉션을 사용하여 CookieContainer의 비공개 필드에 액세스하는 것 외에는 모든 쿠키를 가져 오는 방법이 없다고 생각합니다. (권장하지 않습니다). 쿠키를 별도로 저장하고 필요할 때 CookieContainer에 저장해야합니다. – Will

답변

15

해결책 사용하여 반사 :

public static CookieCollection GetAllCookies(CookieContainer cookieJar) 
{ 
    CookieCollection cookieCollection = new CookieCollection(); 

    Hashtable table = (Hashtable) cookieJar.GetType().InvokeMember("m_domainTable", 
                    BindingFlags.NonPublic | 
                    BindingFlags.GetField | 
                    BindingFlags.Instance, 
                    null, 
                    cookieJar, 
                    new object[] {}); 

    foreach (var tableKey in table.Keys) 
    { 
     String str_tableKey = (string) tableKey; 

     if (str_tableKey[0] == '.') 
     { 
      str_tableKey = str_tableKey.Substring(1); 
     } 

     SortedList list = (SortedList) table[tableKey].GetType().InvokeMember("m_list", 
                    BindingFlags.NonPublic | 
                    BindingFlags.GetField | 
                    BindingFlags.Instance, 
                    null, 
                    table[tableKey], 
                    new object[] { }); 

     foreach (var listKey in list.Keys) 
     { 
      String url = "https://" + str_tableKey + (string) listKey; 
      cookieCollection.Add(cookieJar.GetCookies(new Uri(url))); 
     } 
    } 

    return cookieCollection; 
} 
+0

이 코드는 https 쿠키 만 인쇄하고 http는 무시합니다. 여기에서 개선 된 버전 : http://stackoverflow.com/a/36665793/2010764 –

+0

http 웹 사이트에서이 방법을 사용하고 있습니다. 그것은 잘 작동하고 모든 http 쿠키를 반환합니다. 하지만 https를 http로 변경하면 모든 쿠키가 인쇄되지 않고 메인 도메인에있는 쿠키 만 인쇄됩니다. – Milad

6

첫 번째 대답은 휴대용 프로젝트를 위해 작동하지 않았다 같은 것을합니다. 그래서 여기 또한 나는 또한

var domainTableField = container.GetType().GetRuntimeField("m_domainTable"); 

을 시도했지만이 null 반환 반사

using System.Linq; 
using System.Collections; 
using System.Reflection; 
using System.Net; 

    public static CookieCollection GetAllCookies(this CookieContainer container) 
    { 
     var allCookies = new CookieCollection(); 
     var domainTableField = container.GetType().GetRuntimeFields().FirstOrDefault(x => x.Name == "m_domainTable");    
     var domains = (IDictionary)domainTableField.GetValue(container); 

     foreach (var val in domains.Values) 
     { 
      var type = val.GetType().GetRuntimeFields().First(x => x.Name == "m_list"); 
      var values = (IDictionary)type.GetValue(val); 
      foreach (CookieCollection cookies in values.Values) 
      { 
       allCookies.Add(cookies);      
      } 
     }   
     return allCookies; 
    } 

1) 사용 옵션이 있습니다.

2) 도메인을 통해 반복 할 수 있습니다. 키 및 모든 키에 대해 container.GetCookies()를 사용합니다. 그러나 GetCookies가 Uri를 기대하고 모든 키가 Uri 패턴과 일치하지 않기 때문에 문제가있었습니다.

4

이 방법에 상관없이 프로토콜이 무엇인지, 모든 쿠키를 얻을 수 있도록 없습니다 :

public static IEnumerable<Cookie> GetAllCookies(this CookieContainer c) 
{ 
    Hashtable k = (Hashtable)c.GetType().GetField("m_domainTable", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(c); 
    foreach (DictionaryEntry element in k) 
    { 
     SortedList l = (SortedList)element.Value.GetType().GetField("m_list", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(element.Value); 
     foreach (var e in l) 
     { 
      var cl = (CookieCollection)((DictionaryEntry)e).Value; 
      foreach (Cookie fc in cl) 
      { 
       yield return fc; 
      } 
     } 
    } 
} 
0

사용 CookieContainer.GetCookies Method

CookieCollection cookies = cookieContainer.GetCookies(new Uri(url)); 

url 사이트의 URL이입니다.

필자의 경우 다른 답변에서 제안한 것처럼 리플렉션을 사용할 수 없었습니다. 그러나 쿼리 할 사이트의 URL을 알았습니다. 컨테이너가 모든 쿠키를 맹목적으로 반환하지는 않지만 쿠키는 항상 특정 URL에 속하고 관련 도메인의 컨텍스트 외부에서는 사용할 수 없기 때문에 컨테이너가 URL을 반환한다는 것은 논리적이라고 생각합니다.

+0

왜 다른 저자가 반성과 특수 코드가 필요한지 잘 모르겠습니다. –