Esforço ao tentar obter o cookie da resposta com HttpClient em .net 4.5


107

Eu tenho o seguinte código que funciona com sucesso. Não consigo descobrir como tirar o cookie da resposta. Meu objetivo é poder definir cookies na solicitação e obter cookies da resposta. Pensamentos?

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

Aqui está a resposta 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;
}

Por curiosidade, posso perguntar por que você deseja ler cookies no cliente? Meu entendimento é que os cookies são usados ​​para enviar informações ao servidor, não para retornar informações.
— Darrel Miller

Eu uso o cookie retornado em chamadas que retornam JSON para que não precise fazer uma chamada de autorização separada para cada chamada JSON. Ou seja, tenho um registro de chamadas / Home / GetData que retorna JSON, mas somente se autorizado. Na solicitação do cliente, adiciono o cookie para que / Home / GetData responda. Caso contrário, dirá "403" não autorizado.
— Peter Kellner

Definir o cabeçalho de autorização como um cabeçalho padrão é quase tão eficaz e um pouco mais padrão. Simplesmente não há como o servidor definir o cabeçalho de autenticação automaticamente em nome do cliente.
— Darrel Miller

1
obrigado pela dica Darrel. Você tem algum exemplo de como isso pode ser no asp.net? Lutei com isso para o meu monotouch e agora meu aplicativo da Windows Store. Eu ficaria feliz se houvesse uma maneira simples. Isso é uma dor, especialmente com async e await now nos aplicativos da Windows Store.
— Peter Kellner

Respostas:


170

Para adicionar cookies a uma solicitação, preencha o contêiner de cookies antes da solicitação com CookieContainer.Add(uri, cookie). Depois que a solicitação for feita, o contêiner de cookies será preenchido automaticamente com todos os cookies da resposta. Você pode então chamar GetCookies () para recuperá-los.

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: Após receber os cookies iniciais na primeira chamada, ao acessar quaisquer páginas do mesmo domínio, os cookies serão enviados automaticamente, sem necessidade de etapas adicionais.
— Jahmic de

Você deve adicionar "using System.linq;"
— Cabuxa.Mapache

^^ System.Linq só é necessário se você deseja utilizar o método .Cast <>, não é necessário para a recuperação de cookies, mas deve ser autoexplicativo :)
— MikeDub

É possível obter cookies da mesma forma se httpclientfor compilado na fábrica httpclient? isto é, método do construtor adicionado a services.AddHttpClient
— user3279954

no get Async, já fizemos uma referência a "google.com", por que precisamos declarar um URI com uma referência a ele novamente?
— Malcolm Salvador

7

Há alternativa se você não tiver acesso HttpCliente não puder injetar o CookieContainer. Isso funciona no .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
Brilhante e cru, mas exatamente o que eu preciso ... Bom trabalho, obrigado.
— Vedran Mandić

5

Você pode obter facilmente um valor de cookie com o URL fornecido.

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;
        }
    }
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.