Pregunta

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.

¿Deben realizarse verificaciones 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 cualquiera, por lo que para una seguridad efectiva, necesitaría una verificación de cada método (y eso es mucho código adicional para escribir).

Aquí hay 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
¿Fue útil?

Solución

En mi opinión, debe colocarlo 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 tortuosa a través de su base de código para evitar una verificación de acceso.

Ese argumento requeriría que se realicen verificaciones de seguridad en la fuente de datos, si es compatible (como su RDBMS favorito), o en la capa de acceso a datos.

Sin embargo, algunas restricciones de seguridad tienen un fuerte olor a lógica empresarial; p.ej. " si el usuario está en este rol e intenta modificar datos que cumplan con estas especificaciones, se debe permitir la operación; 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.

Escribí sobre algo similar en el contexto de WCF hace algún tiempo .

Otros consejos

Desde la perspectiva de la implementación, sería la mejor solución para implementar las comprobaciones lo más abajo posible en la pila porque existe la menor cantidad de funciones que requieren protección, por lo tanto, la menor cantidad de cosas para estropear y todas las entradas del usuario tiene que pasar a través de la capa protegida. Si su base está protegida, no necesita preocuparse por todo lo que se construye sobre esa base.

Esta solución tiene un inconveniente obvio: la interfaz de usuario no sabe nada sobre autenticación, autorización, verificación de datos y todo lo demás. Por lo tanto, cada entrada baja de la pila, puede causar un error y vuelve a subir la pila para informar al usuario. Esto provocará 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, también agregará muchas comprobaciones a la interfaz de usuario para brindar una mejor experiencia de usuario.

Si usa programación basada en interfaz, esto no es un problema, ya que puede compartir el código de verificación entre las capas de la aplicación. Esto le permite además agregar fácilmente código de verificación a todas las capas de la aplicación y esto le brindará una defensa profunda: un error en una capa de aplicación puede ser detectado por otra capa. Por supuesto, si el código de verificación en sí mismo es erróneo y lo comparte entre las capas de la aplicación, el error y el error probablemente se verifiquen en todas las capas de la aplicación.

Colocaría las verificaciones de acceso a roles en los objetos comerciales que realmente realizan las cosas potencialmente peligrosas / sensibles.

Agregar la verificación de roles a los eventos de carga de página y clic de botón sería extraño, en mi humilde opinión. Además, si va a proteger la página, proteja la página utilizando las directivas de ubicación declarativas en su web.config ... p. ponga todos sus " admin " páginas en una carpeta separada y proteger la carpeta completa, declarativamente.

Pero, como mínimo, debe tener siempre las verificaciones de sus métodos de objeto de negocio.

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

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

Entonces ponerlo en Page_Load no es suficiente. También debe verificar decorar el método con un PrincipalPermissionAttribute . Eso reduce mucho código.

Esto es solo un comentario anecdótico sobre lo importante que puede ser validar la seguridad en el lado comercial. En nuestro caso, no fue lo suficientemente bueno 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ó un script para automatizar su uso de nuestro sitio. Terminó siguiendo los enlaces esperados en su script que en realidad no se representaron. 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 realmente se aplican.

Objetos comerciales.

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

Editar: más sucinto de esta manera.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top