ฉันจะตั้งค่าคุกกี้บน HttpClient's HttpRequestMessage ได้อย่างไร


247

ฉันพยายามที่จะใช้ API เว็บที่HttpClientจะทำโพสต์ไปยังปลายทางที่ต้องเข้าสู่ระบบในรูปแบบของคุกกี้ของ HTTP ที่ระบุบัญชี (นี้เป็นเพียงสิ่งที่เป็น#ifdef'ed จากรุ่นที่วางจำหน่าย)

ฉันจะเพิ่มคุกกี้วิธีไปHttpRequestMessage?

คำตอบ:


374

นี่คือวิธีที่คุณสามารถตั้งค่าคุกกี้ที่กำหนดเองสำหรับคำขอ:

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
ตัวจัดการอาจถูกลบออกจากการใช้คำสั่งมันจะถูกกำจัดเมื่อลูกค้า http ถูกกำจัด
Kimi

17
Kimi นั้นถูกต้อง แต่คุณไม่ควรใช้ HttpClient ในการใช้ aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
Robert McLaws

9
ข้อควรระวัง: หากคุณใช้ HttpClient เพียง 1 อินสแตนซ์เพื่อทำหลายคำขอคุกกี้ที่ใช้ CookieContainer จะถูกแคช เป็นอันตรายต่อผู้ใช้รับคุกกี้จากผู้ใช้รายอื่น
Acaz Souza

31
"HttpClient มีวัตถุประสงค์ที่จะ instantiated ครั้งและอีกครั้งที่ใช้ตลอดชีวิตของโปรแกรมประยุกต์โดยเฉพาะอย่างยิ่งในการใช้งานเซิร์ฟเวอร์สร้างตัวอย่าง HttpClient ใหม่สำหรับการร้องขอจะหมดจำนวนซ็อกเก็ตที่มีอยู่ภายใต้หนักทุก ... ." จากที่นี่: ASP .net / web-api / ภาพรวม / ขั้นสูง / …
SergeyT

4
@SergeyT แล้วจะทำอย่างไรเมื่อเขาต้องการที่จะทำการแยกเซสชั่นการเรียกไปยังทรัพยากรเดียวกัน? :)
AgentFire

337

คำตอบที่ได้รับการยอมรับเป็นวิธีที่ถูกต้องในการทำเช่นนี้ในกรณีส่วนใหญ่ อย่างไรก็ตามมีบางสถานการณ์ที่คุณต้องการตั้งค่าส่วนหัวของคุกกี้ด้วยตนเอง โดยปกติถ้าคุณตั้งค่าส่วนหัว "คุกกี้" จะถูกละเว้น แต่นั่นเป็นเพราะHttpClientHandlerค่าเริ่มต้นคือการใช้CookieContainerคุณสมบัติสำหรับคุกกี้ หากคุณปิดใช้งานโดยตั้งค่าUseCookiesเป็นfalseคุณสามารถตั้งค่าส่วนหัวของคุกกี้ด้วยตนเองและพวกเขาจะปรากฏในคำขอเช่น

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 ไม่ได้ส่งส่วนหัวคุกกี้ นี้ช่วยให้ฉันตระหนักว่าถ้าคุณตั้ง UseCookies = false ใน Handler มันจะไม่เพียง แต่ใช้ CookieContainer แต่ยังเงียบไม่สนใจคุกกี้ใด ๆ ที่เก็บไว้ในส่วนหัวของคำขอ! ขอบคุณมาก!
Fernando Neira

14
คำตอบนี้มีประโยชน์อย่างยิ่งสำหรับทุกคนที่พยายามใช้ HttpClient เป็นพร็อกซี!
cchamberlain

3
ลองใช้ตอนนี้ ... ถ้าได้ผล ... คุณสมควรได้รับอ้อมกอดที่ดีจากแคนาดา
Maxime Rouiller

11
ข้อควรระวัง: หากคุณใช้ HttpClient เพียง 1 อินสแตนซ์เพื่อทำหลายคำขอคุกกี้ที่ใช้ CookieContainer จะถูกแคช เป็นอันตรายต่อผู้ใช้รับคุกกี้จากผู้ใช้รายอื่น
Acaz Souza

9
สิ่งที่โง่ควรทำให้เกิดข้อยกเว้นเมื่อมีคนพยายามที่จะเพิ่มส่วนหัว "คุกกี้" แทนที่จะเงียบหายไป เสียเวลาหนึ่งชั่วโมงในชีวิต ขอบคุณสำหรับการแก้ปัญหา
stmax

5

หลังจากใช้เวลาหลายชั่วโมงกับปัญหานี้ไม่มีคำตอบข้างต้นช่วยฉันเลยฉันพบเครื่องมือที่มีประโยชน์จริงๆ

ประการแรกฉันใช้ 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 หรือผู้เขียนปลั๊กอินในอย่างไรก็ตาม


2
นี่เป็นคำตอบเดียวกับคำตอบนี้ส่วนเดียวเท่านั้นที่เกี่ยวข้องกับคุกกี้คือการเพิ่มส่วนหัวครั้งล่าสุด สังเกตคำเตือนทั้งหมดในคำตอบนั้น
George Mauer

4

สำหรับฉันแล้ววิธีง่ายๆในการตั้งค่าคุกกี้ในวัตถุ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);
}

โปรดทราบว่าคำตอบที่ได้รับการยอมรับนั้นมีจำนวนมากกว่าและจัดการกับเงื่อนไขของขอบได้มากกว่านี้ มันสามารถใช้ในการทำสิ่งต่าง ๆ เช่น http เท่านั้นหรือคุกกี้ที่กำหนดขอบเขต, คุกกี้ที่มีหลายค่า ฯลฯ ฯลฯ คำตอบที่ได้รับคะแนนสูงสุดอันดับที่สองเสนอวิธีการเดียวกันนี้ แต่มีบริบทและคำอธิบายที่มากขึ้น
George Mauer

@GeorgeMauer อาจเป็นคุณที่ถูกต้อง ทั้งคู่สร้าง httpClient จาก "HttpClient (ตัวจัดการ)" ในกรณีของฉันฉันกำลังสร้าง _httpClient จาก httpClientPool.GetOrCreateHttpClient ()
Waqar UlHaq

1
แต่คุณไม่ได้แสดงให้เห็นว่าในคำตอบของคุณหรืออธิบายความแตกต่างหรือผลประโยชน์ (มันไม่ได้เป็นคำถาม แต่ฉันไม่กังวลเกี่ยวกับเรื่องนี้) ฉันไม่ได้พยายามที่จะหยาบคายมันเป็นสิ่งสำคัญที่จะต้องชัดเจนว่าคำตอบนี้จะเป็นประโยชน์กับที่คนอื่นจะไม่ได้รับความช่วยเหลือที่ดีขึ้น
George Mauer
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.