Простая авторизация в ASP.NET Core

Авторизация в ASP.NET Core контролируется с AuthorizeAttribute помощью различных параметров. В самой базовой форме применение атрибута [Authorize] к контроллеру, действию или Razor странице ограничивает доступ к компоненту, прошедшему проверку подлинности.

Следующий код ограничивает доступ к прошедшим AccountController проверку подлинности пользователям:

[Authorize]
public class AccountController : Controller
{
    public ActionResult Login()
    {
    }

    public ActionResult Logout()
    {
    }
}

Если вы хотите применить авторизацию к действию, а не к контроллеру, примените AuthorizeAttribute атрибут к самому действию:

public class AccountController : Controller
{
   public ActionResult Login()
   {
   }

   [Authorize]
   public ActionResult Logout()
   {
   }
}

Теперь только прошедшие Logout проверку подлинности пользователи могут получить доступ к функции.

Атрибут можно также использовать AllowAnonymous для разрешения доступа пользователей, не прошедших проверку подлинности, к отдельным действиям. Например:

[Authorize]
public class AccountController : Controller
{
    [AllowAnonymous]
    public ActionResult Login()
    {
    }

    public ActionResult Logout()
    {
    }
}

Это позволит только прошедшим проверку подлинности пользователям AccountControllerвыполнять действия, за исключением Login действия, доступного всем, независимо от их аутентифицированного или анонимного состояния.

Предупреждение

[AllowAnonymous] пропускает инструкции авторизации. При объединении и [Authorize] атрибуте [AllowAnonymous][Authorize] атрибуты игнорируются. Например, если применить на [AllowAnonymous] уровне контроллера:

  • Все требования к авторизации из [Authorize] атрибутов на одном контроллере или методах действий на контроллере игнорируются.
  • ПО промежуточного слоя проверки подлинности не является коротким, но не требуется успешно.

Следующий код ограничивает доступ к LogoutModelRazor странице для пользователей, прошедших проверку подлинности:

[Authorize]
public class LogoutModel : PageModel
{
    public async Task OnGetAsync()
    {

    }

    public async Task<IActionResult> OnPostAsync()
    {

    }
}

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

Авторизация атрибутов и Razor страниц

Невозможно AuthorizeAttribute применить к Razor обработчикам страниц. Например, [Authorize] нельзя применять OnGetк обработчику OnPostстраниц или к любому другому обработчику страницы. Рассмотрите возможность использования контроллера MVC ASP.NET Core для страниц с различными требованиями к авторизации для разных обработчиков. Использование контроллера MVC, если требуются различные требования к авторизации:

  • Является наименее сложным подходом.
  • Рекомендуемый корпорацией Майкрософт подход.

Если вы решили не использовать контроллер MVC, можно использовать следующие два подхода для применения авторизации к Razor методам обработчика страницы:

  • Используйте отдельные страницы для обработчиков страниц, требующих разной авторизации. Перемещение общего содержимого в одно или несколько частичных представлений. По возможности это рекомендуемый подход.

  • Для содержимого, который должен совместно использовать общую страницу, напишите фильтр, выполняющий авторизацию в составе IAsyncPageFilter.OnPageHandlerSelectionAsync. Проект PageHandlerAuth GitHub демонстрирует следующий подход:

    • АвторизоватьIndexPageHandlerFilter реализует фильтр авторизации:
    [TypeFilter(typeof(AuthorizeIndexPageHandlerFilter))]
    public class IndexModel : PageModel
    {
        private readonly ILogger<IndexModel> _logger;
    
        public IndexModel(ILogger<IndexModel> logger)
        {
            _logger = logger;
        }
    
        public void OnGet()
        {
    
        }
    
        public void OnPost()
        {
    
        }
    
        [AuthorizePageHandler]
        public void OnPostAuthorized()
        {
    
        }
    }
    
    • Атрибут [AuthorizePageHandler] применяется к обработчику OnPostAuthorized страницы:
    public class AuthorizeIndexPageHandlerFilter : IAsyncPageFilter, IOrderedFilter
    {
        private readonly IAuthorizationPolicyProvider policyProvider;
        private readonly IPolicyEvaluator policyEvaluator;
    
        public AuthorizeIndexPageHandlerFilter(
            IAuthorizationPolicyProvider policyProvider,
            IPolicyEvaluator policyEvaluator)
        {
            this.policyProvider = policyProvider;
            this.policyEvaluator = policyEvaluator;
        }
    
        // Run late in the selection pipeline
        public int Order => 10000;
    
        public Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next) => next();
    
        public async Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context)
        {
            var attribute = context.HandlerMethod?.MethodInfo?.GetCustomAttribute<AuthorizePageHandlerAttribute>();
            if (attribute is null)
            {
                return;
            }
    
            var policy = await AuthorizationPolicy.CombineAsync(policyProvider, new[] { attribute });
            if (policy is null)
            {
                return;
            }
    
            await AuthorizeAsync(context, policy);
        }
    
        #region AuthZ - do not change
        private async Task AuthorizeAsync(ActionContext actionContext, AuthorizationPolicy policy)
        {
            var httpContext = actionContext.HttpContext;
            var authenticateResult = await policyEvaluator.AuthenticateAsync(policy, httpContext);
            var authorizeResult = await policyEvaluator.AuthorizeAsync(policy, authenticateResult, httpContext, actionContext.ActionDescriptor);
            if (authorizeResult.Challenged)
            {
                if (policy.AuthenticationSchemes.Count > 0)
                {
                    foreach (var scheme in policy.AuthenticationSchemes)
                    {
                        await httpContext.ChallengeAsync(scheme);
                    }
                }
                else
                {
                    await httpContext.ChallengeAsync();
                }
    
                return;
            }
            else if (authorizeResult.Forbidden)
            {
                if (policy.AuthenticationSchemes.Count > 0)
                {
                    foreach (var scheme in policy.AuthenticationSchemes)
                    {
                        await httpContext.ForbidAsync(scheme);
                    }
                }
                else
                {
                    await httpContext.ForbidAsync();
                }
    
                return;
            }
        }
    

Предупреждение

Пример метода PageHandlerAuth не выполняет следующие действия.

  • Создание атрибутов авторизации, применяемых к странице, модели страницы или глобально. Создание атрибутов авторизации приводит к выполнению проверки подлинности и авторизации несколько раз, если на странице также применено несколько экземпляров или AuthorizeFilter несколько AuthorizeAttribute экземпляров.
  • Работайте вместе с остальной частью системы проверки подлинности и авторизации core ASP.NET. Необходимо проверить правильность работы этого подхода для приложения.

Нет планов поддержки AuthorizeAttributeRazor обработчиков страниц.