如果中间件返回 AuthenticateResult.Fail(),则响应为 null

Jiale Xue - MSFT 35,556 信誉分 Microsoft 供应商
2024-03-18T08:01:35.2733333+00:00

我有一个这样的自定义身份验证处理程序

 public class MyAuthenticationSchemeOptions: AuthenticationSchemeOptions
    {

    }
 public class MyAuthenticationHandler: AuthenticationHandler<MyAuthenticationSchemeOptions>
    {
        private ICacheProviderService _cacheService;
        private readonly IConfiguration _configuration;
        public MyAuthenticationHandler(
            IOptionsMonitor<MyAuthenticationSchemeOptions> options,
            ILoggerFactory logger,
            UrlEncoder encoder,
            ISystemClock clock,
            ICacheProviderService cacheService,
            IConfiguration configuration)
            : base(options, logger, encoder, clock)
        {
            _cacheService = cacheService;
            _configuration = configuration;
        }

        protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
        {
           if (!Request.Headers.ContainsKey("Header")){
                 Context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                //await Context.Response.WriteAsync("request doesn't contains header");
                return AuthenticateResult.Fail("request doesn't contains header");            
              }
    //further logic of success
        }

  public static class AuthenticateExtensions
    {
        public static AuthenticationBuilder AddAuth(this AuthenticationBuilder builder, Action<GlobalGroupAuthenticationSchemeOptions> configureOptions, string scheme)
        {
            return builder.AddScheme<MyAuthenticationSchemeOptions, MyAuthenticationHandler>(scheme,"abcd", configureOptions);
        }
    }

控制器装饰有

[Authorize(AuthenticationSchemes = "MyAuthenticationScheme")]

Startup.cs

ConfigureServices(IServiceCollection services){
services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = "MyAuthenticationScheme";
                options.DefaultChallengeScheme = "MyAuthenticationScheme";
            }).AddAuth(x => { }, "MyAuthenticationScheme");
}

Configure(IApplicationBuilder app, IWebHostEnvironment env,ILogger<Startup> logger){
        //Other logic is removed as not required here
        app.UseRouting();            
        app.UseAuthorization();
}

此代码仅返回状态代码为“未授权”。如果请求没有标头,则不会返回任何错误消息作为响应。当我取消注释此行的那一刻,我立即收到一个未经处理的异常。任何建议,请在自定义 AuthenticationHandler 服务的情况下返回消息作为响应await Context.Response.WriteAsync("request doesn't contains header");

info: Middleware.MyAuthenticationHandler[7]
   MyAuthenticationScheme was not authenticated. Failure message: Authentication Header Not Found
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]
      An unhandled exception has occurred while executing the request.
      System.InvalidOperationException: StatusCode cannot be set because the response has already started.
         at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ThrowResponseAlreadyStartedException(String value)
         at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.set_StatusCode(Int32 value)
         at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.Microsoft.AspNetCore.Http.Features.IHttpResponseFeature.set_StatusCode(Int32 value)
         at Microsoft.AspNetCore.Http.DefaultHttpResponse.set_StatusCode(Int32 value)
         at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.HandleChallengeAsync(AuthenticationProperties properties)
         at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.ChallengeAsync(AuthenticationProperties properties)
         at Microsoft.AspNetCore.Authentication.AuthenticationService.ChallengeAsync(HttpContext context, String scheme, AuthenticationProperties properties)
         at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
         at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
         at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
         at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
         at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
warn: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[2]
      The response has already started, the error handler will not be executed.
fail: Microsoft.AspNetCore.Server.Kestrel[13]
      Connection id "0HM53499HNTTT", Request id "0HM53499HNTTT:00000002": An unhandled exception was thrown by the application.
      System.InvalidOperationException: StatusCode cannot be set because the response has already started.
         at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ThrowResponseAlreadyStartedException(String value)
         at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.set_StatusCode(Int32 value)
         at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.Microsoft.AspNetCore.Http.Features.IHttpResponseFeature.set_StatusCode(Int32 value)
         at Microsoft.AspNetCore.Http.DefaultHttpResponse.set_StatusCode(Int32 value)
         at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.HandleChallengeAsync(AuthenticationProperties properties)
         at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.ChallengeAsync(AuthenticationProperties properties)
         at Microsoft.AspNetCore.Authentication.AuthenticationService.ChallengeAsync(HttpContext context, String scheme, AuthenticationProperties properties)
         at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
         at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
         at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
         at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
         at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
         at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.HandleException(HttpContext context, ExceptionDispatchInfo edi)
         at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
         at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

Note:此问题总结整理于:Response is null if middleware return AuthenticateResult.Fail()

ASP.NET Core
ASP.NET Core
.NET Framework 中一套用于生成 Web 应用程序和 XML Web 服务的技术。
24 个问题
C#
C#
一种面向对象的类型安全的编程语言,它起源于 C 语言系列,包括对面向组件的编程的支持。
129 个问题
.NET 运行时
.NET 运行时
.NET: 基于 .NET 软件框架的 Microsoft 技术。运行时: 运行未编译为机器语言的应用所需的环境。
41 个问题
0 个注释 无注释
{count} 票

接受的答案
  1. Hui Liu-MSFT 41,146 信誉分 Microsoft 供应商
    2024-03-18T08:39:37.65+00:00

    System.InvalidOperationException:无法设置状态代码,响应已启动。>

    根据上面的描述,我有一个建议,您可以在设置 StatusCode 之前检查“响应是否已经开始”: 代码如下所示:

     protected override async Task<AuthenticateResult> HandleAuthenticateAsync()  
            {  
                if (!Request.Headers.ContainsKey("Header"))  
                {  
    
                    if (!Context.Response.HasStarted)  
                    {  
                        string result;  
                        Context.Response.StatusCode = StatusCodes.Status401Unauthorized;  
                        result = JsonConvert.SerializeObject(new { error = "Request doesn't contains header" });  
                        Context.Response.ContentType = "application/json";  
                        await Context.Response.WriteAsync(result);  
                    }  
                    else  
                    {  
                        await Context.Response.WriteAsync(string.Empty);  
                    }  
      
                    return AuthenticateResult.Fail("request doesn't contains header");  
                }  
                //further logic of success  
            }  
    
          
    

    如果答案不能解决您的问题,请提供更多错误的详细信息,以帮助我们追踪正在发生的事情.

    希望这对你有所帮助。 如果回复有帮助,请单击“接受答案”并投赞成票。

    注意:如果您想接收此线程的相关电子邮件通知,请按照我们文档中的步骤启用电子邮件通知。

    1 个人认为此答案很有帮助。
    0 个注释 无注释

0 个其他答案

排序依据: 非常有帮助