使用C# HttpClient无法获取任何cookie

6
我正在使用C#和HttpClient类尝试在Spotify登录页面获取cookies。然而,当我知道有cookie被设置时,CookieContainer总是为空。我没有发送任何头文件,但它仍应该给我cookie(s),因为当我使用Python(requests模块)发送不带任何头文件的GET请求时,我得到了csrf令牌。这是我的代码:
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Collections;
using System.Web;

class Program
{
    static void Main()
    {
        Task t = new Task(MakeRequest);
        t.Start();
        Console.WriteLine("Getting cookies!");
        Console.ReadLine();
    }

    static async void MakeRequest()
    {
        CookieContainer cookies = new CookieContainer();
        HttpClientHandler handler = new HttpClientHandler();

        handler.CookieContainer = cookies;
        Uri uri = new Uri("https://accounts.spotify.com/en/login/?_locale=en-US&continue=https:%2F%2Fwww.spotify.com%2Fus%2Faccount%2Foverview%2F");
        HttpClient client = new HttpClient(handler);
        var response = await client.GetAsync(uri);
        string res = await response.Content.ReadAsStringAsync();
        Console.WriteLine(cookies.Count);
        foreach (var cookie in cookies.GetCookies(uri)) {
            Console.WriteLine(cookie.ToString());
        }
    }
}

对我来说看起来很简单,但程序总是显示没有 cookie。 有人知道发生了什么吗?


1
你为什么认为有cookie被发送回来了? - DavidG
@DavidG 我说过我在Python中测试了同样的程序,当我试图获取cookies时,我得到了csrf令牌。 - Crisp Apples
@CrispApples,你在处理程序 handler.UseCookies 上启用了 cookie 吗? - Nkosi
UseCookies = true 是默认设置。我建议使用静态 HttpClient。可能是 Lazy<HttpClient> httpClient = new Lazy<HttpClient>(() => { HttpClientHandler handler = new HttpClientHandler { (在此处设置新的 CookieContainer 或使用静态的 -> 以存储所有“会话”的 Cookies) } 等等 }。在我看来,它在所有情况下都能更好地工作。 - Jimi
如果使用FW 4.7.2,则HttpClientHandler还支持SslProtocols属性,该属性允许直接通过处理程序设置SSL协议(除了ServerCertificateCustomValidationCallback之外)。当连接使用Https时需要设置此属性,这也可能是问题所在。 - Jimi
显示剩余3条评论
3个回答

5

您需要使用HttpClientHandler.UseCookies属性启用cookie的使用。

public bool UseCookies { get; set; }

获取或设置一个值,该值指示处理程序是否使用CookieContainer属性来存储服务器cookie,并在发送请求时使用这些cookie。
//...

CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
handler.UseCookies = true; //<-- Enable the use of cookies.

//...

刚试了一下,结果一样...没有返回任何cookie。你认为这是因为HttpClient在Set-Cookie响应头中没有考虑到cookie吗?看看我的答案。 - Crisp Apples
@CrispApples 我测试了一下,访问 https://spotify.com 并返回了 cookies。同样的 Set-Cookie 头有多个条目。对于您提供的原始 URL,容器似乎是空的。 - Nkosi
2
@CrispApples 我也测试了多个 Spotify 域名下的 URL,即使 Set-Cookie 头存在,任何对 accounts.spotify.com 的调用都会导致 cookie 容器为空。 - Nkosi
很奇怪,我在 http://www.spotify.com 上也收到了 cookie。也许 accounts.spotify.com 的 Set-Cookie 标头格式不正确或者其他问题?无论如何,我想说这个问题已经解决了,因为即使 HttpClient 自身没有获取到 csrf token,我仍然可以从 Set-Cookie 响应标头中提取它。 - Crisp Apples
1
即使将 UseCookies 设置为 true,仍未收到 cookies。 - M. Paul

1
我尝试使用Console.WriteLine(response.Headers)将响应头写入控制台,并且在控制台上打印了一个带有csrf令牌的Set-Cookie头。因此,看起来HttpClient不会将此标头中的Cookie视为实际Cookie,因此不会将这些Cookie添加到CookieContainer中。

我遇到了相同的问题,但是使用不同的URL时,它可以通过头部检测到设置的cookie。 - sirdank

0

请确保您自动解压响应。请参见我的答案: https://dev59.com/-2Uq5IYBdhLWcg3wN90t#74750572

以下是我使用的示例:

var clientHandler = new HttpClientHandler {
    AllowAutoRedirect = true,
    UseCookies = true,
    CookieContainer = cookieContainer,
    AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate, // <--
};

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