Lottando cercando di ottenere cookie dalla risposta con HttpClient in .net 4.5


107

Ho il seguente codice che funziona correttamente. Non riesco a capire come ottenere il cookie dalla risposta. Il mio obiettivo è quello di poter impostare i cookie nella richiesta e ottenere i cookie dalla risposta. Pensieri?

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();
    }
}

Ecco la risposta completa:

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

Per curiosità posso chiederti perché vuoi leggere i cookie sul client? A quanto mi risulta, i cookie vengono utilizzati per inviare informazioni al server, non per restituire informazioni.
— Darrel Miller

Utilizzo il cookie restituito sulle chiamate che restituiscono JSON in modo da non dover eseguire una chiamata di autorizzazione separata per ogni chiamata JSON. Vale a dire, ho un registro delle chiamate / Home / GetData che restituisce JSON ma solo se autorizzato. Alla richiesta del cliente, aggiungo il cookie in modo che / Home / GetData risponda. Altrimenti dirà "403" non autorizzato.
— Peter Kellner

L'impostazione dell'intestazione di autorizzazione come intestazione predefinita è quasi altrettanto efficace e un po 'più standard. Non esiste alcun modo per il server di impostare automaticamente l'intestazione di autenticazione per conto del client.
— Darrel Miller

1
grazie per la punta Darrel. Hai qualche esempio di come potrebbe apparire in asp.net? Ho lottato con questo per il mio monotouch e ora la mia app di Windows Store. Sarei felice se ci fosse un modo semplice. Questo è un problema, soprattutto con async e attendo ora sulle app di Windows Store.
— Peter Kellner

Risposte:


170

Per aggiungere cookie a una richiesta, popolare il contenitore dei cookie prima della richiesta con CookieContainer.Add(uri, cookie). Dopo la richiesta, il contenitore dei cookie verrà automaticamente popolato con tutti i cookie della risposta. È quindi possibile chiamare GetCookies () per recuperarli.

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
Nota: dopo aver ricevuto i cookie iniziali nella prima chiamata, quando si accede a qualsiasi pagina dello stesso dominio, i cookie verranno inviati automaticamente, non sono necessari passaggi aggiuntivi.
— Jahmic

È necessario aggiungere "using System.linq;"
— Cabuxa.Mapache

^^ System.Linq è richiesto solo se desideri utilizzare il metodo .Cast <>, non è richiesto per il recupero dei cookie, ma dovrebbe essere autoesplicativo :)
— MikeDub

È possibile ottenere i cookie allo stesso modo se httpclientviene creato dalla fabbrica httpclient? ie metodo builder aggiunto a services.AddHttpClient
— user3279954

su get Async abbiamo già fatto riferimento a "google.com", perché dobbiamo dichiarare nuovamente un URI con un riferimento ad esso?
— Malcolm Salvador

7

C'è un'alternativa se non hai accesso a HttpCliente non puoi iniettare il file CookieContainer. Funziona 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
Brillante e crudo ma proprio quello che mi serve ... Bel lavoro, grazie.
— Vedran Mandić

5

Puoi facilmente ottenere un valore di cookie con l'URL fornito.

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;
        }
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.