如何使用System.Net.Http.HttpClient获取响应cookies?

8

之前已经有人问过这个问题,但是我没有找到明确的答案。使用System.Net.Http.HttpClient可以获取响应cookies吗?


你有没有查看这个问题描述中提到的CookieContainer https://dev59.com/XmMl5IYBdhLWcg3w966L? - Darrel Miller
是的,我有看过一些相关帖子。但是它们都没有展示如何从响应中获取cookies。 - Alex I
2个回答

6
以下是我用于访问服务器生成的 cookie 的一些示例代码。我刚测试了一下,它对我有效。不过我更改了凭据。如果您想看到它的工作原理,您需要创建一个自己的 nerddinner 账户。
    [Fact]
    public async Task Accessing_resource_secured_by_cookie()
    {
        var handler = new HttpClientHandler();
        var httpClient = new HttpClient(handler);

        Assert.Equal(0, handler.CookieContainer.Count);

        // Create a login form
        var body = new Dictionary<string, string>() 
        {
            {"UserName",  "<username>"},
            {"Password", "<password>"},
            {"RememberMe", "false"}
        };
        var content = new FormUrlEncodedContent(body);

        // POST to login form
        var response = await httpClient.PostAsync("http://www.nerddinner.com/Account/LogOn?returnUrl=%2F", content);

        // Check the cookies created by server
        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
        Assert.Equal(1, handler.CookieContainer.Count);
        var cookies = handler.CookieContainer.GetCookies(new Uri("http://www.nerddinner.com"));
        Assert.Equal(".ASPXAUTH", cookies[0].Name);

        // Make new request to secured resource
        var myresponse = await httpClient.GetAsync("http://www.nerddinner.com/Dinners/My");

        var stringContent = await myresponse.Content.ReadAsStringAsync();
        Assert.Equal(HttpStatusCode.OK, myresponse.StatusCode);
    }

从代码中可以看出,你无法直接从HTTP响应消息中获取响应cookie。我怀疑HttpClientHandler在返回响应之前会剥离响应头。然而,响应中的cookie已经被放置在CookieContainer中,你可以从那里访问它们。


对我不起作用。使用HttpWebRequest发送的相同请求返回了三个cookie,而HttpClient仅返回一个。这是否与cookie类型有关?HttpClient未返回的cookie是由FederatedAuthentication ASP.NET MVC模块生成的FedAuth和FetAuth1 cookie。 - Alex I
1
@AlexI 当你说“HttpClient只返回1个”时,你是指HttpResponseMessage Headers中只有1个cookie,还是指CookieContainer只包含1个?如果是后者,那么我很困惑,因为在底层,HttpClient使用的代码与HttpWebRequest / HttpWebResponse完全相同。 - Darrel Miller

2

要获取响应cookie,您可以使用此方法:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接