Пользовательское перенаправление из AuthorizationHandler (ASP.NET Core)

Я использую промежуточное ПО для аутентификации, которое отправляет API-запросы к сторонней службе. Затем это ПО промежуточного слоя устанавливает утверждения, которые впоследствии обрабатываются обработчиком авторизации в сочетании с IAuthorizationRequirement и настраиваемой политикой.

Часть промежуточного программного обеспечения работает, и я могу создавать претензии:

context.User.AddIdentity(identity); // contains claims

Где я застрял, так это перенаправление на определенный URL-адрес (есть настраиваемые правила для того, куда нам нужно перенаправить) из обработчика или атрибута. Из обработчика я пробовал:

var mvcContext = context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext;
mvcContext.Result = new RedirectToActionResult("login", "home", null);

но это игнорируется; возвращается только 401. AuthorizeAttribute больше не имеет OnAuthorization, поэтому я тоже не могу его использовать...

Мысли? Спасибо.


person pbz    schedule 17.01.2017    source источник


Ответы (2)


Ваш подход с AuthorizationFilterContext в обработчике был почти правильным. Как описано в этом ответе, вам также нужно сказать context.Succeed(requirement);, чтобы он работал.

Итак, полное решение будет примерно таким:

  1. Создайте пользовательское требование:

    public class SomeCustomRequirement : IAuthorizationRequirement
    {}
    
  2. Создайте собственный обработчик:

    public class SomeCustomRequirementHandler : AuthorizationHandler<SomeCustomRequirement>
    {
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, UserInformationCompletedRequirement requirement)
        {
            if (!fulfillsRequirement())
                if (context.Resource is AuthorizationFilterContext redirectContext)
                    redirectContext.Result = new RedirectResult("/Account/Unauthorized");
                // even though this is weird it is necessary
                context.Succeed(requirement);
            }
        }
    }
    
  3. Зарегистрируйте обработчик:

    services.AddAuthorization(options =>
    {
        options.AddPolicy(IdentityConstants.UserInformationCompletePolicy, policy =>
        {
            policy.RequireAuthenticatedUser();
            policy.Requirements.Add(new SomeCustomRequirement());
        });
    });
    
    services.AddSingelton<IAuthorizationHandler, SomeCustomRequirementHandler>();    
    // OR transient if the handler uses the Entity Framework
    services.AddTransient<IAuthorizationHandler, SomeCustomRequirementHandler>();
    

Несмотря на то, что мой ответ запоздал, я надеюсь, что это может помочь будущим посетителям.

person Morosko    schedule 25.11.2018

Если единственное, что вы хотите попробовать в промежуточном программном обеспечении API, — это реализовать поведение входа в систему, как кажется, объясняется в вашем коде, следующие возможные случаи, на мой взгляд, наводят на размышления:

  1. Если /login/home перенаправляет на веб-страницу:

    • You should use HttpContext.Response.Redirect to redirect to the LogIn webpage. As the documentation says, This would send a 301 code that any web browser can interpret. The HttpContext is available in the Invoke method.
  2. Если /login/home перенаправляет на контроллер, который выполняет логику, подтверждающую личность пользователя:

Взгляните также на сообщение Нейта и этот вопрос.

person Christopher J.    schedule 16.02.2017