Намагаються вийти з файлу cookie у відповідь з HttpClient в .net 4.5


107

У мене є такий код, який успішно працює. Я не можу зрозуміти, як отримати печиво з відповіді. Моя мета полягає в тому, щоб я хотів мати можливість встановити файли 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 використовуються для надсилання інформації на сервер, а не для повернення інформації.
Даррел Міллер

Я використовую повернене cookie для дзвінків, які повертають JSON, так що мені не потрібно робити окремий виклик авторизації для кожного дзвінка JSON. Тобто, у мене є журнал викликів / Головна / GetData, який повертає JSON, але лише за умови дозволу. На запит клієнта я додаю файл cookie, щоб / Home / GetData відповів. Інакше воно скаже "403" несанкціоновано.
Пітер Кельнер

Встановлення заголовка авторизації як заголовка за замовчуванням майже настільки ж ефективно та трохи стандартніше. Просто сервер не може автоматично встановити заголовок auth від імені клієнта.
Даррел Міллер

1
дякую за пораду Даррел. Чи є у вас приклади того, як це може виглядати на asp.net? Я боровся з цим за свій монотух і тепер додаток для магазину Windows. Я був би радий, якби був простий спосіб. Це біль, особливо з асинхронізацією та очікуванням зараз на додатках Windows Store.
Пітер Келнер

Відповіді:


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

8
Примітка. Після отримання початкових файлів cookie під час першого дзвінка, під час доступу до будь-яких сторінок з одного домену, файли cookie надсилаються автоматично, без додаткових кроків не потрібно.
Яхміч

Ви повинні додати "за допомогою System.linq;"
Cabuxa.Mapache

^^ System.Linq потрібен лише в тому випадку, якщо ви хочете використовувати метод .Cast <>, для пошуку файлів cookie він не потрібен, але це повинно бути роз'яснювальним :)
MikeDub

Чи можливо отримати файли cookie однаковим чином, якщо httpclientвін створений на заводі httpclient? тобто доданий до сервісів метод
builder.AddHttpClient

ми отримали посилання на "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;
}

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;
        }
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.