Autorização simples no ASP.NET Core

A autorização no ASP.NET Core é controlada com o atributo [Authorize] e seus vários parâmetros. Em sua forma mais básica, aplicar o atributo [Authorize] a um controlador, ação ou Página do Razor limita o acesso aos usuários autenticados desse componente.

Pré-requisitos

Este artigo pressupõe que você tenha uma compreensão básica de Páginas do ASP.NET Core Razor e MVC. Se você não estiver familiarizado com o ASP.NET Core, confira os seguintes recursos:

Use o atributo [Authorize]

O código a seguir limita o acesso ao AccountController a usuários autenticados:

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

    public ActionResult Logout()
    {
    }
}

Se você quiser aplicar autorização a uma ação em vez do controlador, aplique o atributo AuthorizeAttribute à ação em si:

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

   [Authorize]
   public ActionResult Logout()
   {
   }
}

Agora, somente usuários autenticados podem acessar a função Logout.

Você também pode usar o atributo AllowAnonymous para permitir o acesso de usuários não autenticados a ações individuais. Por exemplo:

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

    public ActionResult Logout()
    {
    }
}

Isso permitiria apenas usuários autenticados para o AccountController, exceto para a ação Login, que é acessível por todos, independentemente de suas status autenticadas ou não autenticadas ou anônimas.

Aviso

[AllowAnonymous] ignora instruções de autorização. Se você combinar [AllowAnonymous] e um atributo [Authorize], os atributos [Authorize] serão ignorados. Por exemplo, se você aplicar [AllowAnonymous] no nível do controlador:

  • Todos os requisitos de autorização de atributos [Authorize] no mesmo controlador ou métodos de ação no controlador são ignorados.
  • O middleware de autenticação não é de curto-circuito, mas não precisa ter êxito.

O código a seguir limita o acesso à Página do LogoutModelRazor a usuários autenticados:

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

    }

    public async Task<IActionResult> OnPostAsync()
    {

    }
}

Para obter informações sobre como exigir que todos os usuários sejam autenticados globalmente, confira Exigir usuários autenticados.

Atributo de autorização do Razor Pages

O AuthorizeAttributenão pode ser aplicado a manipuladores de página do Razor. Por exemplo, [Authorize] não pode ser aplicado a OnGet, OnPost ou a qualquer outro manipulador de página. Considere usar um controlador MVC ASP.NET Core para páginas com requisitos de autorização diferentes para manipuladores diferentes. Usar um controlador MVC quando diferentes requisitos de autorização são necessários:

  • É a abordagem menos complexa.
  • É a abordagem recomendada pela Microsoft.

Se você decidir não usar um controlador MVC, as duas abordagens a seguir poderão ser usadas para aplicar autorização aos métodos Razor do manipulador de página:

  • Use páginas separadas para manipuladores de página que exigem autorização diferente. Mova o conteúdo compartilhado para uma ou mais modos de exibição parciais. Quando possível, essa é a abordagem recomendada.

  • Para conteúdo que deve compartilhar uma página comum, escreva um filtro que executa a autorização como parte de IAsyncPageFilter.OnPageHandlerSelectionAsync. O projeto GitHub PageHandlerAuth demonstra essa abordagem:

    [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()
        {
    
        }
    }
    
    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;
            }
        }
    

Aviso

A abordagem de exemplo PageHandlerAuthnão:

  • Compõe com atributos de autorização aplicados à página, ao modelo de página ou globalmente. Compor atributos de autorização resulta em autenticação e autorização em execução várias vezes quando você tem mais AuthorizeAttribute uma ou AuthorizeFilter instâncias também aplicadas à página.
  • Trabalhe em conjunto com o rest do sistema de autenticação e autorização do ASP.NET Core. Você deve verificar se o uso dessa abordagem funciona corretamente para seu aplicativo.

Não há planos para dar suporte aos Manipuladores de página AuthorizeAttribute em Razor .