HttpClientのHttpRequestMessageにCookieを設定する方法


246

HttpClientアカウントを識別するHTTP Cookieの形式でログインする必要があるエンドポイントに投稿するためにWeb APIを使用しようとしています(これは#ifdefリリースバージョンから削除されたものにすぎません)。

にCookieを追加するにはどうすればよいHttpRequestMessageですか。

回答:


374

リクエストにカスタム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クライアントが破棄されるときに破棄されます。
Kimi

17
Kimiは正しいですが、HttpClientをusingにラップしないでください。aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
Robert McLaws

9
注意:HttpClientの1つのインスタンスのみを使用して複数のリクエストを実行すると、CookieContainerを使用するCookieがキャッシュされます。ユーザーが別のユーザーからCookieを取得するのは危険です。
Acaz Souza、2016

31
「HttpClientは一度インスタンス化され、アプリケーションの存続期間を通じて再利用されることを目的としています。特にサーバーアプリケーションでは、リクエストごとに新しいHttpClientインスタンスを作成すると、高負荷時に利用可能なソケットの数が使い果たされます...」ここから:asp .net / web-api / overview / advanced /…
SergeyT 2017年

4
@SergeyTでは、同じリソースに対して個別のセッション呼び出しを行う必要がある場合はどうすればよいでしょうか。:)
AgentFire 2018

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ヘッダーを送信しなかったというエラーを数日間追跡してきました。これは、ハンドラーでUseCookies = falseを設定しない限り、CookieContainerを使用するだけでなく、要求ヘッダーに格納されているCookieを暗黙的に無視することを理解するのに役立ちました。どうもありがとうございます!
Fernando Neira 2013

14
この回答は、HttpClientをプロキシとして使用しようとする場合に非常に役立ちます。
チェンバレン

3
これを試してみてください...それがうまくいくなら...カナダのハグに値するでしょう。
Maxime Rouiller、2015

11
注意:HttpClientの1つのインスタンスのみを使用して複数のリクエストを実行すると、CookieContainerを使用するCookieがキャッシュされます。ユーザーが別のユーザーからCookieを取得するのは危険です。
Acaz Souza、2016

9
その愚かなことは、誰かが「Cookie」ヘッダーを静かに失うのではなく追加しようとすると、例外をスローするはずです。私の人生の1時間を要しました。解決策をありがとう。
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;

このプラグインはまだ完全ではないため、2行コメントアウトする必要がありましたが、それでもうまくいきました。

免責事項:私はいずれにしても、Telerikまたはプラグインの作成者のいずれにも関連付けられておらず、承認されていません。


2
これは本質的に同じ答えであるこの一つとして、クッキーに関係していることの一部だけは、ヘッダーの最後の追加です。その回答のすべての警告に注意してください
George Mauer

4

私にとって、簡単な解決策は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などのようなことを行うために使用できます。2番目に高い評価の回答は、これと同じ方法を提案していますが、より多くのコンテキストと説明があります
George Mauer

@GeorgeMauerはあなたが正しいかもしれません。どちらも「HttpClient(handler)」からhttpClientを作成しています。私の場合、httpClientPool.GetOrCreateHttpClient()から_httpClientを作成しています
Waqar UlHaq

1
しかし、あなたは実際にそれをあなたの答えで示したり、違いや利点を説明したりしません(それは実際には問題ではありませんが、私はそれについて心配していません)。私は失礼なことをしようとしているわけではありません。この答えが誰に役立つかを明確にすることが重要です。
George Mauer
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.