Dav*_*New 10 asp.net-core-mvc asp.net-core asp.net-core-1.0
当401和403出现时,我想用JSON响应模型做出响应.例如:
HTTP 401
{
"message": "Authentication failed. The request must include a valid and non-expired bearer token in the Authorization header."
}
Run Code Online (Sandbox Code Playgroud)
我正在使用中间件(如本答案中所建议的)拦截404并且它工作得很好,但401或403并非如此.这是中间件:
app.Use(async (context, next) =>
{
await next();
if (context.Response.StatusCode == 401)
{
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(JsonConvert.SerializeObject(UnauthorizedModel.Create(), SerializerSettings), Encoding.UTF8);
}
});
Run Code Online (Sandbox Code Playgroud)
当置于下方app.UseJwtBearerAuthentication(..)时Startup.Configure(..),它似乎被完全忽略并返回正常的401.
当置于ABOVE app.UseJwtBearerAuthentication(..)中时Startup.Configure(..),将抛出以下异常:
连接标识"0HKT7SUBPLHEM":应用程序抛出了未处理的异常.System.InvalidOperationException:标头是只读的,响应已经开始.在MicrosoftPro.AspNetCore.Server.Kestrel.Internal.Http.FrameHeaders.Microsoft.AspNetCore.Http.IHeaderDictionary.set_Item(String key,StringValues value),位于MyProject的Microsoft.AspNetCore.Http.Internal.DefaultHttpResponse.set_ContentType(String value). Startup.cs中的Api.Startup.<b__12_0> d.MoveNext()
Set处于正确的轨道上,但实际上不需要创建自己的中间件,因为您可以利用事件模型来覆盖默认的挑战逻辑.
这是一个示例,它将返回包含OAuth2错误代码/描述的401响应作为纯文本(您当然可以返回JSON或任何您想要的内容):
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
Authority = "http://localhost:54540/",
Audience = "http://localhost:54540/",
RequireHttpsMetadata = false,
Events = new JwtBearerEvents
{
OnChallenge = async context =>
{
// Override the response status code.
context.Response.StatusCode = 401;
// Emit the WWW-Authenticate header.
context.Response.Headers.Append(
HeaderNames.WWWAuthenticate,
context.Options.Challenge);
if (!string.IsNullOrEmpty(context.Error))
{
await context.Response.WriteAsync(context.Error);
}
if (!string.IsNullOrEmpty(context.ErrorDescription))
{
await context.Response.WriteAsync(context.ErrorDescription);
}
context.HandleResponse();
}
}
});
Run Code Online (Sandbox Code Playgroud)
或者,您也可以使用状态代码页中间件,但对于403响应,您将不会有任何关于导致它的授权策略的提示:
app.UseStatusCodePages(async context =>
{
if (context.HttpContext.Request.Path.StartsWithSegments("/api") &&
(context.HttpContext.Response.StatusCode == 401 ||
context.HttpContext.Response.StatusCode == 403))
{
await context.HttpContext.Response.WriteAsync("Unauthorized request");
}
});
Run Code Online (Sandbox Code Playgroud)
首先,中间件的顺序很重要。
每个中间件选择是否将请求传递给管道中的下一个组件,并且可以在调用管道中的下一个组件之前和之后执行某些操作
如果发生错误,UseJwtBearerAuthentication 将停止进一步的管道执行。
但是您的方法不适用于 JwtBearerAuthentication 中间件,因为当您出现未经授权的错误时,中间件会发送 WWWAuthenticate 标头,这就是为什么您会收到“响应已开始”异常的原因 - 查看HandleUnauthorizedAsync方法。您可以重写此方法并实现您自己的自定义逻辑。
HttpContext.Response.OnStarting另一种可能的解决方案(不确定是否有效)是在中间件中使用回调,因为它是在标头发送之前调用的。你可以看看这个答案
| 归档时间: |
|
| 查看次数: |
5906 次 |
| 最近记录: |