我有一个 MVC webapi 站点,它使用 OAuth/token 身份验证来验证请求。所有相关控制器都具有正确的属性,并且身份验证工作正常。
问题是并非所有请求都可以在属性范围内获得授权——必须在控制器方法调用的代码中执行一些授权检查——在这种情况下返回 401 未授权响应的正确方法是什么?
我已经尝试过 throw new HttpException(401, "Unauthorized access");
,但是当我这样做时,响应状态代码是 500,而且我还得到了堆栈跟踪。即使在我们的日志记录 DelegatingHandler 中,我们也可以看到响应是 500,而不是 401。
HttpResponseException
的适当时间与返回 Unauthorized()
的时间。对“预期”错误使用异常有点反模式,因此如果在某些情况下您希望调用会犯此错误,则返回 Unauthorized()
可能是正确的调用。为真正出乎意料的情况保存 HttpResponseException
。
您应该从 API 方法中抛出 HttpResponseException
,而不是 HttpException
:
throw new HttpResponseException(HttpStatusCode.Unauthorized);
或者,如果您想提供自定义消息:
var msg = new HttpResponseMessage(HttpStatusCode.Unauthorized) { ReasonPhrase = "Oops!!!" };
throw new HttpResponseException(msg);
只需返回以下内容:
return Unauthorized();
return Content<string>(HttpStatusCode.Unauthorized, "Message");
来执行此操作。
作为其他答案的替代方案,如果您想在 ASP.NET 控制器中返回 IActionResult
,也可以使用此代码。
ASP.NET
return Content(HttpStatusCode.Unauthorized, "My error message");
更新:ASP.NET 核心
上面的代码在 ASP.NET Core 中不起作用,您可以使用以下代码之一:
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");
显然原因短语是可选的 (Can an HTTP response omit the Reason-Phrase?)
ControllerBase
类(由 ASP.NET Core WebAPI 使用)不再具有接受 HTTP 状态代码的 Content
重载。
HttpStatusCode.Unauthorized
),而不是 200。Content(...)
只是返回具有给定 HTTP 状态代码的任何给定内容的简写。如果您想发送 200,您可以使用 Ok(...)
你得到一个 500 响应代码,因为你抛出了一个异常(HttpException
),它表明某种服务器错误,这是错误的方法。
只需设置响应状态码.eg
Response.StatusCode = (int)HttpStatusCode.Unauthorized;
Response
属性。
要添加到 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();
它的优点是重定向到默认的未经授权的页面(帐户/访问拒绝),而不是直接给出 401
更改默认位置修改您的 startup.cs
services.AddAuthentication(options =>...)
.AddOpenIdConnect(options =>...)
.AddCookie(options =>
{
options.AccessDeniedPath = "/path/unauthorized";
})
您可以在 asp.net core 2.0 中使用以下代码:
public IActionResult index()
{
return new ContentResult() { Content = "My error message", StatusCode = (int)HttpStatusCode.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);
不定期副业成功案例分享
HttpResponseException
是 NuGet 包Microsoft.AspNetCore.Mvc.WebApiCompatShim
的一部分,它提供 ASP.NET Core MVC 与 ASP.NET Web API 2 的兼容性。也就是说,它允许您在 Core 项目中采用非核心方式。所以对于核心项目,这不是“正确的方式”。