c# - 带有 Unauthorize 状态代码和 Content//response 的 HttpResponseMessage 没有必需的 WWW-Authenticate header 字段

标签 c# asp.net .net asp.net-mvc asp.net-web-api

使用 ASP.NET Web API 2,如果我想返回带有 Unauthorized 状态代码的 HttpResponseMessage,我将获得不同的响应 header - 有或没有 WWW-Authenticate header 字段 - 取决于此响应消息是否有内容。

根据 Status Code Definitions,WWW-Authenticate header 字段是未授权响应的必填字段.

响应中缺少 WWW-Authenticate 头字段会导致下一个请求出错。

要查看问题,您可以创建一个新的 Web API 项目并添加一个简单的测试 Controller :

public class TestController : ApiController
{
    public HttpResponseMessage Get()
    {
        var responseMessage = new HttpResponseMessage(HttpStatusCode.Unauthorized)
        {
            // Content = new StringContent("You are not authorized"),
        };

        return responseMessage;
    }
}

如果响应消息没有内容,我们的调用将得到正常的 401 响应: enter image description here

有回复:

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

enter image description here

带有 401 的响应将具有以下 header :

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 header 属性。

但即使我尝试手动添加 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。

谁能阐明这里发生了什么以及如何使其正常工作?

最佳答案

在发送 HTTP header 后,服务器无法附加 header 。 来自响应 500 的错误消息是由一个模块在您的操作执行后尝试将 HTTP header 写入响应流引起的 - 因为您的操作已经写入标题和正文。

通常的罪魁祸首是 FormsAuthenticationOwin cookie 身份验证 启动并尝试用 302 替换 401(重定向到登录页面)。

场景:
1. 您的操作已执行 - 添加 header 401 Unauthorized 到 header 集合并将 header 写入响应流,然后将正文(您未授权)写入响应流。
2. FormsAuthenticationModule 在响应 header 集合中看到 401 Unauthorized header ,并尝试将其更改为 302 Redirect to login page,并尝试将相应的 header 写入响应流 -失败并显示 Server cannot append header after HTTP headers has been sent.,因为 header 已经在前面写入。

可能的修复:

1) 如果 FormsAuthenticationModule 在您的请求管道中

  • 如果您不使用它,请考虑将其禁用
  • 在 .net 4.5 中,您可以通过设置 HttpResponse.SuppressFormsAuthenticationRedirect 来抑制表单例份验证重定向属性为false
  • 如果不是在 .net 4.5 上,请考虑使用 HttpModule 来抑制这种重定向

Phil Haack blogged on all the above options .

2) 如果使用 OWIN cookie 身份验证 - 考虑 not setting LoginPath property

关于c# - 带有 Unauthorize 状态代码和 Content//response 的 HttpResponseMessage 没有必需的 WWW-Authenticate header 字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29982193/

相关文章:

c# - 获取用于 Visual Studio 签名的可信证书

c# - 使用变量序列化表达式

c# - 当 asp.net 5 web api 中的代码错误时返回 500 内部服务器错误

.net - ReactiveUI ObservableAsPropertyHelper/Reactive Extensions 内存泄漏?

c# - 获取WebBrowser控件中事件网站的标题

c# - 无法找到程序集 Entity Framework v 4.4.0.0

c# - 在 Visual Studio 2012 中找不到 System.Web.Hosting

c# - .NET 异常有多慢?

c# - Linq 查询中的 If 语句

mysql - 用 ASP.NET 编写的 SQL 查询(后面的代码是 VB)未提供预期结果