พยายามดิ้นรนเพื่อให้คุกกี้ไม่ตอบสนองกับ HttpClient ใน. net 4.5


107

ฉันมีรหัสต่อไปนี้ที่ใช้งานได้สำเร็จ ฉันคิดไม่ออกว่าจะเอาคุกกี้ออกจากการตอบกลับอย่างไร เป้าหมายของฉันคือฉันต้องการตั้งค่าคุกกี้ในคำขอและนำคุกกี้ออกจากการตอบกลับ ความคิด?

private async Task<string> Login(string username, string password)
{
    try
    {
        string url = "http://app.agelessemail.com/account/login/";
        Uri address = new Uri(url);
        var postData = new List<KeyValuePair<string, string>>
        {
            new KeyValuePair<string, string>("username", username),
            new KeyValuePair<string, string>("password ", password)
        };

        HttpContent content = new FormUrlEncodedContent(postData);
        var cookieJar = new CookieContainer();
        var handler = new HttpClientHandler
        {
            CookieContainer = cookieJar,
            UseCookies = true,
            UseDefaultCredentials = false
        };

        var client = new HttpClient(handler)
        {
            BaseAddress = address
        };


        HttpResponseMessage response = await client.PostAsync(url,content);
        response.EnsureSuccessStatusCode();
        string body = await response.Content.ReadAsStringAsync();
        return body;
    }
    catch (Exception e)
    {
        return e.ToString();
    }
}

นี่คือคำตอบที่สมบูรณ์:

HttpResponseMessage response = await client.PostAsync(url,content);
response.EnsureSuccessStatusCode();

Uri uri = new Uri(UrlBase);
var responseCookies = cookieJar.GetCookies(uri);
foreach (Cookie cookie in responseCookies)
{
    string cookieName = cookie.Name;
    string cookieValue = cookie.Value;
}

ด้วยความอยากรู้อยากเห็นฉันถามได้ไหมว่าทำไมคุณถึงต้องการอ่านคุกกี้บนไคลเอนต์? ความเข้าใจของฉันคือคุกกี้ใช้สำหรับส่งข้อมูลไปยังเซิร์ฟเวอร์ไม่ใช่เพื่อส่งคืนข้อมูล
Darrel Miller

ฉันใช้คุกกี้ที่ส่งคืนในการโทรที่ส่งคืน JSON เพื่อที่ฉันจะได้ไม่ต้องทำการเรียกการให้สิทธิ์แยกต่างหากสำหรับการโทร JSON แต่ละครั้ง กล่าวคือฉันมีบันทึกการโทร / Home / GetData ซึ่งส่งคืน JSON แต่ถ้าได้รับอนุญาตเท่านั้น ตามคำขอของลูกค้าฉันเพิ่มคุกกี้เพื่อให้ / Home / GetData ตอบสนอง มิฉะนั้นจะพูดว่า "403" ไม่ได้รับอนุญาต
Peter Kellner

การตั้งค่าส่วนหัวการอนุญาตเป็นส่วนหัวเริ่มต้นเกือบจะมีประสิทธิภาพและเป็นมาตรฐานมากกว่าเล็กน้อย ไม่มีวิธีใดที่เซิร์ฟเวอร์จะตั้งค่าส่วนหัวการตรวจสอบสิทธิ์โดยอัตโนมัติในนามของไคลเอ็นต์
Darrel Miller

1
ขอบคุณสำหรับคำแนะนำ Darrel คุณมีตัวอย่างของสิ่งที่อาจดูเหมือนใน asp.net หรือไม่? ฉันต่อสู้กับสิ่งนี้สำหรับ monotouch ของฉันและตอนนี้แอพ windows store ของฉัน ฉันจะมีความสุขถ้ามีวิธีง่ายๆ นี่เป็นความเจ็บปวดโดยเฉพาะกับ async และรอตอนนี้ในแอพ windows store
Peter Kellner

คำตอบ:


170

CookieContainer.Add(uri, cookie)หากต้องการเพิ่มคุกกี้เพื่อคำขอเติมภาชนะคุกกี้ก่อนคำขอด้วย หลังจากส่งคำขอแล้วคอนเทนเนอร์คุกกี้จะถูกเติมโดยอัตโนมัติด้วยคุกกี้ทั้งหมดจากการตอบกลับ จากนั้นคุณสามารถเรียก GetCookies () เพื่อเรียกคืนได้

CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;

HttpClient client = new HttpClient(handler);
HttpResponseMessage response = client.GetAsync("http://google.com").Result;

Uri uri = new Uri("http://google.com");
IEnumerable<Cookie> responseCookies = cookies.GetCookies(uri).Cast<Cookie>();
foreach (Cookie cookie in responseCookies)
    Console.WriteLine(cookie.Name + ": " + cookie.Value);

Console.ReadLine();

8
หมายเหตุ: หลังจากได้รับคุกกี้เริ่มต้นในการโทรครั้งแรกเมื่อเข้าถึงหน้าใด ๆ จากโดเมนเดียวกันคุกกี้จะถูกส่งโดยอัตโนมัติโดยไม่จำเป็นต้องมีขั้นตอนเพิ่มเติม
Jahmic

คุณต้องเพิ่ม "โดยใช้ System.linq;"
Cabuxa Mapache

^^ System.Linq จำเป็นต้องใช้ก็ต่อเมื่อคุณต้องการใช้เมธอด. Cast <> ซึ่งไม่จำเป็นสำหรับการดึงคุกกี้ แต่ควรอธิบายด้วยตนเอง :)
MikeDub

เป็นไปได้ไหมที่จะรับคุกกี้ในลักษณะเดียวกันหากhttpclientสร้างจากโรงงาน httpclient? คือเพิ่มวิธีการสร้างในบริการ
AddHttpClient

ในการรับ Async เราได้ทำการอ้างอิงถึง "google.com" แล้วเหตุใดเราจึงต้องประกาศ URI พร้อมการอ้างอิงอีกครั้ง
Malcolm Salvador

9

มีทางเลือกอื่นหากคุณไม่มีสิทธิ์เข้าถึงHttpClientและไม่สามารถฉีดไฟล์CookieContainer. ใช้งานได้ใน. NET Core 2.2:

private string GetCookie(HttpResponseMessage message)
{
    message.Headers.TryGetValues("Set-Cookie", out var setCookie);
    var setCookieString = setCookie.Single();
    var cookieTokens = setCookieString.Split(';');
    var firstCookie = cookieTokens.FirstOrDefault();
    var keyValueTokens = firstCookie.Split('=');
    var valueString = keyValueTokens[1];
    var cookieValue = HttpUtility.UrlDecode(valueString);
    return cookieValue;
}

1
ยอดเยี่ยมและดิบ แต่สิ่งที่ฉันต้องการ ... ทำได้ดีมากขอบคุณ
Vedran Mandić

5

คุณสามารถรับค่าคุกกี้ได้อย่างง่ายดายด้วย URL ที่กำหนด

private async Task<string> GetCookieValue(string url, string cookieName)
{
    var cookieContainer = new CookieContainer();
    var uri = new Uri(url);
    using (var httpClientHandler = new HttpClientHandler
    {
        CookieContainer = cookieContainer
    })
    {
        using (var httpClient = new HttpClient(httpClientHandler))
        {
            await httpClient.GetAsync(uri);
            var cookie = cookieContainer.GetCookies(uri).Cast<Cookie>().FirstOrDefault(x => x.Name == cookieName);
            return cookie?.Value;
        }
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.