Autorizzazione semplice in ASP.NET Core

L'autorizzazione in ASP.NET Core viene controllata con l'attributo [Authorize] e i relativi vari parametri. Nella forma più semplice, l'applicazione dell'attributo a un controller, un'azione o Razor una pagina limita l'accesso [Authorize] a tale componente agli utenti autenticati.

Prerequisiti

Questo articolo presuppone che si abbia una conoscenza di base di ASP.NET Core Razor Pages e MVC. Se non si ha familiarità con ASP.NET Core, vedere le risorse seguenti:

Usare l'attributo [Authorize]

Il codice seguente limita l'accesso AccountController agli utenti autenticati:

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

    public ActionResult Logout()
    {
    }
}

Se si vuole applicare l'autorizzazione a un'azione anziché al controller, applicare l'attributo AuthorizeAttribute all'azione stessa:

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

   [Authorize]
   public ActionResult Logout()
   {
   }
}

Ora solo gli utenti autenticati possono accedere alla Logout funzione.

È anche possibile usare l'attributo per consentire l'accesso AllowAnonymous da parte di utenti non autenticati a singole azioni. Ad esempio:

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

    public ActionResult Logout()
    {
    }
}

Ciò consentirebbe solo agli utenti autenticati di , AccountControllerad eccezione dell'azione Login , accessibile da tutti, indipendentemente dal relativo stato autenticato o non autenticato/anonimo.

Avviso

[AllowAnonymous] ignora le istruzioni di autorizzazione. Se si combina [AllowAnonymous] e un [Authorize] attributo, gli [Authorize] attributi vengono ignorati. Ad esempio, se si applica [AllowAnonymous] a livello di controller:

  • Tutti i requisiti di autorizzazione degli [Authorize] attributi nello stesso controller o nello stesso metodo di azione nel controller vengono ignorati.
  • Il middleware di autenticazione non è corto circuito, ma non deve avere esito positivo.

Il codice seguente limita l'accesso LogoutModelRazor alla pagina agli utenti autenticati:

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

    }

    public async Task<IActionResult> OnPostAsync()
    {

    }
}

Per informazioni su come richiedere a livello globale l'autenticazione di tutti gli utenti, vedere Richiedere utenti autenticati.

Autorizzare attributi e Razor pagine

Non AuthorizeAttributepuò essere applicato ai Razor gestori di pagina. Ad esempio, [Authorize] non può essere applicato a OnGet, OnPosto a qualsiasi altro gestore di pagine. È consigliabile usare un controller MVC core ASP.NET per le pagine con requisiti di autorizzazione diversi per gestori diversi. Uso di un controller MVC quando sono necessari requisiti di autorizzazione diversi:

  • È l'approccio meno complesso.
  • È l'approccio consigliato da Microsoft.

Se si decide di non usare un controller MVC, è possibile usare i due approcci seguenti per applicare l'autorizzazione ai Razor metodi del gestore Page:

  • Usare pagine separate per i gestori di pagine che richiedono un'autorizzazione diversa. Spostare il contenuto condiviso in una o più visualizzazioni parziali. Quando possibile, si tratta dell'approccio consigliato.

  • Per il contenuto che deve condividere una pagina comune, scrivere un filtro che esegue l'autorizzazione come parte di IAsyncPageFilter.OnPageHandlerSelectionAsync. Il progetto GitHub PageHandlerAuth illustra questo approccio:

    [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;
            }
        }
    

Avviso

L'approccio di esempio PageHandlerAuth non è:

  • Comporre con attributi di autorizzazione applicati alla pagina, al modello di pagina o a livello globale. La composizione degli attributi di autorizzazione comporta l'autenticazione e l'autorizzazione eseguite più volte quando alla pagina sono applicate anche una o AuthorizeFilter più AuthorizeAttribute istanze.
  • Lavorare in combinazione con il rest sistema di autenticazione e autorizzazione di ASP.NET Core. È necessario verificare che l'uso di questo approccio funzioni correttamente per l'applicazione.

Non sono previsti piani per supportare i AuthorizeAttribute Razor gestori di pagine.