使用 UseJwtBearerAuthentication 中间件自定义 401 和 403 响应模型 [英] Custom 401 and 403 response model with UseJwtBearerAuthentication middleware

查看:13
本文介绍了使用 UseJwtBearerAuthentication 中间件自定义 401 和 403 响应模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在 401 和 403 发生时使用 JSON 响应模型进行响应.例如:

I want to respond with a JSON response model when a 401 and 403 occur. For example:

HTTP 401
{
  "message": "Authentication failed. The request must include a valid and non-expired bearer token in the Authorization header."
}

我正在使用中间件(如 this answer 中的建议)来拦截404s 并且效果很好,但 401 或 403s 的情况并非如此.这是中间件:

I am using middleware (as suggested in this answer) to intercept 404s and it works great, but it is not the case with 401 or 403s. Here is the middleware:

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);
    }
});

当放在 Startup.Configure(..) 中的 app.UseJwtBearerAuthentication(..) 之下时,它似乎被完全忽略并返回正常的 401.

When placed BELOW app.UseJwtBearerAuthentication(..) in Startup.Configure(..), it seems to be completely ignored and a normal 401 is returned.

当在 Startup.Configure(..) 中放置在 app.UseJwtBearerAuthentication(..) 之上时,会抛出以下异常:

When placed ABOVE app.UseJwtBearerAuthentication(..) in Startup.Configure(..), then the following exception is thrown:

Connection id "0HKT7SUBPLHEM": 一个未处理的异常被抛出应用程序.System.InvalidOperationException:标头是只读,响应已经开始.在Microsoft.AspNetCore.Server.Kestrel.Internal.Http.FrameHeaders.Microsoft.AspNetCore.Http.IHeaderDictionary.set_Item(字符串键,StringValues 值)在Microsoft.AspNetCore.Http.Internal.DefaultHttpResponse.set_ContentType(字符串值)在 MyProject.Api.Startup.d.MoveNext() 中启动.cs

Connection id "0HKT7SUBPLHEM": An unhandled exception was thrown by the application. System.InvalidOperationException: Headers are read-only, response has already started. at Microsoft.AspNetCore.Server.Kestrel.Internal.Http.FrameHeaders.Microsoft.AspNetCore.Http.IHeaderDictionary.set_Item(String key, StringValues value) at Microsoft.AspNetCore.Http.Internal.DefaultHttpResponse.set_ContentType(String value) at MyProject.Api.Startup.<b__12_0>d.MoveNext() in Startup.cs

推荐答案

Set 在正确的轨道上,但实际上不需要创建自己的中间件,因为您可以利用事件模型来覆盖默认的挑战逻辑.

Set was on the right track, but there's actually no need to create your own middleware, as you can leverage the events model to override the default challenge logic.

这是一个示例,它将以纯文本形式返回包含 OAuth2 错误代码/描述的 401 响应(您当然可以返回 JSON 或任何您想要的):

Here's an example that will return a 401 response containing the OAuth2 error code/description as plain text (you can of course return JSON or whatever you want):

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();
        }
    }
});

或者,您也可以使用状态代码页中间件,但对于 403 响应,您不会有任何关于导致它的授权策略的提示:

Alternatively, you can also use the status code pages middleware, but for 403 responses, you won't have any hint about the authorization policy that caused it:

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");
    }
});

这篇关于使用 UseJwtBearerAuthentication 中间件自定义 401 和 403 响应模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆