2012-09-17 25 views
5

Estoy tratando de implementar un nuevo enfoque de acceso basado en permisos para mi aplicación MVC; Tenemos varios Grupo de permisos y cada grupo contiene una lista de Permiso. por ejemplo, tenemos el grupo de permisos Invoices que contiene las claves de permiso CreateInvoice,RemoveInvoice,etc.Atributos de C#: Usar constantes enum como parámetros de entrada

En este enfoque cada mvc Action debe requerir un permiso específico para la ejecución. Estoy tratando de hacerlo a través de CustomAttributes, algo como esto:

public class InvoiceController : Controller 
    { 
     [RequirePermission(Permissions.Invoices.CreateInvoice)] 
     public ActionResult Create() 
     { 
      return View(); 
     } 
    } 

Para que sea más fácil para los desarrolladores para recordar los diferentes grupos de permisos y claves de permiso que estoy tratando de crear una lista predefinida de permisos que debe ser una combinación de grupo de permisos y clave de permiso. pero debido a las restricciones aplicadas al uso de argumentos de atributos en C# no pude hacerlo funcionar todavía. (no quiero hacer una gran enumurator extra y poner todas las llaves de permisos allí)

mi último intento fue la creación de un enumerador para cada grupo de permisos y luego definir claves de permisos que las constantes de enumeración allí:

public class PermissionEnums 
{ 
    [PermissionGroup(PermissionGroupCode.Invoice)] 
    public enum Invoices 
    { 
     CreateInvoice = 1, 
     UpdateInvoice = 2, 
     RemoveInvoice = 3, 
     ManageAttachments = 4 
    } 

    [PermissionGroup(PermissionGroupCode.UserAccounts)] 
    public enum UserAccounts 
    { 
     Create = 1, 
     ChangePassword = 2 
    } 
} 

Como puede ver aquí tenemos una combinación de códigos, la clave de grupo de permisos especificada utilizando un PermissionGroup atributo y el código de la clave de permiso especificado como código numérico en cada constante enum.

atributo la RequirePermission define como a continuación:

public class RequirePermissionAttribute : Attribute 
{ 
    private Enum _Permission; 

    public RequirePermissionAttribute(Enum Permission) 
     : base() 
    { 
     _Permission = Permission; 
    } 
} 

pero el problema es que los objetos de tipo Enum no podían utilizarse como argumentos Atributo.

Cualquier sugerencia/idea se aprecia

Respuesta

6

He encontrado la solución, lo único que se necesita cambiar es el tipo de parámetro de constructure. en lugar de utilizar Enum usted tiene que utilizar object:

public class RequirePermissionAttribute : AuthorizeAttribute 
{ 
    private object _Permission; 

    public RequirePermissionAttribute(object Permission) 
     : base() 
    { 
     _Permission = Permission; 
    } 
} 

Aquí está el código completo:

/***************** Permission Groups And Keys *****************/ 
public static class Permissions 
{ 
    [PermissionGroup(PermissionGroupCode.Invoice)] 
    public enum Invoices 
    { 
     CreateInvoice = 1, 
     UpdateInvoice = 2, 
     RemoveInvoice = 3, 
     ManageAttachments = 4 
    } 

    [PermissionGroup(PermissionGroupCode.UserAccounts)] 
    public enum UserAccounts 
    { 
     Create = 1, 
     ChangePassword = 2 
    } 
} 

public enum PermissionGroupCode 
{ 
    Invoice = 1, 
    UserAccounts = 2, 
    Members = 3 
} 

/***************** Attributes & ActionFilters *****************/ 

[AttributeUsage(AttributeTargets.Enum)] 
public class PermissionGroupAttribute : Attribute 
{ 
    private PermissionGroupCode _GroupCode; 
    public PermissionGroupCode GroupCode 
    { 
     get 
     { 
      return _GroupCode; 
     } 
    } 

    public PermissionGroupAttribute(PermissionGroupCode GroupCode) 
    { 
     _GroupCode = GroupCode; 
    } 
} 


public class RequirePermissionAttribute : AuthorizeAttribute 
{ 
    private object _RequiredPermission; 

    public RequirePermissionAttribute(object RequiredPermission) 
     : base() 
    { 
     _RequiredPermission = RequiredPermission; 
    } 

    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     var permissionGroupMetadata = (PermissionGroupAttribute)_RequiredPermission.GetType().GetCustomAttributes(typeof(PermissionGroupAttribute), false)[0]; 

     var groupCode = permissionGroupMetadata.GroupCode; 
     var permissionCode = Convert.ToInt32(_RequiredPermission); 

     return HasPermission(currentUserId, groupCode, permissionCode); 
    } 
} 
0

No creo que eso es posible que traté de hacer lo suyo y no se pudo:/lo siento.

permisos en acciones se debe utilizar con Autorizar y usted puede hacer su propio ovveride escribir algo como esto:

[AttributeUsage(AttributeTargets.All)] 
    public sealed class CustomAuthorizeAttribute : AuthorizeAttribute 
    { 

    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     if (httpContext == null) 
      throw new ArgumentNullException("httpContext"); 

     //Its a piece of code from my app you can modify it to suit your needs or use the base one 
     if (!new CustomIdentity(httpContext.User.Identity.Name).IsAuthenticated) 
     { 
      return false; 
     } 

     return true; 
    } 

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
    { 
     base.HandleUnauthorizedRequest(filterContext); 

    } 

} 

entonces en su acción:

[CustomAuthorizeAttribute(Roles = "FE")] 
public ActionResult Index() 
{ 
    return RedirectToAction("Index", "Documents"); 
} 

sin embargo su todavía una cadena que se usar y para que funcione, debe combinarlo con el proveedor de rol personalizado. Mucho alboroto, pero vale la pena en mi opinión.

+0

sí, lo he hecho, pero mi problema no es la creación de un atributo (atributo ActionFilter) para comprobar Permisos de usuario. Solo necesito una forma mejor (que usar claves simples de cadena) para crear constantes de permisos predefinidas. – sos00

+1

http: //www.vivienchevallier.com/Articles/create-a-custom-authorizeattribute-that-accepts-parameters-of-type-enum Pruebe esto. – AdrianCogiel

Cuestiones relacionadas