【问题标题】:C# .net core 2.1 Exception handling of AuthorizationC# .net core 2.1 Authorization的异常处理
【发布时间】:2018-11-06 11:26:49
【问题描述】:

所以在 .net framework 4.7.1 的 Web API 2 中,如果你有一个处理异常的过滤器,定义如下:

public sealed class RequestExceptionFilter : ExceptionFilterAttribute..

在 WebApiConfig 中:

config.Filters.Add(new MyAuthorizationFilter());
config.Filters.Add(new RequestExceptionFilter());

如果在MyAuthorizationFilter 中发生任何异常,它会在RequestExceptionFilter 中被捕获。

在 .net core 2.1 中,我有以下内容:

services.AddMvc(options =>
{
    options.Filters.Add(new MyExceptionFilter());

}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddAuthentication("Basic").AddScheme<AuthenticationSchemeOptions, UserAuthenticator>("Basic", null)

// configure DI for application services
services.AddScoped<IUserAuthenticator, UserAuthenticatorHandler>();

我有以下处理程序:

public sealed class UserAuthenticator: AuthenticationHandler<AuthenticationSchemeOptions>

现在,如果我在protected override async Task&lt;AuthenticateResult&gt; HandleAuthenticateAsync()UserAuthenticator 的方法)中抛出异常,服务器会返回 Internal Server Error 并跳过异常处理。

我可以让它传播到异常过滤器吗?

【问题讨论】:

    标签: c# asp.net-core asp.net-core-2.0


    【解决方案1】:

    根据https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-2.1,似乎授权过滤器在异常过滤器之前运行。

    如果您将异常处理从过滤器中移出以添加为中间件

    public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) 方法中: app.UseMiddleware&lt;MyErrorHandling&gt;();

    public class MyErrorHandling
    {
        private readonly RequestDelegate _next;
    
        public MyErrorHandling(RequestDelegate next)
        {
            _next = next;
        }
    
        public async Task Invoke(HttpContext context)
        {
            try
            {
                await _next.Invoke(context);
            }
            catch (Exception e)
            {
                // Do stuff?
                await context.Response.WriteAsync("it broke. :(");
            }
        }
    }
    

    我认为这种方法会比使用过滤器更灵活一些。

    【讨论】:

      【解决方案2】:

      像这样创建一个扩展方法

      public static void UseGlobalExceptionHandler(this IApplicationBuilder appBuilder, ILogger logger)
              {
                  appBuilder.UseExceptionHandler(app =>
                  {
                      app.Run(async context =>
                      {
                          context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                          context.Response.ContentType = "application/json";
      
                          var ex = context.Features.Get<IExceptionHandlerFeature>()?.Error;
                          //AuthException is your custom exception class
                          if (ex != null && ex.GetType() == typeof(AuthException))
                          {
                              context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                              context.Response.ContentType = "application/json";
                              await context.Response.WriteAsync("Unautherized");
                          }
                      });
                  });
              }
      

      在configure方法下的startup.cs文件中使用

      public void Configure(IApplicationBuilder app, IHostingEnvironment env)
      {
         //Use it like this
         app.UseGlobalExceptionHandler();
      }
      

      【讨论】:

      • 我不想依赖 AuthException。我希望它是任何例外。但我会试一试
      • 显然你可以使用任何异常,你只需要使用 UseExceptionHandler() 扩展并发送你自己的响应而不是默认的 InternalServerError 响应
      【解决方案3】:

      .net core 中很多过滤器的功能(尤其是全局过滤器)已经被Middleware取代了。

      MVC 中过滤器的执行顺序由框架修复 - MSDN Link

      在.net core 中,中间件按照配置的顺序执行

      Startup.cs 中的Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 方法

      这意味着如果您的中间件出现异常,您的授权过滤器将不起作用。解决此问题的最佳方法是将异常处理移至中间件中,并确保在该方法中首先或几乎首先添加它。

      另一个选项可能是启用开发人员异常页面进行测试。

      我已经在这个 SO 答案中更详细地回答了 如何How to catch an exception and respond with a status code in .NET Core

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-18
        • 2019-03-08
        • 2018-11-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多