web-dev-qa-db-fra.com

Doit-il s'agir d'une revendication, d'un rôle ou d'une politique?

La distinction entre les rôles et les revendications est que les rôles décrivent un ensemble d'utilisateurs et les revendications décrivent une propriété d'un utilisateur. Il peut donc y avoir un rôle "Administrateur", mais il peut aussi y avoir une revendication "HasElevatedPrivilegeBadge". Les deux peuvent permettre la même action. Maintenant, que dois-je choisir si je veux autoriser uniquement certaines personnes à faire certaines choses, par exemple:

CanAddItem, CanUpdateItem, CanDeleteItem,
CanAddProduct, CanUpdateProduct, CanDeleteProduct

Je pourrais créer le rôle "Administrateur" et y ajouter les revendications "CanAddItem", "CanUpdateItem", etc., mais "CanAddItem" ne décrit pas une propriété d'un utilisateur. Il dit ce que l'utilisateur peut faire, ce qui n'est pas ce qu'une réclamation devrait faire, n'est-ce pas?

Une autre approche consiste à créer des politiques, telles que:

policy.AddPolicy("CanAddItem", policy => {
    policy.RequireAuthenticatedUser()
          .RequireRole("Administrator");
});

Mais pour plus de 20 politiques, il faudra une bonne partie de ma classe Startup. Existe-t-il une autre façon de procéder ou est-ce que l’une d’elles est la préférée?

Je voudrais souligner que je recherche spécifiquement une solution pour .Net Core Identity. Je demande une solution sur la façon d'adapter mon exigence aux tables d'identité fournies par le cadre.

5
FCin

Essentiellement, vous décrivez un mappage du rôle à l'autorisation.

Je pense que cela est à peu près couvert par la norme [Authorize (Role = xxx)] sur vos actions de contrôleur, où l'autorisation implicite est CanExecuteThisAction. Pas besoin de politiques supplémentaires, car elles agiraient simplement comme un mappage, ce qui pourrait prêter à confusion et, comme vous le dites, ajouter beaucoup de code standard.

Les stratégies semblent viser des autorisations plus complexes, où vous devez exécuter une logique par rapport aux revendications ou autres propriétés de l'utilisateur, l'exemple étant la stratégie AtLeast21 où les utilisateurs prétendent être une date de naissance.

Je suppose qu'ils remplaceraient les classes AuthorizeAttribute personnalisées.

Je ne les utiliserais pas lorsque l'attribut Authorize par défaut peut le gérer seul, comme pour la vérification des rôles.

4
Ewan

Je pourrais créer le rôle "Administrateur" et y ajouter les revendications "CanAddItem", "CanUpdateItem", etc., mais "CanAddItem" ne décrit pas une propriété d'un utilisateur.

Selon votre point de vue, votre exemple peut être un peu trop pragmatique.

D'un autre point de vue, une personne qui a 21 ans est également d'âge légal pour boire, mais ce n'est pas le cas Peut-on boire de l'alcool non?

Revenons à votre exemple, quelle est la différence entre `Product Creator, Product Changer, et vos exemples? Pour moi, c'est juste le point de vue, l'un étant plus descriptif de ce qu'ils sont contre ce qu'ils peuvent faire ... même si c'est vraiment la même chose quand il s'agit de votre réclamation.

1
Erik Philips

J'opte généralement pour les politiques car elles permettent un contrôle granulaire et expressif de l'autorisation. Pour résoudre le problème de leur utilisation d'espace dans la classe de démarrage, vous pouvez répartir les stratégies en une classe statique.

internal static class Policies
{
  public static void CanAddItem(AuthorizationPolicyBuilder policy)
  {
    policy.RequireAuthenticatedUser()
      .RequireRole("Administrator");
  }
}

Et puis dans Startup.cs l'enregistrement de chaque politique est un one-liner

services.AddAuthorization(options =>
{
  options.AddPolicy(nameof(Policies.CanAddItem), Policies.CanAddItem);
});

Si vous aviez besoin d'encore plus de contrôle, vous pourriez envisager d'ajouter un IAuthorizationPolicyProvider personnalisé qui vous permet de résoudre des stratégies par programme.

https://docs.Microsoft.com/en-us/aspnet/core/security/authorization/iauthorizationpolicyprovider?view=aspnetcore-2.1

1
Eric Damtoft

Avertissement: je n'ai jamais utilisé de politiques auparavant. Je pense que la réponse à votre problème dépend également du fournisseur d'identité que vous utilisez. si le fournisseur d'identité n'est pas votre propre application mais un fournisseur d'identité tiers OR un produit standardisé comme le serveur d'identité 4, l'utilisation de rôles et de revendications serait préférable, car OAUTH/openidconnect peut fonctionner avec des rôles/revendications nativley.

Nous utilisons un schéma comme le vôtre, mais de légers rebondissements: 1. Nous avons plusieurs rôles, par ex. un administrateur, itemManager et un utilisateur. 2. Nous avons des revendications comme "item.add", "item.delete", "item.create" 3. Chaque rôle peut avoir N revendications 4. Chaque utilisateur peut avoir N rôles Cela permet beaucoup de composabilité, par ex. un utilisateur peut obtenir la réclamation "item.delete" parce qu'il est administrateur ou parce qu'il est itemManager.

Il est important que les noms des revendications doivent être quelque peu standardisés et que leur granularité soit adaptée à votre application - par exemple, si le droit de créer un élément et de le mettre à jour est connecté de manière logique, créez une seule revendication, pas deux.

De plus, vous pouvez utiliser des rôles pour insérer un peu de logique métier, comme product.maxnumber.200 => l'utilisateur ne peut avoir que 200 produits, qui doivent être validés par votre logique métier.

Enfin, plusieurs responsables de la sécurité que j'ai lus au cours des derniers mois (OWASP) ont recommandé de placer l'autorisation à côté de votre logique métier, car souvent la question "l'utilisateur peut-il faire cela?" doit être répondu dans le contexte de la logique métier: "l'utilisateur a-t-il les rôles product.add ET a-t-il moins de produits product.maxnumber?" -> un tel contexte est facile à obtenir dans une demande particulière, mais difficile à répondre de manière générale, comme dans les politiques.

0
Christian Sauer