HTTPClient在成功之前获得两个401s(发送错误的令牌)

Voo*_*Voo 15 .net c# authorization http .net-4.5

我正在尝试使用自我托管的WebAPI客户端进行通信HttpClient.使用以下代码创建客户端:

HttpClientHandler clientHandler = new HttpClientHandler()
{
    UseDefaultCredentials = true,
    PreAuthenticate = true
};
var client = new HttpClient(clientHandler);
Run Code Online (Sandbox Code Playgroud)

在服务器端我们设置:

HttpListener listener = (HttpListener)app.Properties[typeof(HttpListener).FullName];
listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication;
Run Code Online (Sandbox Code Playgroud)

Startup文件中.

问题是我在处理请求之前得到两个(或一个预先认证后)401错误.

在提琴手中,序列看起来像这样:

First request:
Authorization: Negotiate TlRMTVNTUAABAAAAl7II4gcABwAxAAAACQAJACgAAAAGAbEdAAAAD1dTMTEzLTEyMFNXVC0xMTM=
Answer:
WWW-Authenticate: Negotiate TlRMTVNTUAACAAAADgAOADgAAAAVwonisrQOBMTKHhKwCkgCAAAAAJoAmgBGAAAABgGxHQAAAA9TAFcAVAAtADEAMQAzAAIADgBTAFcAVAAtADEAMQAzAAEAEgBXAFMAMQAxADMALQAxADIAMAAEABYAcwB3AHQALQAxADEAMwAuAGwAbwBjAAMAKgBXAFMAMQAxADMALQAxADIAMAAuAHMAdwB0AC0AMQAxADMALgBsAG8AYwAFABYAQQBMAEQASQA5ADkAOQAuAGwAbwBjAAcACACkGh0XVY3QAQAAAAA=

Second request (succeeds):
Authorization: Negotiate TlRMTVNTUAADAAAAAAAAAFgAAAAAAAAAWAAAAAAAAABYAAAAAAAAAFgAAAAAAAAAWAAAAAAAAABYAAAAFcKI4gYBsR0AAAAPfJafWSuLL0sAXYtWCynOqg==
Run Code Online (Sandbox Code Playgroud)

那么为什么我的客户端不是第一次发送正确的授权令牌,但总是需要这种两次方法?

小智 15

您正在经历的是正常的,这是NTLM身份验证方案的工作方式.

1: C  --> S   GET ...

2: C <--  S   401 Unauthorized
              WWW-Authenticate: NTLM

3: C  --> S   GET ...
              Authorization: NTLM <base64-encoded type-1-message>

4: C <--  S   401 Unauthorized
              WWW-Authenticate: NTLM <base64-encoded type-2-message>

5: C  --> S   GET ...
              Authorization: NTLM <base64-encoded type-3-message>

6: C <--  S   200 Ok
Run Code Online (Sandbox Code Playgroud)
  1. 客户端向GET服务器发送请求.
  2. 由于您需要通过身份验证才能访问所请求的资源,因此服务器会发回401 Unathorized响应,并在WWW-Authenticate标头中通知客户端它支持NTLM身份验证.这是您获得第一个401响应代码的地方.
  3. 客户端将域名和用户名发送到Authorization标头中的服务器.请注意,仅基于这些信息,客户端无法进行身份验证.
  4. 服务器向客户端发送质询.它是一个随机生成的数字,称为nonce.这是您获得第二个401响应代码的地方.
  5. 客户端使用其密码的哈希值发送回服务器质询的响应,以加密随机数.
  6. 服务器将客户端的用户名,发送给客户端的质询以及从客户端接收的响应发送到域控制器.使用用户名,域控制器检索用户密码的哈希值并使用它加密质询.如果结果与客户端发送的响应匹配,则对客户端进行身份验证,然后服务器将200响应代码和请求的资源发送回客户端.


Yah*_*hya 5

遇到了类似的问题,在浏览了很多答案之后,这些答案都不起作用。以下方法有效,并且没有出现两个 401:

var credential = new NetworkCredential("username", "password", "domainname");
var myCache = new CredentialCache();

// Add the target Uri to the CredentialCache with credential object
myCache.Add(new Uri("http://targeturi/"), "NTLM", credential);

// Create an HttpClientHandler to add some settings
var handler = new HttpClientHandler();
handler.AllowAutoRedirect = true;
handler.Credentials = myCache;

// Create an HttpClient with the handler object
httpClient = new HttpClient(handler);

// Wait to get the reponse, and you can use the reponse in your code
HttpResponseMessage response = await httpClient.GetAsync(resourceUri);
Run Code Online (Sandbox Code Playgroud)

来源