Probleme beim Versuch, Cookies mit HttpClient in .net 4.5 außer Antwort zu bringen


107

Ich habe den folgenden Code, der erfolgreich funktioniert. Ich kann nicht herausfinden, wie ich den Cookie aus der Antwort herausholen kann. Mein Ziel ist es, dass ich in der Lage sein möchte, Cookies in der Anfrage zu setzen und Cookies aus der Antwort zu erhalten. Gedanken?

private async Task<string> Login(string username, string password)
{
    try
    {
        string url = "http://app.agelessemail.com/account/login/";
        Uri address = new Uri(url);
        var postData = new List<KeyValuePair<string, string>>
        {
            new KeyValuePair<string, string>("username", username),
            new KeyValuePair<string, string>("password ", password)
        };

        HttpContent content = new FormUrlEncodedContent(postData);
        var cookieJar = new CookieContainer();
        var handler = new HttpClientHandler
        {
            CookieContainer = cookieJar,
            UseCookies = true,
            UseDefaultCredentials = false
        };

        var client = new HttpClient(handler)
        {
            BaseAddress = address
        };


        HttpResponseMessage response = await client.PostAsync(url,content);
        response.EnsureSuccessStatusCode();
        string body = await response.Content.ReadAsStringAsync();
        return body;
    }
    catch (Exception e)
    {
        return e.ToString();
    }
}

Hier ist die vollständige Antwort:

HttpResponseMessage response = await client.PostAsync(url,content);
response.EnsureSuccessStatusCode();

Uri uri = new Uri(UrlBase);
var responseCookies = cookieJar.GetCookies(uri);
foreach (Cookie cookie in responseCookies)
{
    string cookieName = cookie.Name;
    string cookieValue = cookie.Value;
}

Kann ich aus Neugier fragen, warum Sie Cookies auf dem Client lesen möchten? Nach meinem Verständnis werden Cookies zum Senden von Informationen an den Server und nicht zum Zurückgeben von Informationen verwendet.
Darrel Miller

Ich verwende das zurückgegebene Cookie bei Aufrufen, die JSON zurückgeben, damit ich nicht für jeden JSON-Aufruf einen separaten Autorisierungsaufruf ausführen muss. Das heißt, ich habe ein Anrufprotokoll / Home / GetData, das JSON zurückgibt, aber nur, wenn es autorisiert ist. Auf Client-Anfrage füge ich das Cookie hinzu, damit / Home / GetData antwortet. Andernfalls wird "403" nicht autorisiert angezeigt.
Peter Kellner

Das Festlegen des Autorisierungsheaders als Standardheader ist fast genauso effektiv und etwas standardmäßiger. Es gibt einfach keine Möglichkeit für den Server, den Auth-Header automatisch im Namen des Clients festzulegen.
Darrel Miller

1
Danke für den Tipp Darrel. Haben Sie Beispiele dafür, wie das in asp.net aussehen könnte? Ich kämpfte damit um mein Monotouch und jetzt um meine Windows Store App. Ich würde mich freuen, wenn es einen einfachen Weg gäbe. Dies ist besonders bei Async ein Problem und wartet jetzt auf Windows Store-Apps.
Peter Kellner

Antworten:


170

Um einer Anfrage Cookies hinzuzufügen, füllen Sie den Cookie-Container vor der Anfrage mit CookieContainer.Add(uri, cookie). Nachdem die Anfrage gestellt wurde, wird der Cookie-Container automatisch mit allen Cookies aus der Antwort gefüllt. Sie können dann GetCookies () aufrufen, um sie abzurufen.

CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;

HttpClient client = new HttpClient(handler);
HttpResponseMessage response = client.GetAsync("http://google.com").Result;

Uri uri = new Uri("http://google.com");
IEnumerable<Cookie> responseCookies = cookies.GetCookies(uri).Cast<Cookie>();
foreach (Cookie cookie in responseCookies)
    Console.WriteLine(cookie.Name + ": " + cookie.Value);

Console.ReadLine();

8
Hinweis: Nach dem Empfang der ersten Cookies beim ersten Aufruf werden beim Zugriff auf Seiten derselben Domain die Cookies automatisch gesendet, ohne dass zusätzliche Schritte erforderlich sind.
Jahmic

Sie müssen "using System.linq;" hinzufügen.
Cabuxa.Mapache

^^ System.Linq ist nur erforderlich, wenn Sie die .Cast <> -Methode verwenden möchten. Es ist nicht für das Abrufen von Cookies erforderlich, dies sollte jedoch selbsterklärend sein :)
MikeDub

Ist es möglich, Cookies auf die gleiche Weise zu erhalten, wenn httpclientsie aus der httpclient-Factory erstellt wurden? dh Builder-Methode zu services.AddHttpClient hinzugefügt
user3279954

Bei get Async haben wir bereits auf "google.com" verwiesen. Warum müssen wir einen URI mit einem Verweis darauf erneut deklarieren?
Malcolm Salvador

7

Es gibt eine Alternative, wenn Sie keinen Zugriff auf die haben HttpClientund die nicht injizieren können CookieContainer. Dies funktioniert in .NET Core 2.2:

private string GetCookie(HttpResponseMessage message)
{
    message.Headers.TryGetValues("Set-Cookie", out var setCookie);
    var setCookieString = setCookie.Single();
    var cookieTokens = setCookieString.Split(';');
    var firstCookie = cookieTokens.FirstOrDefault();
    var keyValueTokens = firstCookie.Split('=');
    var valueString = keyValueTokens[1];
    var cookieValue = HttpUtility.UrlDecode(valueString);
    return cookieValue;
}

1
Genial und roh, aber genau das, was ich brauche ... Gute Arbeit, danke.
Vedran Mandić

5

Mit der angegebenen URL können Sie problemlos einen Cookie-Wert abrufen.

private async Task<string> GetCookieValue(string url, string cookieName)
{
    var cookieContainer = new CookieContainer();
    var uri = new Uri(url);
    using (var httpClientHandler = new HttpClientHandler
    {
        CookieContainer = cookieContainer
    })
    {
        using (var httpClient = new HttpClient(httpClientHandler))
        {
            await httpClient.GetAsync(uri);
            var cookie = cookieContainer.GetCookies(uri).Cast<Cookie>().FirstOrDefault(x => x.Name == cookieName);
            return cookie?.Value;
        }
    }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.