如何在HttpClient的HttpRequestMessage上设置Cookie


246

我正在尝试使用Web api HttpClient向需要登录的终结点发布帖子,该终结点需要以标识帐户的HTTP cookie的形式登录(这只是#ifdef发行版本中不存在的内容)。

如何向其中添加Cookie HttpRequestMessage

Answers:


373

您可以按照以下方法为请求设置自定义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 = await client.PostAsync("/test", content);
    result.EnsureSuccessStatusCode();
}

2
处理程序可能会从using语句中删除,它将在处理http客户端时被处理。
基米

17
Kimi是正确的,但您也不应在使用中包装HttpClient。aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
Robert McLaws

9
注意:如果仅使用HttpClient的1个实例来执行多个请求,则将使用CookieContainer缓存cookie。对一个用户来说危险的是从另一个用户那里获取cookie。
Acaz Souza

31
“ HttpClient旨在实例化一次,并在应用程序的整个生命周期内重复使用。尤其是在服务器应用程序中,为每个请求创建一个新的HttpClient实例将耗尽在繁重的负载下可用的套接字数量……”从这里开始:asp .net / web-api / overview / advanced /…
SergeyT

4
@SergeyT,当他需要对同一资源进行单独的会话调用时,该怎么办?:)
AgentFire '18年

336

在大多数情况下,可接受的答案是正确的方法。但是,在某些情况下,您想手动设置cookie标头。通常,如果您设置“ Cookie”标头,则将其忽略,但这是因为HttpClientHandler默认情况下将其CookieContainer属性用于Cookie。如果您禁用它,则可以通过设置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();
}

44
我一直在追寻一个错误,其中一个错误是使用SendAsync发送的请求未发送Cookie标头。这使我意识到,除非您在Handler中设置UseCookies = false,否则它不仅会使用CookieContainer,而且还会无提示地忽略存储在请求标头中的任何Cookie!非常感谢!
Fernando Neira

14
对于任何试图将HttpClient用作代理的人,此答案都非常有用!
cchamberlain 2015年

3
现在尝试一下...如果可行...您应该得到加拿大的良好拥抱。
Maxime Rouiller

11
注意:如果仅使用HttpClient的1个实例来执行多个请求,则将使用CookieContainer缓存cookie。对一个用户来说危险的是从另一个用户那里获取cookie。
Acaz Souza

9
当某人尝试添加“ Cookie”标头而不是悄悄地松开它时,该愚蠢的事情应该引发异常。花了我一个小时的时间。感谢您的解决方案。
stmax

5

在这个问题上花费了几个小时之后,以上答案都没有帮助我,所以我找到了一个非常有用的工具。

首先,我使用Telerik的Fiddler 4来详细研究我的Web请求

其次,我遇到了一个对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或插件的作者均未与我联系或认可。


2
这基本上是与这个答案相同的答案,它与Cookie唯一相关的部分是最后添加了标头。请注意该答案中的所有注意事项
George Mauer

3

对我来说,简单的解决方案是在HttpRequestMessage对象中设置cookie 。

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

需要注意的是接受的答案做了以上,并处理比这多很多边界条件。它可以用于仅使用http或作用域cookie,多值cookie等之类的东西。评分第二高的答案提出了与之相同的方法,但是具有更多的上下文和解释
George Mauer

@GeorgeMauer可能是您正确的。他们两个都从“ HttpClient(handler)”创建httpClient。以我为例,我要从httpClientPool.GetOrCreateHttpClient()创建_httpClient
Waqar UlHaq,

1
但是您实际上并没有在答案中表明这一点,也没有解释其区别或好处(这实际上也不是问题,但我对此并不担心)。我并不是在试图粗鲁,重要的是要弄清楚这个答案对谁有帮助,而其他答案则不会更好。
乔治·莫尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.