Борьба с попыткой получить cookie из ответа с помощью HttpClient в .net 4.5

107

У меня есть следующий код, который успешно работает. Я не могу понять, как вытащить cookie из ответа. Моя цель состоит в том, чтобы иметь возможность устанавливать файлы cookie в запросе и получать файлы cookie из ответа. Мысли?

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

Вот полный ответ:

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;
}
Питер Келлнер
источник
Могу я из любопытства спросить, почему вы хотите читать файлы cookie на клиенте? Насколько я понимаю, файлы cookie используются для отправки информации на сервер, а не для возврата информации.
Darrel Miller
Я использую возвращенный файл cookie для вызовов, которые возвращают JSON, поэтому мне не нужно выполнять отдельный вызов авторизации для каждого вызова JSON. То есть у меня есть журнал вызовов / Home / GetData, который возвращает JSON, но только в случае авторизации. По запросу клиента я добавляю cookie, чтобы / Home / GetData ответил. В противном случае будет указано «403 неавторизовано».
Питер Келлнер
Установка заголовка авторизации в качестве заголовка по умолчанию почти так же эффективна и немного более стандартна. У сервера просто нет возможности автоматически установить заголовок auth от имени клиента.
Даррел Миллер,
1
спасибо за подсказку Даррел. У вас есть примеры того, как это может выглядеть в asp.net? Я боролся с этим для моего монотач, а теперь и для моего приложения для магазина Windows. Я был бы счастлив, если бы был простой способ. Это неприятно, особенно с async и await now в приложениях магазина Windows.
Питер Келлнер

Ответы:

170

Чтобы добавить файлы cookie в запрос, заполните контейнер файлов cookie перед запросом с помощью CookieContainer.Add(uri, cookie). После того, как запрос сделан, контейнер cookie будет автоматически заполнен всеми файлами cookie из ответа. Затем вы можете вызвать GetCookies (), чтобы получить их.

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();
Despertar
источник
8
Примечание. После получения начальных файлов cookie при первом вызове при доступе к любым страницам из того же домена файлы cookie будут отправлены автоматически, никаких дополнительных действий не требуется.
Jahmic
Вы должны добавить "using System.linq;"
Cabuxa.Mapache
^^ System.Linq требуется только в том случае, если вы хотите использовать метод .Cast <>, он не требуется для получения
файлов
Можно ли получить файлы cookie таким же образом, если они httpclientсобраны из фабрики httpclient? ie builder метод добавлен в services.AddHttpClient
user3279954 05
при получении Async мы уже сделали ссылку на "google.com", зачем нам снова объявлять URI со ссылкой на него?
Малькольм Сальвадор
7

Есть альтернатива, если у вас нет доступа к HttpClientфайлу CookieContainer. Это работает в .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;
}
Ритис I
источник
1
Великолепно и сыро, но именно то, что мне нужно ... Хорошая работа, спасибо.
Ведран Мандич,
5

Вы можете легко получить значение cookie с заданным URL.

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;
        }
    }
}
Альпер Эбикоглу
источник