.NET Core 3.1 OAUTH 2 令牌内省与自定义 JSON 响应 - "Status Code cannot be set because the response has already started"

.NET Core 3.1 OAUTH 2 Token Introspection with Custom JSON Response - "Status Code cannot be set because the response has already started"

我已经尝试了所有解决方案,但没有任何效果。

我正在使用包 IdentityModel.AspNetCore.OAuth2Introspection v6.0.0。我的业务用例是,当身份验证失败时,我必须 return 401 未授权状态代码 加上响应中的自定义 JSON 对象 。此代码适用于 return JSON 对象,但它每次都会在后端抛出相同的错误,一旦开始发生,延迟就会在我的应用程序中激增。

这是我目前的情况:

services.AddAuthentication("Bearer")
    .AddOAuth2Introspection(options =>
    {
        options.Authority = _idpAuthority;
        options.ClientId = _apiResourceName;
        options.ClientSecret = _apiResourceSecret;
    
        options.Events.OnAuthenticationFailed = async context =>
        {
            context.NoResult();
            if (!context.Response.HasStarted)
            {
                context.Response.StatusCode = 401;
                context.Response.ContentType = "application/json";
                await context.Response.Body.WriteAsync(JsonSerializer.SerializeToUtf8Bytes(new ErrorListResponseModel().AddError("401", "UNAUTHORIZED")));     
            }
                               
        };
    });

这会产生错误:

System.InvalidOperationException: StatusCode cannot be set because the response has already started.

这个错误的记录调用点是Microsoft.AspNetCore.Server.IIS.Core.IISHttpContext.ReportApplicationError

我是添加还是删除context.NoResult() -- 没有区别。

我试过使用同步委托函数和 returning Task.CompletedTask 代替——没有区别。

如果我没有明确设置 context.Response.StatusCode,我会在响应中得到一个 200 状态代码,并且仍然会抛出错误!

图书馆的评论表明

Invoked if exceptions are thrown during request processing. The exceptions will be re-thrown after this event unless suppressed.

。 . .但我没有看到任何关于如何抑制这些异常的建议。

请帮忙

我通过将此代码从 OnAuthenticationFailed 事件中取出并将其移至 Startup.cs 的 Configure(IApplicationBuilder app) 部分来解决此问题:

app.UseStatusCodePages((StatusCodeContext statusCodeContext) =>
{
    var context = statusCodeContext.HttpContext;
    if (context.Response.StatusCode == 401)
    {
        context.Response.ContentType = _applicationJsonMediaHeader;
        return context.Response.Body.WriteAsync(_serializedUnauthorizedError).AsTask();
    }

    return Task.CompletedTask;
});