Web API 2:POST请求时出现随机401未授权错误

4

我目前正在构建一个Angular 2 + ASP Web API 2应用程序,遇到了一个烦人的授权问题。

我可以使用标准身份框架创建帐户并使用Bearer令牌登录,但是当我尝试将数据POST到我的控制器时,第二个调用会出现401授权问题...

例如,下面是第一个成功POST的示例:

Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, br
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Authorization:Bearer 2x4FSZqJ6Msos870_gIl4aKjgdms1PEGNnFp2ptM6Rrgs4vtmvnMdu2nzEfBoly15CI2bQss5DVe-bkN2uSTHrMP7F6blK90DcFt095xTsWk3BJ_5RiZ-jsXOrqTZaisChIbWgGN0o-DiTEA_ojFKImgsX9yip6hloZ6GI_Cd0eg6EjX6S_PUmmyI13oiBAHKROmDvVoB4y0-DbHPnAO--x9yGxU1z_SRwFYqX8Dua7oAvpbyl2VFIqqA39DlQ0E9JPaRC0gvrBxeS-nibAaBeDUwLSAQm6HOe-vynVhQeGrBvHl7r3gicaNdaS5UZvrC43KFTe6__wR1aDaIgpMejlp-eVnjTVbcxvR16XOXrud1W-tNcoOHtoMdGKKb0IvfxK_GCety5eiiTIGWUpA26nF5cCZEIna8ZJawXRiBZVV__MEPDBlR68mJHvHVKfm5w_jupwF5_oehcKwbT_QZ92hxg4UV8uUaiisqbIe7jQ
Connection:keep-alive
Content-Length:60
Content-Type:application/json
Cookie:.AspNet.Cookies=wcZzztFwOl41pBDgXshPnYCaaQhULRqu9O6grYPDhUx4cSY8PRY1oBRQLs3gPz4ySoxQBaaehtCLDeOFzXAN7q_UMbZps82aCajwvBQewtu_SLizCRTU9UHncWy0EFnJtLAuF5u_8sKW6sNNPTHfDtmjl3UVQkkvYDBceJC5F-sISGqH-sPFwEGmoXgcKLHWfPlejxAvRCRvGbhFhrdKpk_sycoi_B0sBe9Kc8EULXlybEeUolyyrY7L5HvOUIuujLThILt6ipYEmIk8b_2x32uCq7euh5Y_RDzI009SMceOSBs6HYsqUxz6lR2F3KvlcYBQ3rDr8qALhJBnMyJsysdDIruF9dVjK7-IjdEBPXMsGCnHK5gQs_1bIflSaPBbxVPn2VzPui-WChDCdoVXRgGRRnaEtkzaTOhBZIjlLZ1DWS1MqkM-V0khFQxBDqsxll0pZTgNZuwEOLBYoWWiAK9fATXLSmtMYA2UMKoAE0M
Host:localhost:56762
Origin:http://localhost:56762
Referer:http://localhost:56762/tasks/details;id=null
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36

使用这个数据:{Title: "测试", Category: "测试", Entries: []}

现在,几秒钟后返回 401 错误的是:

Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, br
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Authorization:Bearer 2x4FSZqJ6Msos870_gIl4aKjgdms1PEGNnFp2ptM6Rrgs4vtmvnMdu2nzEfBoly15CI2bQss5DVe-bkN2uSTHrMP7F6blK90DcFt095xTsWk3BJ_5RiZ-jsXOrqTZaisChIbWgGN0o-DiTEA_ojFKImgsX9yip6hloZ6GI_Cd0eg6EjX6S_PUmmyI13oiBAHKROmDvVoB4y0-DbHPnAO--x9yGxU1z_SRwFYqX8Dua7oAvpbyl2VFIqqA39DlQ0E9JPaRC0gvrBxeS-nibAaBeDUwLSAQm6HOe-vynVhQeGrBvHl7r3gicaNdaS5UZvrC43KFTe6__wR1aDaIgpMejlp-eVnjTVbcxvR16XOXrud1W-tNcoOHtoMdGKKb0IvfxK_GCety5eiiTIGWUpA26nF5cCZEIna8ZJawXRiBZVV__MEPDBlR68mJHvHVKfm5w_jupwF5_oehcKwbT_QZ92hxg4UV8uUaiisqbIe7jQ,Bearer 2x4FSZqJ6Msos870_gIl4aKjgdms1PEGNnFp2ptM6Rrgs4vtmvnMdu2nzEfBoly15CI2bQss5DVe-bkN2uSTHrMP7F6blK90DcFt095xTsWk3BJ_5RiZ-jsXOrqTZaisChIbWgGN0o-DiTEA_ojFKImgsX9yip6hloZ6GI_Cd0eg6EjX6S_PUmmyI13oiBAHKROmDvVoB4y0-DbHPnAO--x9yGxU1z_SRwFYqX8Dua7oAvpbyl2VFIqqA39DlQ0E9JPaRC0gvrBxeS-nibAaBeDUwLSAQm6HOe-vynVhQeGrBvHl7r3gicaNdaS5UZvrC43KFTe6__wR1aDaIgpMejlp-eVnjTVbcxvR16XOXrud1W-tNcoOHtoMdGKKb0IvfxK_GCety5eiiTIGWUpA26nF5cCZEIna8ZJawXRiBZVV__MEPDBlR68mJHvHVKfm5w_jupwF5_oehcKwbT_QZ92hxg4UV8uUaiisqbIe7jQ
Connection:keep-alive
Content-Length:62
Content-Type:application/json
Cookie:.AspNet.Cookies=wcZzztFwOl41pBDgXshPnYCaaQhULRqu9O6grYPDhUx4cSY8PRY1oBRQLs3gPz4ySoxQBaaehtCLDeOFzXAN7q_UMbZps82aCajwvBQewtu_SLizCRTU9UHncWy0EFnJtLAuF5u_8sKW6sNNPTHfDtmjl3UVQkkvYDBceJC5F-sISGqH-sPFwEGmoXgcKLHWfPlejxAvRCRvGbhFhrdKpk_sycoi_B0sBe9Kc8EULXlybEeUolyyrY7L5HvOUIuujLThILt6ipYEmIk8b_2x32uCq7euh5Y_RDzI009SMceOSBs6HYsqUxz6lR2F3KvlcYBQ3rDr8qALhJBnMyJsysdDIruF9dVjK7-IjdEBPXMsGCnHK5gQs_1bIflSaPBbxVPn2VzPui-WChDCdoVXRgGRRnaEtkzaTOhBZIjlLZ1DWS1MqkM-V0khFQxBDqsxll0pZTgNZuwEOLBYoWWiAK9fATXLSmtMYA2UMKoAE0M
Host:localhost:56762
Origin:http://localhost:56762
Referer:http://localhost:56762/tasks/details;id=null
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36

使用这个数据:{Title: "Test2", Category: "Test2", Entries: []}

我看不出我的两篇文章有什么实质性的区别。它们基本上是相同的。当我在浏览器中刷新、重新登录并再次进行这些测试时,它的行为方式完全相同:第一次请求返回HTTP 200,第二次HTTP 401。

这是我的控制器操作:

[HttpPost]
[Route("Create")]
[InjectUserIdInServiceFilter]
public int CreateTask(CreateUpdateTimedTaskViewModel timedTask)
{
      var model = this.mapper.Map<CreateUpdateTimedTaskViewModel, TimedTask>(timedTask);
      return this.taskService.Create(model);
}

我的控制器定义如下:

[Authorize]
[RoutePrefix("api/TimedTask")]
public class TimedTaskController : ApiController

请注意,我使用默认的自动生成代码进行身份验证/OAuth/Owin部分;我没有改变其行为。
有人知道正在发生什么吗?
提前致谢。
T. Thomas

很可能您的令牌已过期。您能否创建一个新的Bearer令牌,然后再试一次? - Jawand Singh
在名为 Startup.Auth.cs 的类中,您可以找到 OAuthServerOptions,在其中您可以找到名为 AccessTokenExpireTimeSpan = TimeSpan.FromHours(2) 的属性,如果您想增加令牌的过期时间,可以在此更改时间。此外,您应该在应用程序中实现刷新令牌。 - Jawand Singh
我有这个设置:AccessTokenExpireTimeSpan = TimeSpan.FromDays(14)。因此,我不认为问题来自这里。我会查看刷新令牌,但我仍然不明白为什么它不能按照原样工作。 - Thomas KiTe Trentin
我不知道为什么它会表现出这样的行为,我的应用程序在使用 config.SuppressDefaultHostAuthentication(); 时运行良好。 - Jawand Singh
@JawandSingh 好的,我找到了我的问题所在。这是我客户端愚蠢的错误,我在答案中详细说明了(我必须等待一个小时才能接受它)。感谢您的时间,对于误导我感到抱歉。 - Thomas KiTe Trentin
显示剩余3条评论
1个回答

2

好的,经过大约4-5小时的调查,我找出了问题所在。

这个问题并不是来自后端(Web API / MVC或任何其他方面),而是来自客户端。

我在Angular 2的“http”周围包装了一个用于自动创建调用期间使用的标头的东西,这里的逻辑有缺陷,导致“authenticate”标头重复,使其无效。

我在第一次调用中附加了Authenticate:Bearer XXXXXX,这是有效的,但在第二次调用中破坏了此标头。

如果您仔细查看第二个调用的“Authenticate”,则会发现令牌重复两次,从而导致身份验证问题。

只有通过逐步调试C#部分才能找到此问题,从而使我注意到Request.Headers中的Authenticate标头为空。

这个问题真的很棘手,因为所有的错误消息都误导了方向。


1
这就是为什么我从不相信客户端应用程序的原因 :) - Jawand Singh

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