Una biblioteca de ayuda para implementar el control de acceso basado en permiso/atributos (ABAC) con tokens web JSON utilizando el control de acceso basado en políticas (PBAC) de ASP.NET Core.
Crea los permisos enum:
public enum Permissions
{
Create = 0 ,
Read = 1 ,
Update = 2 ,
Delete = 3 ,
}Tenga en cuenta que es importante tener el valor subyacente exacto para cada permiso: ¡arruinarlo, te meterá los permisos almacenados!
Además, solo se admiten enums con el int como un tipo subyacente (el valor predeterminado).
Establezca los valores de permiso del usuario dentro de su proveedor de identidad utilizando el PermissionSet :
user . Claims [ ClaimNames . Permissions ] = new PermissionSet < Permissions > ( new [ ]
{
Permissions . Create ,
Permissions . Read ,
} )
. ToCompactString ( ) ;Agregue el controlador de requisitos de póliza de permiso con el mismo nombre de reclamación que el anterior:
services . AddPermissionBasedAuthorization < Permissions > ( options =>
options . PermissionsClaimName = ClaimNames . Permissions ) ; Tenga en cuenta que si redefine la autorización DefaultPolicy en su aplicación, entonces el código anterior debe insertarse después de su lógica para hacer que las políticas de permiso hereden la nueva política predeterminada.
(Opcionalmente) herede la AuthorizePermission<T> con el tipo de enum de permisos específicos:
public class AuthorizePermissionAttribute : AuthorizePermissionAttribute < Permissions >
{
public AuthorizePermissionAttribute ( Permissions permission )
: base ( permission )
{ }
}O crear un método de extensión si se usa las API mínimas:
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 ) ) ;
} Decorar los controladores/puntos finales con el atributo AuthorizePermission<T> (o el creado anteriormente):
[ HttpGet ]
[ Authorize ( Permissions . Read ) ]
public IActionResult Get ( )
=> Ok ( ) ;O si usa las API mínimas:
app . MapGet ( "/" , ( ) => Results . Ok ( ) )
. RequirePermission ( Permissions . Read ) ; El conjunto de permisos se está serializando en una cadena como un número hexadecimal donde n -th bit representa la presencia de un permiso con el valor subyacente de n .
Por ejemplo, considere el siguiente permiso enum:
public enum Permissions
{
Create = 0,
Read = 1,
Update = 2,
Delete = 3,
Manage = 4,
}
Luego, la representación binaria de un conjunto que contiene todos los permisos anteriores se vería así:
1 F - permission string
┌┬┬┤ ┌┬┬┤
0001 1111 - permission bit values
││││ ││││
7654 3210 - bit positions
└┬┘│ ││││
│ │ │││└ Create
│ │ ││└ Read
│ │ │└ Update
│ │ └ Delete
│ └ Manage
└ Not used
Para la deserialización, lo anterior se hace en el orden invertido.
Además, debido a que, según el valor de enum, podemos calcular la posición de bit específica que necesitamos para verificar, no necesitamos deserializar la cadena completa cuando verificamos un solo permiso.
Verificar un valor de permiso único de la cadena compacta:
| Método | Significar | Error | Stddev | Asignado |
|---|---|---|---|---|
| Permissionset_haspermission | 74.17 ns | 1.382 ns | 1.225 ns | - |
Validar a un usuario tiene un permiso requerido en su lista de reclamos:
| Método | Significar | Error | Stddev | Asignado |
|---|---|---|---|---|
| PermissionAuthorizationHandlerBenchmark_HandlerequirementAsync | 359.4 ns | 6.79 ns | 13.25 ns | 144 B |