域的 Cookie 未用于子域

Cookie for domain not being used for subdomains

我使用 HttpClient in my app to send my user/password to a service that returns some cookies that I can later use for all my other requests. The service is located at https://accounts.dev.example.com/login and returns two cookies that have Domain=.dev.example.com. The issue I'm finding is that, in some machines (Windows Domain Controllers), these cookies are not being used when I request resources in subdomains like https://accounts.dev.example.com/health-check, but according to the MDN docs 域的 cookie 可用于向子域请求资源:

Domain= Optional

Specifies those hosts to which the cookie will be sent. If not specified, defaults to the host portion of the current document location (but not including subdomains). Contrary to earlier specifications, leading dots in domain names are ignored. If a domain is specified, subdomains are always included.

您知道如何正确配置 HttpClient 以将域 cookie 传递给子域请求吗?

更多细节:

我在 https://accounts.dev.example.com/login 的身份验证服务 return 生成的 cookie 在 HTTP headers:

中看起来像这样
Set-Cookie: AK=112233;Version=1;Domain=.dev.example.com;Path=/;Max-Age=5400;Secure;HttpOnly, 
Set-Cookie: AS=445566;Version=1;Domain=.dev.example.com;Path=/;Max-Age=5400;Secure;HttpOnly, 

然后我可以在普通工作站中使用以下任一调用来查询 C# 的 CookieContainer

cookies.GetCookies("https://accounts.dev.example.com")
cookies.GetCookies("https://dev.example.com")

两者都会 return 2 个 cookie,例如:

$Version=1; AK=112233; $Path=/; $Domain=.dev.example.com
$Version=1; AS=445566; $Path=/; $Domain=.dev.example.com

但在其他机器(域控制器的)中,第一次调用将 return 一个空列表,而第二次调用将 return 2 个 cookie。

为什么 CookieContainer.GetCookies 的行为会因 运行 代码的机器而异?

我的工作站正在使用 Microsoft Windows 10 Home Single Language (.Net 4.0.30319.42000),DC 正在使用 Microsoft Windows Server 2012 R2 Datacenter (.Net 4.0.30319.36399)

密码

这是我的代码的修改版本:

public static async Task<string> DoAuth(CookieContainer cookies,
                                        Dictionary<string, string> postHeaders,
                                        StringContent postBody)
{
    try
    {
        using (var handler = new HttpClientHandler())
        {
            handler.CookieContainer = cookies;
            using (var client = new HttpClient(handler, true))
            {
                foreach (var key in postHeaders.Keys)
                    client.DefaultRequestHeaders.Add(key, postHeaders[key]);

                var response = await client.PostAsync("https://accounts.dev.example.com/login", postBody);
                response.EnsureSuccessStatusCode();
                
                // This line returns 0 in Domain Controllers, and 2 in all other machines
                Console.Write(cookies.GetCookies("https://accounts.dev.example.com").Count);

                return await response.Content.ReadAsStringAsync();
            }
        }
    }
    catch (HttpRequestException e)
    {
        ...
        throw;
    }
}

因为我找不到这个问题的答案(也不在 TechNet 中),我决定采用以下解决方案,它有效,但不确定是否有解决问题的正确方法问题:

foreach (Cookie cookie in cookies.GetCookies(new Uri("https://dev.example.com")))
{
    cookies.Add(new Uri("https://accounts.dev.example.com"), new Cookie(cookie.Name, cookie.Value, cookie.Path, ".accounts.dev.example.com"));
}

因此,我正在为我的应用程序应将这些 cookie 发送到的每个子域复制 cookie。

潜在的问题似乎是 Set-Cookie header 中的错误。问题的原因似乎是 Set-Cookie header 中的 Version= 组件。这使得 CookieContainer 掉落在它的脸上并导致奇怪的 $Version$Domain cookie 然后在后续的客户端请求中被发送。据我所知,也没有办法删除这些损坏的饼干。使用原始域迭代 GetCookies() 不会显示错误的 cookie。