Une bibliothèque d'aide pour implémenter le contrôle d'accès basé sur l'autorisation / d'attribut (ABAC) avec les jetons Web JSON à l'aide du contrôle d'accès basé sur les politiques d'ASP.NET Core (PBAC).
Créez l'énumération des autorisations:
public enum Permissions
{
Create = 0 ,
Read = 1 ,
Update = 2 ,
Delete = 3 ,
}Notez que le fait d'avoir la valeur sous-jacente exacte pour chaque autorisation est important - le gâcher gâchera les autorisations stockées!
De plus, seuls les énigmes avec l' int en tant que type sous-jacent (la valeur par défaut) sont actuellement pris en charge.
Définissez les valeurs d'autorisation de l'utilisateur à l'intérieur de votre fournisseur d'identité à l'aide de PermissionSet :
user . Claims [ ClaimNames . Permissions ] = new PermissionSet < Permissions > ( new [ ]
{
Permissions . Create ,
Permissions . Read ,
} )
. ToCompactString ( ) ;Ajoutez le gestionnaire d'obligation de politique d'autorisation avec le même nom de revendication que ci-dessus:
services . AddPermissionBasedAuthorization < Permissions > ( options =>
options . PermissionsClaimName = ClaimNames . Permissions ) ; Notez que si vous redéfinissez l'autorisation DefaultPolicy dans votre application, le code ci-dessus doit être inséré après votre logique pour faire en sorte que les politiques d'autorisation héritent de la nouvelle stratégie par défaut.
(Éventuellement) Hériter de l' AuthorizePermission<T> avec les autorisations spécifiques Type d'énumération:
public class AuthorizePermissionAttribute : AuthorizePermissionAttribute < Permissions >
{
public AuthorizePermissionAttribute ( Permissions permission )
: base ( permission )
{ }
}Ou créer une méthode d'extension si vous utilisez les API minimales:
public static TBuilder RequirePermission < TBuilder > ( this TBuilder builder , Permissions permission )
where TBuilder : IEndpointConventionBuilder
{
if ( builder == null )
throw new ArgumentNullException ( nameof ( builder ) ) ;
return builder . RequireAuthorization ( new AuthorizePermissionAttribute < Permissions > ( permission ) ) ;
} Décorez les contrôleurs / points de terminaison avec l'attribut AuthorizePermission<T> (ou celui créé ci-dessus):
[ HttpGet ]
[ Authorize ( Permissions . Read ) ]
public IActionResult Get ( )
=> Ok ( ) ;Ou si vous utilisez les API minimales:
app . MapGet ( "/" , ( ) => Results . Ok ( ) )
. RequirePermission ( Permissions . Read ) ; L'ensemble d'autorisation est en cours de série en une chaîne sous forme de numéro hexadécimal où n -th bit représente la présence d'une autorisation avec la valeur sous-jacente de n .
Par exemple, considérez l'énumération d'autorisation suivante:
public enum Permissions
{
Create = 0,
Read = 1,
Update = 2,
Delete = 3,
Manage = 4,
}
Ensuite, la représentation binaire d'un ensemble contenant toutes les autorisations ci-dessus ressemblerait à ceci:
1 F - permission string
┌┬┬┤ ┌┬┬┤
0001 1111 - permission bit values
││││ ││││
7654 3210 - bit positions
└┬┘│ ││││
│ │ │││└ Create
│ │ ││└ Read
│ │ │└ Update
│ │ └ Delete
│ └ Manage
└ Not used
Pour la désérialisation, ce qui précède se fait dans l'ordre inversé.
De plus, car sur la base de la valeur d'énumération, nous pouvons calculer la position de bit spécifique que nous devons vérifier, nous n'avons pas besoin de désérialiser la chaîne entière lorsque nous vérifions une seule autorisation.
Vérification d'une seule valeur d'autorisation à partir de la chaîne compacte:
| Méthode | Signifier | Erreur | Stddev | Alloué |
|---|---|---|---|---|
| PermisssionSet_haspermission | 74.17 ns | 1,382 ns | 1,225 ns | - |
La validation d'un utilisateur a une autorisation requise dans sa liste de revendications:
| Méthode | Signifier | Erreur | Stddev | Alloué |
|---|---|---|---|---|
| Autorisation AuthorizationHandlerBenchmark_HandlerequimentAsync | 359.4 ns | 6.79 ns | 13.25 ns | 144 b |