使用ASP.NET Web API 2,如果我想返回带有未授权状态代码的HttpResponseMessage,我会得到不同的响应头 - 有或没有WWW-Authenticate头字段 - 取决于此响应消息是否包含内容或不
根据Status Code Definitions,WWW-Authenticate标头字段是未授权响应的必填字段。
响应中缺少WWW-Authenticate头字段会导致下一个请求出错。
要查看问题,您可以创建新的Web API项目并添加一个简单的测试控制器:
public class TestController : ApiController
{
public HttpResponseMessage Get()
{
var responseMessage = new HttpResponseMessage(HttpStatusCode.Unauthorized)
{
// Content = new StringContent("You are not authorized"),
};
return responseMessage;
}
}
如果回复消息没有内容,我们将获得正常的401响应:
回复:
HTTP/1.1 401 Unauthorized
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
WWW-Authenticate: Bearer
X-SourceFiles: =?UTF-8?B?RDpcUHJvamVjdHNcVGVzdEFwaVxUZXN0QXBpXGFwaVxUZXN0?=
X-Powered-By: ASP.NET
Date: Fri, 01 May 2015 05:31:20 GMT
Content-Length: 0
如果我们向响应消息添加内容(取消注释内容行),则每个第二个响应将不是401,而是500
401的回复将包含以下标题:
HTTP/1.1 401 Unauthorized
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 22
Content-Type: text/plain; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RDpcUHJvamVjdHNcVGVzdEFwaVxUZXN0QXBpXGFwaVxUZXN0?=
X-Powered-By: ASP.NET
Date: Fri, 01 May 2015 05:34:38 GMT
You are not authorized
500的回复会说
Server cannot append header after HTTP headers have been sent.
Description: an unhandled exception occurred during the execution of the current web request.Please review the stack trace for more information about the error and where it originated in the code..... Exception Details: System.Web.HttpException: Server cannot append header after HTTP headers have been sent.
所以它看起来好像是因为以前的回复是非法的 - 它们不包含WWW-Authenticate头属性。
但即使我尝试手动添加WWW-Authenticate
,它也无济于事public class TestController : ApiController
{
public HttpResponseMessage Get()
{
var responseMessage = new HttpResponseMessage(HttpStatusCode.Unauthorized)
{
Content = new StringContent("You are not authorized"),
};
responseMessage.Headers.Add("WWW-Authenticate", "Bearer");
return responseMessage;
}
}
现在它在回复中
HTTP/1.1 401 Unauthorized
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 22
Content-Type: text/plain; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
WWW-Authenticate: Bearer
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RDpcUHJvamVjdHNcVGVzdEFwaVxUZXN0QXBpXGFwaVxUZXN0?=
X-Powered-By: ASP.NET
Date: Fri, 01 May 2015 05:43:51 GMT
You are not authorized
但我仍然有每秒请求500而不是401。
任何人都可以澄清这里发生了什么,以及如何让它正常工作?
答案 0 :(得分:0)
来自响应500的Server cannot append header after HTTP headers have been sent.
错误消息是由一个模块尝试在执行操作后将http标头写入响应流引起的 - 因为您的操作已经写入了标题和正文。
常见的罪魁祸首是 FormsAuthentication 和 Owin Cookie身份验证,并尝试将302替换为302(重定向到登录页面)。< / p>
<强>情境:强>
1.执行您的操作 - 向标头集合添加标头401 Unauthorized
,并将标头写入响应流,然后将主体(您未经授权)写入响应流。 />
2. FormsAuthenticationModule在响应头集合中看到401 Unauthorized
标头,并尝试将其更改为302 Redirect to login page
,并尝试将相应的标头写入响应流 - 由于Server cannot append header after HTTP headers have been sent.
而失败。标题已经写好了。
可能的解决方法:
1)如果 FormsAuthenticationModule 在您的请求管道中
Phil Haack blogged on all the above options
2)如果使用 OWIN Cookie身份验证 - 请考虑not setting LoginPath property