2013-02-27 16 views
21

私はここで何が間違っているのか把握するのに苦労しています。私はログイン情報を送信している、私は正しい値でヘッダーのセットクッキーを見ることができますが、クッキーコレクションは満たされていません。Set-Cookieヘッダー(no-redirect)にもかかわらず、HttpWebResponse.Cookiesが空です

これはHTTPSです。ログインは自動的にリダイレクトされますが、この問題のトラブルシューティングを試みるにはAllowAutoRedirect = falseで無効にしました。

このスクリーンショットでは、デバッグ情報が簡単に表示され、クッキーが設定されるはずです。 httpWebRequest.Cookieを新しい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(); 

ここ

はのSet-Cookieヘッダーの値がある...なんてこった... http://www.yahoo.comへの接続とまったく同じコードを試してみましたが、クッキーは私のコレクションの中に入れています

s = 541E2101-B768-45C8-B814-34A00525E50F;ドメイン= example.com;パス= /; バージョン= 1

+0

正しいドメイン名がサーバーから設定されていることを確認してください。それはdomain.comか.domain.comか、どちらも異なっています。あなたのコードをASP.NETに投稿できますか? –

答えて

14

C#ASP.NETアプリケーションによって作成されたC#でクッキーを読んだとき、私は...、同様にその問題を発見した;)

ない、それはそれに関係しているかどうかわから、私の場合に設定されている2つのCookieは、Cookieのペイロードをカンマで区切って1つのSet-Cookieヘッダーに書き込まれていることがわかりました。だから私はこの複数のクッキーの問題に対処するAppDeveloperのソリューションを適応させただけでなく、私がコメントで述べた名前/値の問題を修正しました。

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 = sat、monday 2017; domain:asdf.com、coki2 = val2; expires = sat、monday 2017; domain:asdf.com、"期限切れの日付でもコンマが使用されます。それは一時的な修正値= Regex.Replace(value、 "(e | E)xpires =(。+?)(; | $)|(P | p)ath =( 。+?); "、" "); –

+0

@ blackholeearth0_gmailと記載されているように、カンマから分割すると、 'expires'ヘッダ' Wed、04-Apr-18'にコンマがあるので余分な不正なクッキーを生成する – AaA

14

ウェブサイトによって送信さSet-Cookieヘッダは(一般的な形式で、それがされている必要がありません)不正な形式であるように思えます。

この場合、手動でクッキーを解析し、それを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

私はこれをして、私のサンプルコードに含めるのを忘れてしまった。 – Brad

+0

@Brad - plsは適切なサンプルコードを投稿します! –

+0

私のコードはカスタムオブジェクトです。私はここに投稿するためにそれを修正して単純化しなければなりませんでした。行を残して申し訳ありませんが、私は直ちにそれを修正しました。 – Brad

1

私はこの質問が古いであることを知っているが、私はきちんと「のSet-Cookieを」ヘッダを解析し、いくつかのコードに出くわしました。カンマで区切られたクッキーを処理し、各クッキーの名前、有効期限、パス、値、およびドメインを抽出します。

このコードは、Microsoftの独自のCookieパーサーよりも優れています。これは、公式のCookieパーサーが行うべきことです。私はそれが非常に一般的な問題であるため、Microsoftがこれをまだ修正していない理由を知りません。 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; 
} 
3

this answerのようにCookieContainerを使用

はここで、元のコードです。 私はこれらの正規表現のアプローチを引き上げたものは、expires=Tue, ...のコンマでした。

5

他の回答を見る私は誤ったクッキー処理を改善しました。これらの回答とは異なり、これはすべてのクッキーのプロパティ(期限切れ、安全なものなど)を自動的に処理します。)、すべてのCookie範囲で動作します(誤ったCookieが1つ以上ある場合でも)。

これは、拡張メソッドとして実装されますと、以下のように使用することができます。

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

FixCookies()拡張メソッド:

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

'='にクッキー値を分割しています - これは潜在的な落とし穴です値がbase64でエンコードされた文字列の場合 –

2

少し遅れかもしれないが、あなたは、関数SetCookiesを使用することができます

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

'set-cookie'に' path =/'が含まれていると、これは失敗します。 – Salar

関連する問題