简体   繁体   English

401 在第二个 HttpClient/HttpWebRequest 调用上未经授权

[英]401 Unauthorized on SECOND HttpClient/HttpWebRequest call

I have a application that uses the SharePoint 2010 REST API.我有一个使用 SharePoint 2010 REST API 的应用程序。 In the process of creating an Item there are multiple request done after each other:在创建 Item 的过程中,有多个请求依次完成:

1 Call: Getting Items from List: Succes 1 次调用:从列表中获取项目:成功

2 Call: Create Item: 401 Unauthorized 2 调用:创建项目:401 未授权

This is the same if I do it like this:如果我这样做也是一样的:

1 Call: Create Item: Succes 1 次调用:创建项目:成功

2 Call: Delete Item: 401 Unauthorized 2 呼叫:删除项目:401 未经授权

What I know is that my functions work separately they DON'T work when they are called after each other.我所知道的是,我的功能独立工作,当他们在彼此之后叫他们工作。 When I close the application (Windows Phone 8.1 app) after creating a item and when restarted try to delete the item it works.当我在创建项目后关闭应用程序(Windows Phone 8.1 应用程序)并在重新启动时尝试删除它工作的项目。

First I thought it had to do with the way I handle my fields so I changed them to NULL in a finally statement but that didn't work.首先,我认为这与我处理字段的方式有关,所以我在 finally 语句中将它们更改为 NULL 但这不起作用。

    public async Task<bool> CreateNewItem(NewItem myNewItem)
    {   
        try
        {
            StatusBar statusBar = await MyStatusBar.ShowStatusBar("Creating new List Item.");
            //Retrieving Settings from Saved file
            mySettings = await MyCredentials.GetMySettings();
            myCred = new NetworkCredential(mySettings.UserName, mySettings.Password, mySettings.Domain);

            using (var handler = new HttpClientHandler { Credentials = myCred })
            {
                HttpClient client = new HttpClient(handler);
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                NewItem newItem = myNewItem;
                var jsonObject = JsonConvert.SerializeObject(newItem);

                HttpResponseMessage response = await client.PostAsync(new Uri(baseUrl + listNameHourRegistration), new StringContent(jsonObject.ToString(), Encoding.Unicode, "application/json"));
                response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                response.EnsureSuccessStatusCode();

                string responseMessage = await response.Content.ReadAsStringAsync();

                client.Dispose();

                if (responseMessage.Length > 0)
                     return true;
            }
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
            return false;
        }
        finally
        {
            request = null;
            response = null;
            myCred = null;
            mySettings = null;
        }
        
        return false;
    }

Just run into the same problem. 刚遇到同样的问题。

Anyway, the 2nd request does not follow the same authentication procedure. 无论如何,第二个请求不会遵循相同的身份验证过程。 Even if you initialize a new HttpClient object. 即使您初始化了一个新的HttpClient对象。 I sniffed the HTTP traffic. 我嗅到了HTTP流量。 交通

After the 1st request I am doing another with different credentials. 在第一个请求之后,我将使用不同的凭据进行另一个操作。 This is also ending in a 401. I am really confused... 这也以401结尾。我真的很困惑...

Seems the NTLM Handshake stucks at the 2nd of 6 steps http://www.innovation.ch/personal/ronald/ntlm.html NTLM握手似乎卡在了6个步骤的第2个步骤中http://www.innovation.ch/personal/ronald/ntlm.html

Edit: You may want to use the CSOM. 编辑:您可能要使用CSOM。 http://social.msdn.microsoft.com/Forums/office/en-US/efd12f11-cdb3-4b28-a9e0-32bfab71a419/windows-phone-81-sdk-for-sharepoint-csom?forum=sharepointdevelopment http://social.msdn.microsoft.com/Forums/office/en-US/efd12f11-cdb3-4b28-a9e0-32bfab71a419/windows-phone-81-sdk-for-sharepoint-csom?forum=sharepointdevelopment

虽然我仍然不知道实际的问题是什么,但至少我找到了一种解决方法 :使用WebRequest类而不是HttpClient

I was running into this same error when I realized I was adding the headers each time I was calling the endpoint.当我意识到每次调用端点时都添加标题时,我遇到了同样的错误。 Hopefully this will help someone.希望这会帮助某人。

Instead I initialized the HttpClient instance in my class constructor and set the headers there.相反,我在我的类构造函数中初始化了 HttpClient 实例并在那里设置了标头。 Also I learned it is better practice to only use 1 instance instead of recreating with "using" (See this article https://www.aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/ )我还了解到只使用 1 个实例而不是使用“使用”重新创建是更好的做法(请参阅本文https://www.aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/

Here's my final solution: I'm invoking CallApiAsync from another class in a loop.这是我的最终解决方案:我正在循环中从另一个类调用 CallApiAsync。

class ApiShared
    {
        private HttpClient client;

        public ApiShared()  {
            client = new HttpClient();
            client.DefaultRequestHeaders.Add("x-api-key", ConfigurationManager.AppSettings["ApiKey"]);
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        }

        public async Task<ApiResponse_Root> CallApiAsync(string endpoint)
        {
            // Make API call
            Uri endpointUri = new Uri(endpoint);
            var stringTask = client.GetStringAsync(endpointUri);
            var data = JsonConvert.DeserializeObject<ApiResponse_Root>(await stringTask);

            return data;
        }
    }

On a windows machine you can resolve this with this registry setting change:在 Windows 机器上,您可以通过以下注册表设置更改来解决此问题:

Go to the following Registry entry:转到以下注册表项:

Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa

Now add a new DWORD to the Lsa folder called: DisableLoopBackCheck and set this to 1现在添加一个新的 DWORD 到 Lsa 文件夹,名为: DisableLoopBackCheck并将其设置为1

I see that this question has been posted long back. 我看到这个问题已经发布很久了。 But I don't see a correctly working solution posted yet to this thread. 但是我没有看到正确的解决方案发布到此线程。

I faced exactly the same issue where the next requests kept on failing returning me 401 UnAuthorized. 我面临着完全相同的问题,下一个请求一直失败,并返回401 UnAuthorized。

I figured out using fiddler that from SECOND request onwards, there was a Cookie added to the request which was possibly a result of Set-Cookie response sent by the server along with first response. 我发现使用fiddler从SECOND请求开始,向该请求添加了一个Cookie,这可能是服务器与第一个响应一起发送的Set-Cookie响应的结果。

So here's how I tackled the situation - Make UseCookies false: 所以这是我处理情况的方法-将UseCookies设为false:

new HttpClientHandler { Credentials = myCred, UseCookies = false }

This should resolve your issue. 这样可以解决您的问题。 Hope this helps someone who's looking for a solution to a similar issue. 希望这对正在寻找类似问题的解决方案的人有所帮助。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM