2011-12-17 5 views
7

Tratando de gestionar el acceso a un sitio web que crearon algunas entidades necesarias enter image description here¿Es seguro usar reflejos y enumeraciones para el control lógico del acceso a la aplicación MVC?

El objetivo es utilizar un atributo de permiso personalizado para el método de la acción de algún controlador de mi aplicación MVC.

[Permissions(PermissionType.SomePermissionName, CrudType.CanDelete)] 
public ActionResult SomeAction() 
{ 
} 

Para esta operación Tengo dos enumeraciones

[Flags] 
public enum CrudType 
{ 
    CanCreate = 0x1, 
    CanRead = 0x2, 
    CanUpdate = 0x4, 
    CanDelete = 0x8, 
} 

[Flags] 
public enum PermissionType 
{ 
    SomePermissionName = 0x1, 
    //... 
} 

ahora quiero el método siguiente para comprobar los permisos

public static bool CanAccess(RolePermissions rp, CrudType crudType) 
{ 
    var pInfo = rp.GetType().GetProperties(); 
    var res = pInfo.FirstOrDefault(x => x.Name == crudType.ToString()); 
    if(res != null) 
    { 
     return Convert.ToBoolean(res.GetValue(rp, null)); 
    } 
    return false; 
} 

Funciona bien, pero ¿es seguro utilizar la reflexión aquí? ¿Es un buen estilo?
Una pregunta más se trata dicha pieza de código

var permission = PermissionService.GetByName(permissionType.ToString()); 

Aquí estoy tratando de conseguir un objeto de permiso de una base de datos utilizando alguna llamada constante del PermissionType enumeración.
En ambos casos, el trabajo correcto depende de las relaciones entre las enumeraciones y algunos campos o registros de la tabla. Por otro lado, tengo un buen mecanismo para controlar la lógica (como me parece). ¿Es esa una buena manera?

+0

¿Esto no está disponible en ASP.NET Membership APi? –

+1

Realmente no me gusta la membresía.Además me gustaría usar mis propias clases, tablas propias, control propio, etc. – Shymep

+0

¿Alguna razón que no te gusta, aparte de las clases propias, tablas propias, controles propios? Cuando estaba pensando en pasar a Membresía APi :( –

Respuesta

3

otra edición
En su caso, tendría sentido para crear una propiedad de sólo lectura para la clase ExistingPermissionsRolePermissions, y hacer la fusión de las cuatro booleanos en una CrudType dentro de esa propiedad de captador. Entonces solo puede hacer rp.ExistingPermissions.HasFlag(permissionToCheck).

EDITADO

Gracias a @DevDelivery para señalar el tema - buena captura. Lamentablemente, la solución fija no es tan bonita como esperaba, por lo que en este caso podría tener sentido seguir el enfoque de @ DevDelivery.

Puesto que usted tiene sus CrudType como "campos de bits", se puede utilizar un enfoque más limpio (menos código y una mejor legibilidad):

public static bool CanAccess(RolePermissions rp, CrudType permissionToCheck) 
{ 
    CrudType existingPermissions = 
           SetPermissionFlag(CrudType.CanCreate, rp.CanCreate) | 
           SetPermissionFlag(CrudType.CanRead, rp.CanRead) | 
           SetPermissionFlag(CrudType.CanUpdate, rp.CanUpdate) | 
           SetPermissionFlag(CrudType.CanDelete, rp.CanDelete); 

    return existingPermissions.HasFlag(permissionToCheck); 
} 

public static CrudType SetPermissionFlag(CrudType crudType, bool permission) 
{ 
    return (CrudType)((int)crudType * Convert.ToInt32(permission)); 
} 

La desventaja en comparación con su solución es que usted tendrá que modificar este método en caso de que agregue más operaciones (al CanRead existente, etc.).

+1

¡¡Es increíble !!! – Shymep

+0

El problema aquí es que las propiedades RolePermission son booleanas. Orientar un grupo de booleanos simplemente te dará otro booleano. – DevDelivery

+0

@DevDelivery - buena captura, eso no funcionaría de hecho. Parece que la solución no es tan bonita después de la solución. – Yakimych

1

El uso de la reflexión tiene un impacto en el rendimiento y el enlace tardío significa que el compilador no captará el cambio del nombre de una enumeración o de la propiedad.

Además, este código es muy difícil de entender, por lo tanto, es difícil de mantener.

Aquí solo hay 4 opciones para verificar. Una declaración simple de cambio es más fácil, más rápida y más limpia.

Usar el reflejo tendría sentido si estuviera tratando de permitir cambios en la base de datos o que los componentes de terceros introduzcan nuevos permisos.

Cuestiones relacionadas