2009-06-26 7 views
5

En mi aplicación típica, el usuario hace clic en un botón en una página aspx, invoca un objeto comercial C# y luego ejecuta un procedimiento almacenado.¿En qué parte de la pila de llamadas deben realizarse las comprobaciones de roles?

¿Se deberían realizar controles de roles en la parte superior de la pila, en la parte inferior de la pila o en todos los niveles? Parece que si un usuario malintencionado puede invocar un método, podría invocar alguno, por lo que para una seguridad efectiva, necesitaría verificar todos los métodos (y eso es mucho código adicional para escribir).

Aquí está una pila de llamadas típica para ilustrar mi pregunta:

Page_Load() 
{ 
    if(p.IsInRole("Managers")) //or equivalent attribute 
    { 
    AddAccount.Visible =true; 
    } 
} 

AddAccount_OnClick() 
{ 
    if(p.IsInRole("Managers")) //or equivalent attribute 
    { 
    //Add the account 
    Account.Add(...); //and maybe another role check... 
    } 
} 

-- TSQL doesn't understand .NET authorization, this call is in a 'trusted' subsystem 
create proc Add_Account @user, @account_name 
If @user in (Select user from role_table where role='manager') 
-- Add the account 

Respuesta

3

En mi opinión, debe ponerlo lo más cerca posible de los datos. Cuanto más cerca esté de los datos, mejor podrá asegurarse de que no sea posible tomar una ruta indirecta a través de su base de código para eludir un control de acceso.

Ese argumento requeriría que se realizaran comprobaciones de seguridad en la propia fuente de datos, si la admite (como su RDBMS favorito) o la capa de acceso a datos.

Sin embargo, algunas restricciones de seguridad tienen un fuerte olor a lógica de negocios; p.ej. "si el usuario tiene esta función e intenta modificar los datos que cumplen con estas especificaciones, la operación debe permitirse; de ​​lo contrario, no". Eso me parece una política, y algo que pertenece a la capa de lógica de negocios de un motor de reglas separado.

I wrote about something similar in the context of WCF some time ago.

2

colocaría las comprobaciones de acceso en función de los objetos de negocio en realidad llevar a cabo las cosas potencialmente peligrosas/sensibles.

Agregar la verificación de roles a la carga de la página y los eventos de clic de botón serían extraños, en mi humilde opinión. Además, si va a proteger la página, proteja la página mediante las directivas de ubicación declarativa en su web.config ... p. ponga todas sus páginas de "administrador" en una carpeta separada y proteja la carpeta completa, de manera declarativa.

Pero, siempre debe tener los controles en sus métodos de objetos comerciales, como mínimo.

2

Debe ponerlo en el nivel de método. No puede suponer que llegue a ese método de ninguna manera específica. Ese método puede ser llamado por el manejador de botones o puede llamarse en código normal como resultado de cualquier tipo de lógica. ¿Cuántas veces ha visto algo como esto llamando a un manejador de botones ...

private void MyBypassingCall() 
{ 
    if(myLogic) 
    { 
    AddAccount_OnClick(); 
    } 
} 

Por lo tanto, ponerlo en Page_Load no es suficiente. También debería verificar la decoración del método con un PrincipalPermissionAttribute. Eso reduce mucho código.

1

Objetos comerciales.

Pero en tiempo de construcción. Deje que cada instancia capture un rol muy específico.

Editar: Más sucinta de esta manera.

2

Esto es solo un comentario anecdótico sobre lo importante que puede ser hacer una validación de seguridad en el aspecto comercial. No fue lo suficientemente bueno en nuestro caso para ser optimistas sobre las bajas expectativas de piratería de solicitudes. No teníamos ningún tipo de validación en nuestros objetos comerciales y nos quemamos de forma inesperada. Un cliente creó una secuencia de comandos para automatizar el uso de nuestro sitio. Terminó siguiendo los enlaces esperados en su script que en realidad no se procesaron. Terminó corrompiendo datos. Por supuesto, esto es más un problema de estado del sistema y de integridad de datos para nosotros que una violación de seguridad, pero supongo que ambos se aplican realmente.

3

Desde una perspectiva de implementación, sería la mejor solución implementar las comprobaciones en la medida de lo posible porque hay la menor cantidad de funciones que requieren protección, de ahí la menor cantidad de errores y todos los usuarios las entradas tienen que pasar a través de la capa protegida. Si su base está protegida, no necesita preocuparse por todo lo que se basa en esa base.

Esta solución tiene un inconveniente obvio: la interfaz de usuario no sabe nada de autenticación, autorización, verificación de datos y todo lo demás. Por lo tanto, cada entrada desciende de la pila, puede causar un error y sube la pila nuevamente para informar al usuario. Esto causará una experiencia de usuario desagradable porque los errores que podrían detectarse fácilmente en la interfaz de usuario solo se detectan después de pasar los datos a los sistemas de fondo.En consecuencia, agregará muchas verificaciones a la interfaz del usuario, también, para brindar una mejor experiencia al usuario.

Si utiliza la programación basada en interfaz, esto no es un problema en absoluto, porque puede compartir el código de verificación entre las capas de la aplicación. Esto le permite agregar fácilmente código de verificación a todas las capas de aplicación y esto le dará una defensa en profundidad: un error en una capa de aplicación puede ser capturado por otra capa. Por supuesto, si el código de verificación en sí mismo es erróneo y lo compartes a través de las capas de aplicación, es probable que el error y el error pasen por todas las capas de la aplicación.

Cuestiones relacionadas