Авторизация в. NET Core 3: заказ, в котором выполняются требования - PullRequest
0 голосов
/ 03 февраля 2020

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

При запуске у меня есть:

 app.UseEndpoints(endpoints =>
 {
     endpoints.MapControllers()
         .RequireAuthorization("UserIsAuthenticated")
         .RequireAuthorization("UserIsRegistered");
 });

, а затем я использую атрибут [Authorize(Roles = "Administrator")] по умолчанию и мои [MyAuthorize] атрибуты.

Порядок, в котором эти политики должны должно быть выполнено:

  • Сначала UserIsAuthenticated, чтобы проверить, аутентифицирован ли пользователь.
  • Если они есть, он должен проверить UserIsRegistered.
  • Наконец, атрибуты должны быть применены.

В моем случае порядок имеет значение, потому что у меня есть

services.AddAuthorization(options => { options.InvokeHandlersAfterFailure = false; });

(если пользователь не аутентифицирован, я не могу проверить его утверждения и нет смысла проверять следующие политики).

Однако в некоторых случаях я видел, что атрибуты оцениваются до политик аутентификации.

Есть ли способ наложить порядок требований?

1 Ответ

0 голосов
/ 04 февраля 2020

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

public class AuthorizeMultiplePolicyFilter: IAsyncAuthorizationFilter
{
    private  IAuthorizationService _authorization;
    private  string[] _policies;


    public AuthorizeMultiplePolicyFilter(string[] policies)
    {
        _policies = policies;
    }

    public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
    {
        if (context.HttpContext.Request.Path.StartsWithSegments("/Account"))
        {
            return;
        }

        _authorization = context.HttpContext.RequestServices.GetRequiredService<IAuthorizationService>();
        foreach (var policy in _policies)
        {
            var authorized = await _authorization.AuthorizeAsync(context.HttpContext.User, policy);
            if (!authorized.Succeeded)
            {
                if(policy == "UserIsAuthenticated")
                {
                    context.Result = new RedirectResult("/Account/Login");
                }
                if(policy == "UserIsRegistered")
                {
                    context.Result = new ForbidResult();
                }

                return;
            }
        }

    }
}

Startup.cs

services.AddControllersWithViews(options =>
                options.Filters.Add(new AuthorizeMultiplePolicyFilter(new string[] { "UserIsAuthenticated", "UserIsRegistered" }))
        );
...