C # .net core 2.1 Исключительная обработка авторизации - PullRequest
0 голосов
/ 06 ноября 2018

Так что в Web API 2 в .net framework 4.7.1, если у вас есть фильтр, который обрабатывает исключение, определяется следующим образом:

public sealed class RequestExceptionFilter : ExceptionFilterAttribute..

И в WebApiConfig:

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

если бы какое-либо исключение произошло в MyAuthorizationFilter, оно было бы поймано в RequestExceptionFilter.

В ядре .net 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<AuthenticateResult> HandleAuthenticateAsync(), который является методом UserAuthenticator, сервер вернет Внутреннюю ошибку сервера и пропустит обработку исключения.

Можно ли распространить его на фильтр исключений?

Ответы [ 3 ]

0 голосов
/ 06 ноября 2018

Создайте метод расширения, подобный этому

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

Используйте его в файле startup.cs в разделе «Метод настройки»

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
   //Use it like this
   app.UseGlobalExceptionHandler();
}
0 голосов
/ 06 ноября 2018

В ядре .net множество функций фильтров (особенно глобальных фильтров) были заменены на Промежуточное ПО .

Порядок выполнения фильтров в MVC был исправлен платформой - MSDN Link

Промежуточное программное обеспечение ядра .net выполняется в порядке, настроенном в

Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) метод в Startup.cs

Это означает, что ваш фильтр авторизации не будет работать, если в вашем промежуточном программном обеспечении есть исключение. Лучший способ обойти это - переместить обработку исключений в Middleware и убедиться, что она добавляется первой или почти первой в этом методе.

Еще одним вариантом может быть включение страницы исключений разработчика для тестирования.

Я ответил на как более подробно в этом SO ответе: Как перехватить исключение и ответить кодом состояния в .NET Core

0 голосов
/ 06 ноября 2018

Согласно https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-2.1 кажется, что фильтры авторизации запускаются раньше фильтров исключений.

Возможно, если вы переместили обработку исключений из фильтра, который будет добавлен в качестве промежуточного программного обеспечения

Если метод public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory): app.UseMiddleware<MyErrorHandling>();

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

Я думаю, что этот метод будет более гибким, чем использование фильтров.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...