2013-02-27 7 views
21

Sto lottando per capire cosa c'è che non va. Sto inviando informazioni di accesso, posso vedere il Set-Cookie nell'intestazione con il valore corretto, ma la raccolta dei cookie non viene riempita.HttpWebResponse.Cookies vuoti nonostante Set-Cookie Header (senza reindirizzamento)

Questo è HTTPS, il reindirizzamento automatico di accesso, ma l'ho disabilitato con AllowAutoRedirect = false per provare a risolvere questo problema.

In questa schermata è possibile visualizzare facilmente le informazioni di debug e impostare il cookie. Sto impostando il mio httpWebRequest.Cookie su un nuovo CookieCollection.

Right click and select view image to see full-size.

HttpWebRequest httpRequest; 
CookieContainer reqCookies = new CookieContainer(); 
string url = "https://example.com"; 
string[] email = user.Split('@'); 
email[0] = System.Web.HttpUtility.UrlEncode(email[0]); 
user = email[0] + "@" + email[1]; 
pass = System.Web.HttpUtility.UrlEncode(pass); 

string postData = "email=" + user + "&password=" + pass; 
byte[] byteData = Encoding.UTF8.GetBytes(postData); 

httpRequest = (HttpWebRequest)WebRequest.Create(url); 
httpRequest.Method = "POST"; 
httpRequest.Referer = url; 
httpRequest.CookieContainer = reqCookies; 
httpRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1003.1 Safari/535.19"; 
httpRequest.Accept = "text/html, application/xhtml+xml, */*"; 
httpRequest.ContentType = "application/x-www-form-urlencoded"; 
httpRequest.ContentLength = byteData.Length; 
using (Stream postStream = httpRequest.GetRequestStream()) 
{ 
    postStream.Write(byteData, 0, byteData.Length); 
    postStream.Close(); 
} 

httpRequest.AllowAutoRedirect = false; 
HttpWebResponse b = (HttpWebResponse)httpRequest.GetResponse(); 

provato il codice esattamente lo stesso collegamento a http://www.yahoo.com ei biscotti sono messi nella mia collezione ... Argh ...

Ecco il valore di Set-Cookie Header:

s = 541E2101-B768-45C8-B814-34A00525E50F; Dominio = example.com; Path = /; versione = 1

+0

Sei sicuro di avere impostato il nome di dominio corretto dal server? è domain.com o .domain.com, entrambi sono diversi. Puoi pubblicare il tuo codice ASP.NET? –

risposta

14

ho trovato pure tale questione, quando la lettura di cookie in C# che sono stati creati da un C# ASP.NET app ...;)

Non sono sicuro se si ha a che fare con esso, ma ho scoperto che i due cookie impostati nel mio caso sono scritti in una singola intestazione Set-Cookie, con il payload del cookie separato da virgole. Quindi ho adattato la soluzione di AppDeveloper per gestire questo problema con più cookie, oltre a correggere la cosa nome/valore che ho menzionato nei commenti.

private static void fixCookies(HttpWebRequest request, HttpWebResponse response) 
{ 
    for (int i = 0; i < response.Headers.Count; i++) 
    { 
     string name = response.Headers.GetKey(i); 
     if (name != "Set-Cookie") 
      continue; 
     string value = response.Headers.Get(i); 
     foreach (var singleCookie in value.Split(',')) 
     { 
      Match match = Regex.Match(singleCookie, "(.+?)=(.+?);"); 
      if (match.Captures.Count == 0) 
       continue; 
      response.Cookies.Add(
       new Cookie(
        match.Groups[1].ToString(), 
        match.Groups[2].ToString(), 
        "/", 
        request.Host.Split(':')[0])); 
     } 
    } 
} 
+2

"coki1 = val1; expires = sab, lunedi 2017; dominio: asdf.com, coki2 = val2; expires = sat, monday 2017; dominio: asdf.com,". la virgola è usata anche nella data di scadenza. su it incasina split (",") aggiungi questo valore per fix temporanea = Regex.Replace (valore, "(e | E) xpires = (. +?) (; | $) | (P | p) ath = (. +?); "," "); –

+0

come menzionato @ blackholeearth0_gmail, la divisione dalla virgola produrrà dei cookie aggiuntivi errati in quanto vi è una virgola nell'intestazione 'expires'' Wed, 04-Apr-18' – AaA

14

Sembra Set-Cookie intestazione inviato dal sito web non è valido (non nel formato tipico avrebbe dovuto essere).

In tal caso, è necessario analizzare manualmente il cookie e inserirlo nel numero CookieContainer.

for (int i = 0; i < b.Headers.Count; i++) 
{ 
    string name = b.Headers.GetKey(i); 
    string value = b.Headers.Get(i); 
    if (name == "Set-Cookie") 
    { 
     Match match = Regex.Match(value, "(.+?)=(.+?);"); 
     if (match.Captures.Count > 0) 
     { 
      reqCookies.Add(new Cookie(match.Groups[1].Value, match.Groups[2].Value, "/", "example.com")); 
     } 
    } 
} 
+0

Ho fatto questo, ho dimenticato di includere nel mio codice di esempio. – Brad

+0

@Brad - pls inserisci il codice di esempio corretto! –

+0

Il mio codice è un oggetto personalizzato e ho dovuto modificarlo e semplificarlo per postare qui. Scusa per aver lasciato fuori una linea, l'ho risolto immediatamente. – Brad

1

so che questa domanda è vecchio, ma mi sono imbattuto in un codice che analizza correttamente un header "Set-Cookie". Gestisce i cookie separati da virgole e ne estrae il nome, la scadenza, il percorso, il valore e il dominio di ciascun cookie.

Questo codice funziona meglio del parser cookie di Microsoft e questo è ciò che dovrebbe fare il parser ufficiale dei cookie. Non ho idea del perché Microsoft non abbia ancora risolto questo problema poiché si tratta di un problema molto comune.

Ecco il codice originale: http://snipplr.com/view/4427/

sto postando qui nel caso in cui il collegamento va giù ad un certo punto:

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; 
} 
3

Utilizzare un CookieContainer come in this answer. Quello che ha fatto scattare questa regex per me era una virgola in expires=Tue, ....

5

Considerando altre risposte, ho migliorato la gestione errata dei cookie. A differenza di queste risposte, questo gestisce automaticamente tutte le proprietà dei cookie (come scaduti, sicuri, ecc.) e funziona con tutti i tipi di cookie (anche quando ci sono più di 1 cookie errato).

E 'implementato come metodo di estensione e può essere utilizzato nel modo seguente:

//... 
      using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 
      { 
       request.FixCookies(response); 
//... 

FixCookies() metodo di estensione:

using System; 
using System.Collections.Generic; 
using System.Net; 

namespace AG.WebHelpers 
{ 
    static public class ExtensionMethods 
    { 
     static public void FixCookies(this HttpWebRequest request, HttpWebResponse response) 
     { 
      for (int i = 0; i < response.Headers.Count; i++) 
      { 
       string name = response.Headers.GetKey(i); 
       if (name != "Set-Cookie") 
        continue; 
       string value = response.Headers.Get(i); 
       var cookieCollection = ParseCookieString(value,() => request.Host.Split(':')[0]); 
       response.Cookies.Add(cookieCollection); 
      } 
     } 

     static private CookieCollection ParseCookieString(string cookieString, Func<string> getCookieDomainIfItIsMissingInCookie) 
     { 
      bool secure = false; 
      bool httpOnly = false; 

      string domainFromCookie = null; 
      string path = null; 
      string expiresString = null; 

      Dictionary<string, string> cookiesValues = new Dictionary<string, string>(); 

      var cookieValuePairsStrings = cookieString.Split(';'); 
      foreach(string cookieValuePairString in cookieValuePairsStrings) 
      { 
       var pairArr = cookieValuePairString.Split('='); 
       int pairArrLength = pairArr.Length; 
       for (int i = 0; i < pairArrLength; i++) 
       { 
        pairArr[i] = pairArr[i].Trim(); 
       } 
       string propertyName = pairArr[0]; 
       if (pairArrLength == 1) 
       { 
        if (propertyName.Equals("httponly", StringComparison.OrdinalIgnoreCase)) 
         httpOnly = true; 
        else if (propertyName.Equals("secure", StringComparison.OrdinalIgnoreCase)) 
         secure = true; 
        else 
         throw new InvalidOperationException(string.Format("Unknown cookie property \"{0}\". All cookie is \"{1}\"", propertyName, cookieString)); 
        continue; 
       } 

       string propertyValue = pairArr[1]; 
       if (propertyName.Equals("expires", StringComparison.OrdinalIgnoreCase)) 
        expiresString = propertyValue; 
       else if (propertyName.Equals("domain", StringComparison.OrdinalIgnoreCase)) 
        domainFromCookie = propertyValue; 
       else if (propertyName.Equals("path", StringComparison.OrdinalIgnoreCase)) 
        path = propertyValue; 
       else 
        cookiesValues.Add(propertyName, propertyValue); 
      } 

      DateTime expiresDateTime; 
      if (expiresString != null) 
      { 
       expiresDateTime = DateTime.Parse(expiresString); 
      } 
      else 
      { 
       expiresDateTime = DateTime.MinValue; 
      } 
      if (string.IsNullOrEmpty(domainFromCookie)) 
      { 
       domainFromCookie = getCookieDomainIfItIsMissingInCookie(); 
      } 

      CookieCollection cookieCollection = new CookieCollection(); 
      foreach (var pair in cookiesValues) 
      { 
       Cookie cookie = new Cookie(pair.Key, pair.Value, path, domainFromCookie); 
       cookie.Secure = secure; 
       cookie.HttpOnly = httpOnly; 
       cookie.Expires = expiresDateTime; 

       cookieCollection.Add(cookie); 
      } 
      return cookieCollection; 
     } 
    } 
} 
+0

Stai dividendo il valore del cookie su '=' - questa è una potenziale trappola se il valore è una stringa codificata in base64 –

2

che potrebbe essere un po' in ritardo, ma è possibile utilizzare SetCookies funzione

var cHeader = responce.Headers.Get("Set-Cookie"); 
var cookie = new CookieContainer(); 
cookie.SetCookies(new Uri("[...]"), cHeader); 
+0

Questo fallirà se 'set-cookie' contiene' percorso =/' – Salar

Problemi correlati