简体   繁体   English

使用 HttpClient 的随机 401 未授权错误

[英]Random 401 Unauthorized errors using HttpClient

I am using HttpClient to invoke a Web Api REST endpoint and once in a while I see a random 401 Unauthorized Status.我正在使用 HttpClient 调用 Web Api REST 端点,偶尔我会看到一个随机的 401 未授权状态。

Here is my HttpClient wrapper that was created for re usability purposes.这是我的 HttpClient 包装器,它是为可重用性目的而创建的。 I have modified it to keep it simple for this post without modifying the core parts.我已经修改了它以保持这篇文章的简单而不修改核心部分。

public class HttpHelper
{
        public const string JsonContentType = "application/json";

        public T PostAsJsonObject<T>(string uri, T t) where T : class
        {
            using (HttpResponseMessage response = PostJsonHttpRequest(uri, JsonContentType, t))
            {
                response.EnsureSuccessStatusCode();
                return response.Content.ReadAsAsync<T>().Result;
            }
        }

        private HttpResponseMessage PostJsonHttpRequest<T>(string uri, string contentType, T content) where T : class
        {
            if (String.IsNullOrEmpty(uri))
            {
                throw new ArgumentNullException("uri");
            }
            HttpResponseMessage response = CreateHttpClient(contentType).PostAsJsonAsync(uri, content).Result;
            return response;
        }

        private HttpClient CreateHttpClient(string contentType)
        {
           var credentials = new NetworkCredential("srvuser", "somepwd", "somedomain");
           return new HttpClient(new HttpClientHandler { Credentials = credentials, PreAuthenticate = true });
        }
}

Here is how I am invoking it.这是我调用它的方式。

var httpHelper = new HttpHelper();
var response = httpHelper.PostAsJsonObject("https://xyz.pvt/inventory/api/orders", "234");

Most of the time it works fine, but once in a while I get 401 Unauthorized error.大多数情况下它工作正常,但偶尔我会收到 401 Unauthorized 错误。 I am trying to figure out what might be causing it.我试图找出可能导致它的原因。

System.Net.Http.HttpRequestException: Response status code does not indicate success: 401 (Unauthorized). System.Net.Http.HttpRequestException:响应状态代码未指示成功:401(未经授权)。 at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode() at HttpHelper.PostAsJsonObject[T](String uri, T t)在 System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode() 在 HttpHelper.PostAsJsonObject[T](String uri, T t)

I looked at asp.net logs, and found a strange pattern.我查看了asp.net日志,发现了一个奇怪的模式。 Most of the time, I see pair of entries (401 followed by 200 OK) such as大多数情况下,我会看到一对条目(401 后跟 200 OK),例如

2017-02-09 12:04:13 104.68.45.152 POST /inventory/api/orders/ - 80 - 132.64.78.120 HTTP/1.1 - 401 2 5 764 
2017-02-09 12:04:16 104.68.45.152 POST /inventory/api/orders/ - 80 somedomain\srvusr 132.64.78.120 HTTP/1.1 - 200 0 0 2917

2017-02-09 12:04:16 104.68.45.152 POST /inventory/api/orders/ - 80 - 132.64.78.120 HTTP/1.1 - 401 2 5 0 
2017-02-09 12:04:19 104.68.45.152 POST /inventory/api/orders/ - 80 somedomain\srvusr 132.64.78.120 HTTP/1.1 - 200 0 0 2230

But occasionally I just see 401但偶尔我只看到 401

2017-02-09 12:14:04 104.68.45.152 POST /inventory/api/orders/ - 80 - 132.64.78.120 HTTP/1.1 - 401 2 5 0

REST api is implemented using ASP.NET Web Api 2 running on .NET 4.6.1 and in IIS 7.5, it is setup with just Windows Authentication. REST api 是使用在 .NET 4.6.1 和 IIS 7.5 上运行的 ASP.NET Web Api 2 实现的,它仅使用 Windows 身份验证进行设置。

Not sure what is causing the authentication to fail once in a while.不确定是什么导致身份验证偶尔失败。

UPDATE:更新:

Here is the new code that I wrote using async await pattern.这是我使用异步等待模式编写的新代码。

public class HttpHelper
{
        public const string JsonContentType = "application/json";

        private HttpClient CreateHttpClient(string url, string contentType)
        {
            var handler = new HttpClientHandler
            {
                Credentials = new CredentialCache { { new Uri(url), "NTLM", new NetworkCredential("srvuser", "somepwd", "somedomain") } },
                PreAuthenticate = true
            };
            var httpClient = new HttpClient(handler);
            httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(contentType));
            return httpClient;
        }

        private async Task<HttpResponseMessage> PostJsonHttpRequestAsync<T>(string url, string contentType, T content) where T : class
        {
            if (string.IsNullOrEmpty(url))
            {
                var exception = new ArgumentNullException("url");
                throw exception;
            }

            var response = await CreateHttpClient(url, contentType).PostAsJsonAsync(url, content);

            return response;
        }

        public async Task<T> PostAsJsonObjectAsync<T>(string uri, T t) where T : class
        {
            using (var response = await PostJsonHttpRequestAsync(uri, JsonContentType, t))
            {
                return await response.Content.ReadAsAsync<T>(new[]
                    {
                      new JsonMediaTypeFormatter
                      {
                         SerializerSettings = { NullValueHandling = NullValueHandling.Ignore, TypeNameHandling = TypeNameHandling.Auto }
                      }
                    }.AsEnumerable());
            }
        }
    }

Here is how I am finally invoking it.这是我最终调用它的方式。

static class TestMe
{
    static void Main()
    {
        var httpHelper = new HttpHelper();
        var responseTask = httpHelper.PostAsJsonObjectAsync("https://xyz.pvt/inventory/api/orders", "234");

        responseTask.Wait(120000);
        var response = responseTask.Result;
        Console.WriteLine(response);
    }
}

Even now I see same problem.即使现在我也看到同样的问题。 Still getting random 401 Unauthorized errors.仍然随机出现 401 Unauthorized 错误。

UPDATE 2更新 2

I did some more investigation and found that these mysterious 401 errors are coming from IIS.我做了更多调查,发现这些神秘的 401 错误来自 IIS。 When ever these mysterious 401 error occurs, IIS log has a corresponding 401 error entry, but in this case the request never reaches asp.net pipeline.当这些神秘的 401 错误发生时,IIS 日志中有一个相应的 401 错误条目,但在这种情况下,请求永远不会到达 asp.net 管道。 As if for some reason the request is bounced back by IIS with 401 error.好像出于某种原因,请求被 IIS 以 401 错误退回。

Without going into too much in depth, I know that windows authentication in IIS uses 2 requests to manage authentication based on how the HttpClient is configured.无需深入研究,我知道 IIS 中的 Windows 身份验证使用 2 个请求来管理基于 HttpClient 的配置方式的身份验证。 So a successful authentication request will have a 401.2 followed by 200 OK.因此,成功的身份验证请求将具有 401.2 后跟 200 OK。 It is what happening most of the time.这是大多数时候发生的事情。 Occasionally thou I notice there is a 401.2, followed by just 401. The same request upon retry attempt goes thru fine (401.2 followed by 200 OK).有时你我会注意到有一个 401.2,然后是 401。重试时相同的请求会通过(401.2 后跟 200 OK)。

Really appreciate if anyone have some insight into this issue and a potential resolution to it.如果有人对这个问题有一些洞察力和潜在的解决方案,真的很感激。

Are you certain that your code is even the problem?您确定您的代码甚至是问题所在吗? I don't know the details of your situation, but it's possible the web server is sometimes sending you back 401 responses for no good reason.我不知道您的情况的详细信息,但 Web 服务器有时可能会无缘无故地向您发送 401 响应。

Here's something you could do to test this theory: run two (or more) instances of your program simultaneously, ideally on different machines.您可以执行以下操作来测试该理论:同时运行程序的两个(或更多)实例,最好在不同的机器上运行。 Wait until you get the 401 errors.等到您收到 401 错误。 If all instances of your code start receiving the 401 errors at the same time, then it's almost certainly a problem on the web server.如果您的代码的所有实例同时开始收到 401 错误,那么几乎可以肯定这是 Web 服务器上的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 httpclient api 在 c# 中出现未经授权的 401 错误 - httpclient api unauthorized 401 error in c# PostAsync(承载身份验证)后未经授权的HttpClient 401 - HttpClient 401 Unauthorized after PostAsync (Bearer Auth) HttpClient 不接受授权标头(401 未授权)? - HttpClient not accepting Authorization headers (401 Unauthorized)? 401 在第二个 HttpClient/HttpWebRequest 调用上未经授权 - 401 Unauthorized on SECOND HttpClient/HttpWebRequest call 通过HttpClient使用Google Cloud AutoML时收到401“未经授权”错误 - Receiving 401 “Unauthorized” error while using Google Cloud AutoML via HttpClient 使用HttpClient在本地主机上调用rest api导致401未经授权的IIS 8.5 - Calling rest api on localhost using HttpClient causing 401 Unauthorized, IIS 8.5 使用 HttpClient.GetAsync() 使用具有基本身份验证的 WCF REST 服务导致 (401) 未经授权 - Consuming a WCF REST service with Basic authentication using HttpClient.GetAsync() results in (401) Unauthorized StatusCode:401,ReasonPhrase:使用C#通过HTTPClient调用Post方法时,显示“未授权” - StatusCode: 401, ReasonPhrase: 'Unauthorized' gets displayed when calling a Post Method through HTTPClient using C# 401未经授权使用Google任务 - 401 unauthorized using google task 401未经授权使用Yahoo OAuth - 401 Unauthorized using Yahoo OAuth
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM