Решить использовать авторизацию или нет на основе запроса в Asp.net Core - PullRequest
0 голосов
/ 23 октября 2019

Я занимаюсь разработкой основного приложения MVC 2.2 для ASP.net и в настоящее время использую классические атрибуты [Authorize] и [AllowAnonymous] в действиях моего контроллера, чтобы решить, можно ли получить доступ к определенному действию анонимно или требуется авторизация. .

Однако у меня есть требование, при котором для определенных действий требуется авторизация, только если в запросе http отсутствует определенный заголовок. Обычно я реализую это, просто имея что-то вроде этого:

[HttpGet]
[AllowAnonymous]
public IActionResult SomeAction()
{
    if (!Request.Headers.ContainsKey("something"))
    {
        return RedirectToAction("SomeActionWithAuth");
    }
    ...
}

[HttpGet]
[Authorize]
public IActionResult SomeActionWithAuth()
{
    ...
}

, однако в данном конкретном случае у меня есть строгое требование избегать перенаправлений, поэтому я не могу использовать этот подход.

мой вопрос:

  • Есть ли способ перехватить запрос до того, как он достигнет контроллера, и принять решение во время выполнения, для каждого запроса, должен ли запрос потребовать аутентификацию или нет?
  • Если это невозможно, возможно, есть способ решить во время выполнения, на какой контроллер / действие направить запрос? (таким образом, у меня могла бы быть установка, подобная вышеупомянутой, с двумя действиями с различными требованиями аутентификации, но без фактического перенаправления HTTP на стороне клиента, что я не могу сделать)

1 Ответ

1 голос
/ 23 октября 2019

Создайте собственную политику авторизации для этого.

public class HeaderRequirement : IAuthorizationRequirement
{
    public HeaderRequirement(string header)
    {
        Header = header;
    }

    public string Header { get; }
}

public class HeaderRequirementHandler : AuthorizationHandler<HeaderRequirement>
{
    protected override Task HeaderRequirementHandler (
        AuthorizationHandlerContext context,
        HeaderRequirement requirement)
    {
        var hasHeader = context.Request.Headers.ContainsKey(requirement.Header);
        if (hasHeader) // if we have the header
        {
            context.Succeed(requirement); // authorization successful
        }

        return Task.CompletedTask;
    }
}

Зарегистрируйте обработчик как сервис

services.AddScoped<IAuthorizationHandler, HeaderRequirementHandler>();

Добавьте политику в сервисы авторизации

services.AddAuthorization(options =>
    {
        options.AddPolicy("SomeHeader", policy =>
            policy.Requirements.Add(new HeaderRequirement("SomeHeader")));
    });

Теперь вы можете использовать его следующим образом: [Authorize(Policy = "SomeHeader")]

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

...