System.Net.Http.HttpClient如何选择身份验证类型?

6
假设我使用 HttpClient 发送一个请求到受保护的端点,代码如下:
var httpClient = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "url");
var response = await httpClient.SendAsync(request);

我随后收到以下标头的响应:
HTTP/1.1 401 Unauthorized
Content-Type: text/html
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
WWW-Authenticate: Basic
Date ...

从响应头中,我看到可以通过三种不同的方式与服务器进行身份验证(Negotiate、NTLM和Basic)。然后,我将我的代码更新为:

var httpClientHandler = new HttpClientHandler
{
    Credentials = new NetworkCredential
    {
        UserName = "username",
        Password = "password"
    }
};
var httpClient = new HttpClient(httpClientHandler);
var request = new HttpRequestMessage(HttpMethod.Get, "url");
var response = await httpClient.SendAsync(request);

我再次执行程序,这一次得到了200 OK的返回。一切都好。
如果我使用 Fiddler 检查请求,我会发现 HttpClient 决定使用“Negotiate”作为身份验证方法。
我的问题是: HttpClient 如何决定使用哪种身份验证类型?它是否对某些身份验证类型有优先顺序?
关于 NetworkCredential 的文档指出:
引用:

NetworkCredential 类是一个基类,用于提供基于密码的身份验证方案(如基本身份验证、摘要身份验证、NTLM 和 Kerberos)中的凭据。

因此,我知道我提供的凭据可以应用于所有三种身份验证类型,但我至今仍未能弄清它如何 / 为什么选择特定的身份验证类型。
非常感谢您提供任何有关此问题的见解!

响应中是按顺序排列的。谈判首先出现,而且系统可以处理谈判,所以它继续尝试了它。 - Steve
1个回答

0

你可以使用 GetCredential 方法,它会给你带有认证类型的凭据。有点奇怪但是有效:

var httpClientHandler = new HttpClientHandler
{
    Credentials = new NetworkCredential
    {
        UserName = "username",
        Password = "password"       
    }.GetCredential("*", 80, "Basic") // Substitute * and 80 with url and port if possible
};
var httpClient = new HttpClient(httpClientHandler);
var request = new HttpRequestMessage(HttpMethod.Get, "url");
var response = await httpClient.SendAsync(request);

评论澄清后

当您有多个身份验证类型时,客户端必须使用最强的可用方法(但有时很难确定)。

来源: HTTP身份验证 - WWW-Authenticate头 - 多个领域


嗨,Oscar,感谢你抽出时间来看这个问题。我不确定你的答案是否涵盖了当有多个选项可用时HttpClient选择使用哪种身份验证类型的情况。但再次感谢您的贡献! :) - Lasse Christiansen
哦,我明白了,我以为你在尝试选择身份验证类型GetCredential("*", 80, "Basic") - Oscar Vicente Perez

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