Làm cách nào để tôi đặt cookie trên HttpRequestMessage của HttpClient


246

Tôi đang cố gắng sử dụng web api HttpClientđể thực hiện một bài đăng đến điểm cuối yêu cầu đăng nhập dưới dạng cookie HTTP xác định tài khoản (đây chỉ là một cái gì đó không có #ifdeftrong phiên bản phát hành).

Làm cách nào để thêm cookie vào HttpRequestMessage?

Câu trả lời:


373

Đây là cách bạn có thể đặt giá trị cookie tùy chỉnh cho yêu cầu:

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
xử lý có thể được loại bỏ khỏi việc sử dụng câu lệnh, nó sẽ được xử lý khi http client được xử lý.
Kimi

17
Kimi là chính xác, nhưng bạn cũng không nên sử dụng HTTPClient của mình. aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
Robert McLaws

9
THẬN TRỌNG: nếu bạn chỉ sử dụng 1 phiên bản của HTTPClient để thực hiện một số yêu cầu, cookie sử dụng CookieContainer sẽ được lưu trữ. Nguy hiểm cho người dùng lấy cookie từ người dùng khác.
Acaz Souza

31
"HttpClient dự định được khởi tạo một lần và được sử dụng lại trong suốt vòng đời của một ứng dụng. Đặc biệt là trong các ứng dụng máy chủ, việc tạo một cá thể httpClient mới cho mọi yêu cầu sẽ làm cạn kiệt số lượng ổ cắm có sẵn trong tải nặng ..." Từ đây: asp .net / web-api / tổng quan / nâng cao /
Mạnh mẽ

4
@SergeyT vậy người ta sẽ làm gì khi anh ta cần thực hiện các cuộc gọi phiên riêng lẻ đến cùng một tài nguyên? :)
AgentFire

336

Các câu trả lời được chấp nhận là cách chính xác để làm điều này trong nhiều trường hợp. Tuy nhiên, có một số tình huống bạn muốn đặt tiêu đề cookie theo cách thủ công. Thông thường nếu bạn đặt tiêu đề "Cookie" thì nó sẽ bị bỏ qua, nhưng đó là vì HttpClientHandlermặc định sử dụng thuộc tính của nó CookieContainercho cookie. Nếu bạn vô hiệu hóa điều đó thì bằng cách cài đặt UseCookiesthành falsebạn có thể đặt tiêu đề cookie theo cách thủ công và chúng sẽ xuất hiện trong yêu cầu, ví dụ:

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
Tôi đã theo đuổi trong nhiều ngày, một lỗi trong đó các yêu cầu được gửi bằng SendAsync không gửi tiêu đề cookie; điều này giúp tôi nhận ra rằng, trừ khi bạn đặt UseCookies = false trong Trình xử lý, nó sẽ không chỉ sử dụng CookieContainer mà còn âm thầm bỏ qua bất kỳ Cookie nào được lưu trữ trong tiêu đề yêu cầu! Cảm ơn bạn rất nhiều!
Fernando Neira

14
Câu trả lời này cực kỳ hữu ích cho bất kỳ ai đang cố gắng sử dụng HttpClient làm proxy!
cchamberlain

3
Hãy thử điều này ngay bây giờ ... nếu nó hoạt động ... bạn xứng đáng được ôm Canada tốt.
Maxime Rouiller

11
THẬN TRỌNG: nếu bạn chỉ sử dụng 1 phiên bản của HTTPClient để thực hiện một số yêu cầu, cookie sử dụng CookieContainer sẽ được lưu trữ. Nguy hiểm cho người dùng lấy cookie từ người dùng khác.
Acaz Souza

9
Điều ngu ngốc đó sẽ tạo ra một ngoại lệ khi ai đó cố gắng thêm tiêu đề "Cookie" thay vì âm thầm mất nó. Chi phí cho tôi một giờ của cuộc sống của tôi. Cảm ơn giải pháp.
stmax

5

Sau khi dành hàng giờ cho vấn đề này, không có câu trả lời nào ở trên giúp tôi vì vậy tôi đã tìm thấy một công cụ thực sự hữu ích.

Đầu tiên, tôi đã sử dụng Fiddler 4 của Telerik để nghiên cứu các Yêu cầu Web của tôi một cách chi tiết

Thứ hai, tôi đã xem qua plugin hữu ích này cho Fiddler:

https://github.com/sunilpottumuttu/FiddlerGenerateHttpClientCode

Nó sẽ chỉ tạo mã C # cho bạn. Một ví dụ là:

        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;

Lưu ý rằng tôi đã phải nhận xét hai dòng vì plugin này chưa hoàn toàn hoàn hảo nhưng nó vẫn hoàn thành công việc.

TUYÊN BỐ TỪ CHỐI: Dù sao tôi cũng không được liên kết hoặc xác nhận bởi Telerik hoặc tác giả của plugin.


2
Đây thực chất là cùng một câu trả lời như câu hỏi này , phần duy nhất của nó liên quan đến cookie là phần bổ sung cuối cùng của tiêu đề. Lưu ý tất cả những lời cảnh báo trong câu trả lời đó
George Mauer

4

Đối với tôi, giải pháp đơn giản hoạt động để đặt cookie trong đối tượng 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);
}

Lưu ý rằng câu trả lời được chấp nhận thực hiện nhiều tấn và xử lý nhiều điều kiện cạnh hơn so với điều này. Nó có thể được sử dụng để làm những việc như chỉ http hoặc cookie có phạm vi, cookie đa trị liệu, v.v ... Câu trả lời được đánh giá cao thứ hai đề xuất phương pháp tương tự như vậy nhưng với nhiều bối cảnh và giải thích hơn
George Mauer

@GeorgeMauer có thể là bạn đúng. Cả hai đều tạo httpClient từ "HttpClient (handler)". Trong trường hợp của tôi, tôi đang tạo _httpClient từ httpClientPool.GetOrCreateHttpClient ()
Waqar UlHaq

1
Nhưng bạn không thực sự cho thấy rằng trong câu trả lời của bạn cũng như không giải thích sự khác biệt hoặc lợi ích (nó cũng không thực sự là câu hỏi, nhưng tôi không lo lắng về điều đó). Tôi không cố tỏ ra thô lỗ, điều quan trọng là phải rõ ràng câu trả lời này sẽ hữu ích cho ai sẽ không được những người khác giúp đỡ tốt hơn.
George Mauer
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.