ASP.NET Web API : return 401/未授权响应的正确方法
ASP.NET Web API : Correct way to return a 401/unauthorised response
我有一个 MVC webapi 站点,它使用 OAuth/token 身份验证来对请求进行身份验证。所有相关的控制器都具有正确的属性,并且身份验证工作正常。
问题是并非所有请求都可以在属性范围内授权 - 一些授权检查必须在控制器方法调用的代码中执行 - [=21= 的正确方法是什么] 在这种情况下是 401 未经授权的响应?
我已经尝试 throw new HttpException(401, "Unauthorized access");
,但是当我这样做时,响应状态代码是 500,我也得到了堆栈跟踪。即使在我们的日志记录 DelegatingHandler 中,我们也可以看到响应是 500,而不是 401。
您收到 500 响应代码是因为您抛出了异常(HttpException
),这表明某种服务器错误,这是错误的方法。
只需设置响应状态码即可。例如
Response.StatusCode = (int)HttpStatusCode.Unauthorized;
你应该抛出一个 HttpResponseException
from your API method, not HttpException
:
throw new HttpResponseException(HttpStatusCode.Unauthorized);
或者,如果您想提供自定义消息:
var msg = new HttpResponseMessage(HttpStatusCode.Unauthorized) { ReasonPhrase = "Oops!!!" };
throw new HttpResponseException(msg);
只需 return 以下内容:
return Unauthorized();
作为其他答案的替代方案,如果您想在 ASP.NET 控制器中 return 一个 IActionResult
,您也可以使用此代码。
ASP.NET
return Content(HttpStatusCode.Unauthorized, "My error message");
更新:ASP.NET核心
以上代码在 ASP.NET 核心中不起作用,您可以使用其中之一:
return StatusCode((int)System.Net.HttpStatusCode.Unauthorized, "My error message");
return StatusCode(Microsoft.AspNetCore.Http.StatusCodes.Status401Unauthorized, "My error message");
return StatusCode(401, "My error message");
显然,短语的原因是可选的 ()
您可以在 asp.net 核心 2.0 中使用以下代码:
public IActionResult index()
{
return new ContentResult() { Content = "My error message", StatusCode = (int)HttpStatusCode.Unauthorized };
}
要添加到 ASP.NET Core >= 1.0 中的现有答案,您可以
return Unauthorized();
return Unauthorized(object value);
要将信息传递给客户端,您可以这样调用:
return Unauthorized(new { Ok = false, Code = Constants.INVALID_CREDENTIALS, ...});
在客户端上,除了 401 响应之外,您还将获得传递的数据。例如,在大多数客户端上,您可以 await response.json()
获取它。
在.Net Core中可以使用
return new ForbidResult();
而不是
return Unauthorized();
这有利于重定向到默认的未授权页面 (Account/AccessDenied) 而不是直接给出 401
更改默认位置修改您的 startup.cs
services.AddAuthentication(options =>...)
.AddOpenIdConnect(options =>...)
.AddCookie(options =>
{
options.AccessDeniedPath = "/path/unauthorized";
})
您还关注了这个代码:
var response = new HttpResponseMessage(HttpStatusCode.NotFound)
{
Content = new StringContent("Users doesn't exist", System.Text.Encoding.UTF8, "text/plain"),
StatusCode = HttpStatusCode.NotFound
}
throw new HttpResponseException(response);
我有一个 MVC webapi 站点,它使用 OAuth/token 身份验证来对请求进行身份验证。所有相关的控制器都具有正确的属性,并且身份验证工作正常。
问题是并非所有请求都可以在属性范围内授权 - 一些授权检查必须在控制器方法调用的代码中执行 - [=21= 的正确方法是什么] 在这种情况下是 401 未经授权的响应?
我已经尝试 throw new HttpException(401, "Unauthorized access");
,但是当我这样做时,响应状态代码是 500,我也得到了堆栈跟踪。即使在我们的日志记录 DelegatingHandler 中,我们也可以看到响应是 500,而不是 401。
您收到 500 响应代码是因为您抛出了异常(HttpException
),这表明某种服务器错误,这是错误的方法。
只需设置响应状态码即可。例如
Response.StatusCode = (int)HttpStatusCode.Unauthorized;
你应该抛出一个 HttpResponseException
from your API method, not HttpException
:
throw new HttpResponseException(HttpStatusCode.Unauthorized);
或者,如果您想提供自定义消息:
var msg = new HttpResponseMessage(HttpStatusCode.Unauthorized) { ReasonPhrase = "Oops!!!" };
throw new HttpResponseException(msg);
只需 return 以下内容:
return Unauthorized();
作为其他答案的替代方案,如果您想在 ASP.NET 控制器中 return 一个 IActionResult
,您也可以使用此代码。
ASP.NET
return Content(HttpStatusCode.Unauthorized, "My error message");
更新:ASP.NET核心
以上代码在 ASP.NET 核心中不起作用,您可以使用其中之一:
return StatusCode((int)System.Net.HttpStatusCode.Unauthorized, "My error message");
return StatusCode(Microsoft.AspNetCore.Http.StatusCodes.Status401Unauthorized, "My error message");
return StatusCode(401, "My error message");
显然,短语的原因是可选的 ()
您可以在 asp.net 核心 2.0 中使用以下代码:
public IActionResult index()
{
return new ContentResult() { Content = "My error message", StatusCode = (int)HttpStatusCode.Unauthorized };
}
要添加到 ASP.NET Core >= 1.0 中的现有答案,您可以
return Unauthorized();
return Unauthorized(object value);
要将信息传递给客户端,您可以这样调用:
return Unauthorized(new { Ok = false, Code = Constants.INVALID_CREDENTIALS, ...});
在客户端上,除了 401 响应之外,您还将获得传递的数据。例如,在大多数客户端上,您可以 await response.json()
获取它。
在.Net Core中可以使用
return new ForbidResult();
而不是
return Unauthorized();
这有利于重定向到默认的未授权页面 (Account/AccessDenied) 而不是直接给出 401
更改默认位置修改您的 startup.cs
services.AddAuthentication(options =>...)
.AddOpenIdConnect(options =>...)
.AddCookie(options =>
{
options.AccessDeniedPath = "/path/unauthorized";
})
您还关注了这个代码:
var response = new HttpResponseMessage(HttpStatusCode.NotFound)
{
Content = new StringContent("Users doesn't exist", System.Text.Encoding.UTF8, "text/plain"),
StatusCode = HttpStatusCode.NotFound
}
throw new HttpResponseException(response);