我正在尝试使用HttpClient
与自托管的WebAPI客户端进行通信。使用以下代码创建客户端:
HttpClientHandler clientHandler = new HttpClientHandler()
{
UseDefaultCredentials = true,
PreAuthenticate = true
};
var client = new HttpClient(clientHandler);
我们在服务器端设置了:
HttpListener listener = (HttpListener)app.Properties[typeof(HttpListener).FullName];
listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication;
在Startup
文件中。
问题是我在处理请求之前得到两个(或一个预先认证后的一个)401错误。
在提琴手中,序列看起来像这样:
First request:
Authorization: Negotiate TlRMTVNTUAABAAAAl7II4gcABwAxAAAACQAJACgAAAAGAbEdAAAAD1dTMTEzLTEyMFNXVC0xMTM=
Answer:
WWW-Authenticate: Negotiate TlRMTVNTUAACAAAADgAOADgAAAAVwonisrQOBMTKHhKwCkgCAAAAAJoAmgBGAAAABgGxHQAAAA9TAFcAVAAtADEAMQAzAAIADgBTAFcAVAAtADEAMQAzAAEAEgBXAFMAMQAxADMALQAxADIAMAAEABYAcwB3AHQALQAxADEAMwAuAGwAbwBjAAMAKgBXAFMAMQAxADMALQAxADIAMAAuAHMAdwB0AC0AMQAxADMALgBsAG8AYwAFABYAQQBMAEQASQA5ADkAOQAuAGwAbwBjAAcACACkGh0XVY3QAQAAAAA=
Second request (succeeds):
Authorization: Negotiate TlRMTVNTUAADAAAAAAAAAFgAAAAAAAAAWAAAAAAAAABYAAAAAAAAAFgAAAAAAAAAWAAAAAAAAABYAAAAFcKI4gYBsR0AAAAPfJafWSuLL0sAXYtWCynOqg==
那么为什么我的客户端不是第一次发送正确的授权令牌,但总是需要这种两次方法?
答案 0 :(得分: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
GET
请求。401 Unathorized
响应,并在WWW-Authenticate
标头中通知客户端它支持NTLM
身份验证。因此,您可以获得第一个401
响应代码。Authorization
标头中将域名和用户名发送给服务器。请注意,仅基于这些信息,客户端无法进行身份验证。401
响应代码的地方。200
响应代码和请求的资源发送回客户端。答案 1 :(得分:2)
面对类似的问题,经过大量的回答,其中没有一个有效。以下工作,并没有提出两个401&#39>:
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);
答案 2 :(得分:0)