Autorisation simple dans ASP.NET Core

L’autorisation dans ASP.NET Core est contrôlée à l’aide de AuthorizeAttribute et de ses différents paramètres. Dans sa forme la plus basique, l’application de l’attribut [Authorize] à un contrôleur, à une action ou à une page Razor, limite l’accès à ce composant aux utilisateurs authentifiés.

Le code suivant limite l’accès à AccountController aux utilisateurs authentifiés :

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

    public ActionResult Logout()
    {
    }
}

Si vous souhaitez appliquer l’autorisation à une action plutôt qu’au contrôleur, appliquez l’attribut AuthorizeAttribute à l’action elle-même :

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

   [Authorize]
   public ActionResult Logout()
   {
   }
}

Désormais, seuls les utilisateurs authentifiés peuvent accéder à la fonction Logout.

Vous pouvez également utiliser l’attribut AllowAnonymous pour autoriser les utilisateurs non authentifiés à accéder à des actions individuelles. Par exemple :

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

    public ActionResult Logout()
    {
    }
}

Cela autoriserait uniquement les utilisateurs authentifiés à accéder à AccountController, à l’exception de l’action Login, qui est accessible par tout le monde, quelle que soit leur état authentifié ou non authentifié/anonyme.

Avertissement

[AllowAnonymous] contourne les instructions d’autorisation. Si vous combinez [AllowAnonymous] et un attribut [Authorize], les attributs [Authorize] sont ignorés. Par exemple, si vous appliquez [AllowAnonymous] au niveau du contrôleur :

  • Toutes les exigences d’autorisation des attributs [Authorize] sur le même contrôleur ou des méthodes d’action sur le contrôleur sont ignorées.
  • L’intergiciel d’authentification n’est pas court-circuité, mais n’a pas besoin de réussir.

Le code suivant limite l’accès à la page LogoutModelRazor aux utilisateurs authentifiés :

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

    }

    public async Task<IActionResult> OnPostAsync()
    {

    }
}

Pour plus d’informations sur la façon d’exiger l’authentification globale de tous les utilisateurs, consultez Exiger des utilisateurs authentifiés.

Attribut d’autorisation et Razor Pages

AuthorizeAttribute ne peut pas être appliqué aux gestionnaires de page Razor. Par exemple, [Authorize] ne peut pas être appliqué à OnGet, OnPost ou à tout autre gestionnaire de page. Envisagez d’utiliser un contrôleur MVC ASP.NET Core pour les pages avec des exigences d’autorisation différentes pour différents gestionnaires. L’utilisation d’un contrôleur MVC lorsque des exigences d’autorisation différentes sont requises :

  • Est l’approche la moins complexe.
  • Est l’approche recommandée par Microsoft.

Si vous décidez de ne pas utiliser de contrôleur MVC, les deux approches suivantes peuvent être utilisées pour appliquer l’autorisation aux méthodes du gestionnaire Razor Page :

  • Utiliser des pages distinctes pour les gestionnaires de page nécessitant une autorisation différente. Déplacer le contenu partagé dans une ou plusieurs vues partielles. Lorsque cela est possible, il s’agit de l’approche recommandée.

  • Pour le contenu qui doit partager une page commune, écrire un filtre qui effectue l’autorisation dans le cadre de IAsyncPageFilter.OnPageHandlerSelectionAsync. Le projet GitHub PageHandlerAuth illustre cette approche :

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

Avertissement

L’exemple d’approche PageHandlerAuthne :

  • compose pas avec les attributs d’autorisation appliqués à la page, au modèle de la page ou à l’échelle globale. La composition des attributs d’autorisation entraîne l’exécution de l’authentification et de l’autorisation plusieurs fois lorsque vous avez une autre instance AuthorizeAttribute ou AuthorizeFilter également appliquée à la page.
  • fonctionne pas conjointement avec le reste du système d’authentification et d’autorisation ASP.NET Core. Vous devez vérifier que cette approche fonctionne correctement pour votre application.

Il n’est pas prévu de prendre en charge AuthorizeAttribute sur les gestionnaires Razor Page.