Как мне установить cookie в HttpClient's HttpRequestMessage

Я пытаюсь использовать веб-API HttpClient сделать сообщение для конечной точки, которая требует входа в систему в виде HTTP-cookie, который идентифицирует учетную запись (это только то, что #ifdefвышли из релизной версии).

Как мне добавить куки в HttpRequestMessage?

7 ответов

Решение

Вот как вы можете установить пользовательское значение cookie для запроса:

var baseAddress = new Uri("http://example.com");
var cookieContainer = new CookieContainer();
using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
    var content = new FormUrlEncodedContent(new[]
    {
        new KeyValuePair<string, string>("foo", "bar"),
        new KeyValuePair<string, string>("baz", "bazinga"),
    });
    cookieContainer.Add(baseAddress, new Cookie("CookieName", "cookie_value"));
    var result = client.PostAsync("/test", content).Result;
    result.EnsureSuccessStatusCode();
}

Принятый ответ является правильным способом сделать это в большинстве случаев. Однако в некоторых ситуациях вы хотите установить заголовок cookie вручную. Обычно, если вы устанавливаете заголовок "Cookie", он игнорируется, но это потому, что HttpClientHandler по умолчанию использует его CookieContainer свойство для печенья. Если вы отключите это, установив UseCookies в false Вы можете установить заголовки cookie вручную, и они появятся в запросе, например

var baseAddress = new Uri("http://example.com");
using (var handler = new HttpClientHandler { UseCookies = false })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
    var message = new HttpRequestMessage(HttpMethod.Get, "/test");
    message.Headers.Add("Cookie", "cookie1=value1; cookie2=value2");
    var result = await client.SendAsync(message);
    result.EnsureSuccessStatusCode();
}

Для меня простое решение работает для установки файлов cookie в объекте HttpRequestMessage.

protected async Task<HttpResponseMessage> SendRequest(HttpRequestMessage requestMessage, CancellationToken cancellationToken = default(CancellationToken))
{
    requestMessage.Headers.Add("Cookie", $"<Cookie Name 1>=<Cookie Value 1>;<Cookie Name 2>=<Cookie Value 2>");

    return await _httpClient.SendAsync(requestMessage, cancellationToken).ConfigureAwait(false);
}

У меня была аналогичная проблема, и для моего приложения AspNetCore 3.1 другие ответы на этот вопрос не работали. Я обнаружил, что настройка именованного HttpClient в моем Startup.csи использование распространения заголовка заголовка Cookie работало отлично. Это также позволяет избежать беспокойства о правильном размещении вашего обработчика и клиента. Обратите внимание: если распространение файлов cookie запроса - это не то, что вам нужно (извините, Op), вы можете установить свои собственные файлы cookie при настройке фабрики клиента.

Настроить службы с IServiceCollection

services.AddHttpClient("MyNamedClient").AddHeaderPropagation();
services.AddHeaderPropagation(options =>
{
    options.Headers.Add("Cookie");
});

Настроить с помощью IApplicationBuilder

builder.UseHeaderPropagation();
  • Ввести IHttpClientFactory в ваш контроллер или промежуточное ПО.
  • Создайте своего клиента using var client = clientFactory.CreateClient("MyNamedClient");

Потратив несколько часов на эту проблему, ни один из ответов выше не помог мне, поэтому я нашел действительно полезный инструмент.

Во-первых, я использовал Fiddler 4 от Telerik для подробного изучения своих веб-запросов.

Во-вторых, я наткнулся на этот полезный плагин для Fiddler:

https://github.com/sunilpottumuttu/FiddlerGenerateHttpClientCode

Он просто сгенерирует код C# для вас. Пример был:

        var uriBuilder = new UriBuilder("test.php", "test");
        var httpClient = new HttpClient();


        var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, uriBuilder.ToString());



        httpRequestMessage.Headers.Add("Host", "test.com");
        httpRequestMessage.Headers.Add("Connection", "keep-alive");
     //   httpRequestMessage.Headers.Add("Content-Length", "138");
        httpRequestMessage.Headers.Add("Pragma", "no-cache");
        httpRequestMessage.Headers.Add("Cache-Control", "no-cache");
        httpRequestMessage.Headers.Add("Origin", "test.com");
        httpRequestMessage.Headers.Add("Upgrade-Insecure-Requests", "1");
    //    httpRequestMessage.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
        httpRequestMessage.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36");
        httpRequestMessage.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
        httpRequestMessage.Headers.Add("Referer", "http://www.translationdirectory.com/");
        httpRequestMessage.Headers.Add("Accept-Encoding", "gzip, deflate");
        httpRequestMessage.Headers.Add("Accept-Language", "en-GB,en-US;q=0.9,en;q=0.8");
        httpRequestMessage.Headers.Add("Cookie", "__utmc=266643403; __utmz=266643403.1537352460.3.3.utmccn=(referral)|utmcsr=google.co.uk|utmcct=/|utmcmd=referral; __utma=266643403.817561753.1532012719.1537357162.1537361568.5; __utmb=266643403; __atuvc=0%7C34%2C0%7C35%2C0%7C36%2C0%7C37%2C48%7C38; __atuvs=5ba2469fbb02458f002");


        var httpResponseMessage = httpClient.SendAsync(httpRequestMessage).Result;

        var httpContent = httpResponseMessage.Content;
        string result = httpResponseMessage.Content.ReadAsStringAsync().Result;

Обратите внимание, что мне пришлось закомментировать две строки, так как этот плагин еще не совсем совершенен, но, тем не менее, он выполнил свою работу.

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Я не связан и не одобрен ни Telerik, ни автором плагина в любом случае.

Если вы хотите использовать HttpClientдля отправки запроса, требующего входа пользователя в систему, это означает, что вам необходимо выполнить процесс входа в систему, затем получить файлы cookie и отправить эти файлы cookie на запрос, требующий входа в систему.

Я сделал это при тестировании действия под названием IsLoggedIn. Это действие проверяет, зарегистрирован ли пользователь с помощью файлов cookie в HttpRequest.

Что я сделал при тестировании этого действия:

                      string Login = JsonConvert.SerializeObject(new LoginViewModel()
                {
                    Email = userFromDb.Email,
                    Password = "fdfdf@2239",
                    RememberMe = false
                }); ;
                StringContent LoginhttpContent = new(Login, Encoding.UTF8, "application/json");
                var Login_response = await _httpClient.PostAsync(HelperFunctions.getUrl(HelperFunctions.AcctounController.name, HelperFunctions.AcctounController.Login), LoginhttpContent);
                Assert.Equal(HttpStatusCode.OK, Login_response.StatusCode);
    
                //receive cookies from the login response
                var cookies = Login_response.Headers.GetValues(HeaderNames.SetCookie);
                 //Add the cookies to the DefaultRequestHeaders of the _httpClient
                _httpClient.DefaultRequestHeaders.Add("Cookie",cookies);
                var IsLoggedIn_response = await _httpClient.GetAsync(HelperFunctions.getUrl(HelperFunctions.AcctounController.name, HelperFunctions.AcctounController.IsLoggedIn));
                Assert.Equal("true",IsLoggedIn_response.Content.ReadAsStringAsync().Result);
      var cookies = new CookieContainer();
var clientHandler = new HttpClientHandler();
clientHandler.CookieContainer = cookies;
var client = new HttpClient(clientHandler, true);
Другие вопросы по тегам