web-dev-qa-db-fra.com

Autorisation personnalisée dans Asp.net WebApi - quel gâchis?

Je lis plusieurs ressources (livres et réponses SO) sur l'autorisation dans WebApi.

Supposons que je veuille ajouter un attribut personnalisé qui autorise l'accès uniquement à certains utilisateurs:

Cas n ° 1

J'ai vu cette approche de surcharger OnAuthorization, qui définit la réponse si quelque chose ne va pas

public class AllowOnlyCertainUsers : AuthorizeAttribute
{
 public override void OnAuthorization(HttpActionContext actionContext)
  {
   if ( /*check if user OK or not*/)
   {
     actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
   }
  }
}

Cas n ° 2

Mais j'ai aussi vu cet exemple similaire qui annulait aussi OnAuthorization mais en appelant base:

public override void OnAuthorization(HttpActionContext actionContext) 
{ 
  base.OnAuthorization(actionContext);

    // If not authorized at all, don't bother

    if (actionContext.Response == null)  
     {
      //...
     }
}

Ensuite, vous vérifiez si le HttpActionContext.Response est défini ou non. S'il n'est pas défini, cela signifie que la demande est autorisée et que l'utilisateur est d'accord

Cas n ° 3

Mais j'ai aussi vu cette approche consistant à remplacer IsAuthorized:

public class AllowOnlyCertainUsers : AuthorizeAttribute
{
 protected override bool IsAuthorized(HttpActionContext context)
  {
   if ( /*check if user OK or not*/)
   {
    return true;// or false
   }
  }
}

Cas n ° 4

Et puis j'ai vu un exemple similaire mais avec l'appel de base.IsAuthorized (context):

protected override bool IsAuthorized(HttpActionContext context)
{
 if (something1 && something2 && base.IsAuthorized(context)) //??
 return true;
 return false;
}

Une dernière chose

Et finalement, Dominick dit ici :

Vous ne devriez pas écraser OnAuthorization, car il vous manquerait une gestion [AllowAnonymous].

Questions

  • 1) Quelles méthodes dois-je utiliser: IsAuthorized ou OnAuthorization? (ou quand utiliser lequel)

  • 2) quand dois-je appeler base.IsAuthorized or base.OnAuthorization`?

  • 3) Est-ce ainsi qu'ils l'ont construit? que si la réponse est nulle alors tout va bien? (cas n ° 2)

NB

Veuillez noter que j'utilise (et que je veux utiliser) uniquement AuthorizeAttribute qui hérite déjà de AuthorizationFilterAttribute

Pourquoi ?

Parce que j'en suis à la première étape de: http://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api

enter image description here

Quoi qu'il en soit, je demande via l'extension d'attribut Authorize.

105
Royi Namir

Quelles méthodes devrais-je utiliser: IsAuthorized ou OnAuthorization? (ou quand utiliser lequel)

Vous étendrez AuthorizationFilterAttribute si votre logique d'autorisation ne dépend pas de l'identité établie et des rôles. Pour l'autorisation liée à l'utilisateur, vous allez étendre et utiliser AuthorizeAttribute. Dans le premier cas, vous remplacerez OnAuthorization. Dans ce dernier cas, vous substituerez IsAuthorized. Comme vous pouvez le constater à partir du code source de ces attributs, OnAuthorization est marqué comme un élément virtuel à remplacer si vous dérivez de AuthorizationFilterAttribute. D'autre part, la méthode IsAuthorized est marquée virtuelle dans AuthorizeAttribute. Je crois que ceci est un bon pointeur sur l'utilisation prévue.

quand devrais-je appeler base.IsAuthorized ou base.OnAuthorization?

La réponse à cette question réside dans le fonctionnement général de OO. Si vous substituez une méthode, vous pouvez soit fournir complètement une nouvelle implémentation, soit utiliser une implémentation fournie par parent et améliorer le comportement. Par exemple, prenons le cas de IsAuthorized(HttpActionContext). Le comportement de la classe de base consiste à comparer l'utilisateur/rôle à ce qui est spécifié dans le filtre par rapport à l'identité établie. Dites, vous voulez faire tout cela mais en plus, vous voulez vérifier quelque chose d'autre, qui peut être basé sur un en-tête de requête ou autre. Dans ce cas, vous pouvez fournir un remplacement comme celui-ci.

protected override bool IsAuthorized(HttpActionContext actionContext)
{
    bool isAuthroized = base.IsAuthorized(actionContext);
    // Here you look at the header and do your additional stuff based on actionContext
    // and store the result in isRequestHeaderOk
    // Then, you can combine the results
    // return isAuthorized && isRequestHeaderOk;
}

Je suis désolé mais je ne comprends pas votre Q3. BTW, le filtre d'autorisation existe depuis longtemps et les gens l'utilisent pour toutes sortes de choses, et parfois aussi de manière incorrecte.

Une dernière chose. Et enfin, il y avait ce gars ici qui a dit: Vous ne devriez pas écraser OnAuthorization - car il vous manquerait la gestion [AllowAnonymous].

Le type qui a dit cela est le dieu du contrôle d'accès - Dominick. Évidemment ce sera correct. Si vous regardez l'implémentation de OnAuthorization (copié ci-dessous),

public override void OnAuthorization(HttpActionContext actionContext)
{
    if (actionContext == null)
    {
        throw Error.ArgumentNull("actionContext");
    }

    if (SkipAuthorization(actionContext))
    {
        return;
    }

    if (!IsAuthorized(actionContext))
    {
        HandleUnauthorizedRequest(actionContext);
    }
}

l'appel de SkipAuthorization est la partie qui garantit que les filtres AllowAnonymous sont appliqués, c'est-à-dire que l'autorisation est ignorée. Si vous substituez cette méthode, vous perdez ce comportement. En fait, si vous décidiez de baser votre autorisation sur des utilisateurs/rôles, vous auriez alors décidé de dériver de AuthorizeAttribute. La seule option correcte qui vous reste à ce moment-là sera de remplacer IsAuthorized et non le _ déjà remplacé OnAuthorization, bien qu’il soit techniquement possible de le faire.

PS Dans l’API Web ASP.NET, il existe un autre filtre appelé filtre d’authentification. L’idée est que vous l’utilisiez comme filtre d’authentification et d’autorisation, comme son nom l’indique. Cependant, il existe de nombreux exemples où cette limite est floue. De nombreux exemples de filtres d'authentification permettent d'effectuer une sorte d'authentification. Quoi qu'il en soit, si vous avez le temps et que vous voulez comprendre un peu plus, jetez un coup d'œil à ce MSDN article . Disclaimer: Il a été écrit par moi.

90
Badri

Ok, ma suggestion est de procéder comme suit en supposant que vous utilisez des jetons de porteur OAuth pour protéger votre API Web et que vous définissez allowedTime en tant que revendication pour l'utilisateur lorsque vous avez émis le jeton. Vous pouvez en savoir plus sur authentification par jeton ici

  1. Créer CustomAuthorizeAttribute à partir de AuthorizationFilterAttribute
  2. remplacez la méthode OnAuthorizationAsync et utilisez l'exemple de code ci-dessous:

     public class CustomAuthorizeAttribute : AuthorizationFilterAttribute
    {
    
        public override Task OnAuthorizationAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken)
        {
    
            var principal = actionContext.RequestContext.Principal as ClaimsPrincipal;
    
            if (!principal.Identity.IsAuthenticated)
            {
                return Task.FromResult<object>(null);
            }
    
            var userName = principal.FindFirst(ClaimTypes.Name).Value;
            var userAllowedTime = principal.FindFirst("userAllowedTime").Value;
    
            if (currentTime != userAllowedTime)
            {
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, "Not allowed to access...bla bla");
                return Task.FromResult<object>(null);
            }
    
            //User is Authorized, complete execution
            return Task.FromResult<object>(null);
    
        }
    }
    
  3. Maintenant, dans vos contrôleurs, vous utilisez l'attribut CustomAuthorize pour protéger vos contrôleurs à l'aide de cette logique d'autorisation.
17
Taiseer Joudeh

ASP.NET v5 a introduit un tout nouveau système d'autorisation. Pour ceux qui vont utiliser .NET 5, je suggérerais de passer à Microsoft.AspNet.Authorization.

En gros, cela résout le désordre causé en conservant à la fois System.Web.Http.Authorize et System.Web.Mvc.Authorize et d’autres implémentations d’authentification plus anciennes.

Il fournit une très bonne abstraction des types d'action (créer, lire, mettre à jour, supprimer), des ressources, des rôles, des revendications, des vues, des exigences personnalisées et permet de créer des gestionnaires personnalisés combinant tous les éléments ci-dessus. En outre, ces gestionnaires peuvent être utilisés en combinaison également.

Dans ASP.NET v5, l’autorisation fournit désormais un rôle déclaratif simple et un modèle plus riche, basé sur la stratégie, dans lequel l’autorisation est exprimée en exigences et les gestionnaires évaluent les revendications des utilisateurs par rapport aux exigences. Les vérifications impératives peuvent être basées sur des règles simples ou des règles évaluant l'identité de l'utilisateur et les propriétés de la ressource à laquelle l'utilisateur tente d'accéder.

3
Anestis Kivranoglou