Durante unos 10 años, he trabajado en varias aplicaciones internas de clientes de escritorio con almacenes de datos de SQL Server. Raramente comencé estos proyectos, la mayoría son trabajos de adquisición.
Una cosa que parecía constante en todas partes era que había una sola cuenta de usuario global de SQL Server que esta aplicación usaba que le otorgaba permiso para la base de datos común, y sí, en algunas situaciones ingenuas usaba la sa
cuenta de usuario, que generalmente intentaba arreglar cuando era posible .
Realmente no puede ocultar este nombre de usuario y contraseña que la aplicación utiliza para acceder a la base de datos. Por lo general se almacenan en una ini
o config
archivo, o posiblemente al horno en el ejecutable en sí. En todos los casos, son visibles para el usuario si cavan un poco. En un caso, en realidad utilizamos un config
archivo pero lo ciframos, pero, por supuesto, la clave de cifrado tenía que almacenarse en el archivo ejecutable (no éramos ingenuos ante las limitaciones de esto, pero efectivamente evitó que las personas hurgaran lo suficiente como para saberlo). para buscar en los config
archivos).
Todos estos sistemas tenían un sistema de autenticación de usuario integrado en la aplicación, pero, por supuesto, todos se gestionaron a través de la propia aplicación, lo que significa que la información del usuario se almacenó en la base de datos. La aplicación restringió las cosas que podría hacer en función de su nivel de acceso, pero es muy discutible si solo puede conectarse a la base de datos y ejecutar consultas ad-hoc.
Me interesa saber qué hacen otros sistemas para solucionar este problema. Estas son las opciones que conozco:
- Use el mecanismo de seguridad de SQL Server para mantener una lista de usuarios y roles, y hacer que la aplicación de escritorio agregue y elimine usuarios a través de consultas T-SQL.
- En lugar de conectarse directamente a la base de datos, cree algún tipo de servicio web que se ejecute en el servidor y coloque la lógica de autenticación allí. Haga que cada solicitud haga validación de seguridad.
Las primeras opciones son un poco feas porque separas a los usuarios de la base de datos, por lo que los usuarios ya no son entidades de primera clase y no puedes hacer referencia a ellos con relaciones de clave externa, etc.
El segundo parece ser un gran problema de rendimiento y mucho trabajo adicional, además de que no puedes usar fácilmente los mapeadores de ORM como NHibernate (creo).
¿Alguien tiene experiencia con esto? ¿Mejores prácticas?
Editar
Pensando un poco más, ¿puede la autenticación de SQL Server realmente resolver este problema? Por ejemplo, si su usuario debe poder insertar y actualizar los registros de la hoja de tiempo para que pueda editar su hoja de tiempo, no hay forma de que el servidor SQL pueda prohibir el acceso a otras filas en la tabla de detalles de la hoja de tiempo, lo que significa que también puede leer y escribir las hojas de tiempo de otras personas.
Respuestas:
Me temo que agregar una capa de servicio web es probablemente la solución correcta a su problema.
La separación del cliente de la implementación de la base de datos subyacente probablemente también lo ayudará a largo plazo.
Agregar una capa de servicio web no necesariamente tiene que afectar el rendimiento ...
De hecho, con una API adecuada, un servicio web puede mejorar el rendimiento, agrupando múltiples consultas de bases de datos dentro de la LAN del centro de datos, en lugar de requerir múltiples viajes de ida y vuelta a través de la WAN.
Y, por supuesto, una capa de servicio web a menudo se puede escalar horizontalmente y agregar el almacenamiento en caché adecuado a las consultas de su base de datos, tal vez incluso un mecanismo de notificación de cambio.
Una capa de servidor agrega seguridad que no puede garantizar con aplicaciones que se ejecutan en un cliente remoto. Todo lo que se ejecuta en un cliente puede ser "pirateado" y realmente no debe considerarse de ninguna manera confiable. Realmente solo debe poner la lógica de presentación en el cliente y alojar cualquier cosa importante en el hardware que tenga control completo.
No sé acerca de sus aplicaciones, pero mis aplicaciones web están naturalmente divididas en varias capas, con el código de presentación separado de la capa de persistencia por al menos un nivel de lógica empresarial que los mantiene separados. Creo que esto hace que sea mucho más fácil razonar sobre mi aplicación, y mucho más rápido para agregar o modificar la funcionalidad. Si las capas se separan de todos modos, es relativamente fácil mantener la capa de presentación en el cliente y el resto en un servidor bajo mi control.
Entonces, si bien puede resolver sus problemas sin introducir una capa de "servicio web", para cuando haya escrito todos los procedimientos almacenados (o equivalentes) necesarios para completar los huecos en la implementación estándar de seguridad de la base de datos, probablemente sería mejor escribir una aplicación del lado del servidor para la que puede escribir pruebas unitarias adecuadas.
fuente
De manera similar a la respuesta de jmoreno, puede denegar el acceso de un usuario a todo, aparte de los permisos EXECUTE en los procedimientos almacenados, luego aprovechar el encadenamiento de propiedad para que el procedimiento almacenado realice las operaciones requeridas en las tablas.
Ver aquí para más detalles https://msdn.microsoft.com/en-us/library/bb669058(v=vs.110).aspx
Cuando el usuario ingresa su nombre de usuario / contraseña del lado del cliente, los almaceno y los envío como parámetros a cada llamada a un procedimiento almacenado. Luego puede verificarlos con los valores almacenados en una tabla antes de realizar la operación deseada.
Definitivamente no es la última palabra en seguridad, pero podría ser necesario si sus PC tienen inicios de sesión genéricos, lo que limita su capacidad de usar grupos AD para obtener permisos, o si tiene acceso limitado a AD.
fuente
Un enfoque es usar grupos de AD y procedimientos almacenados para limitar lo que el usuario puede hacer; por ejemplo, su hoja de tiempo DB, podría permitir insertar, actualizar y eliminar las horas de los usuarios, pero no permitir la actualización de las horas de nadie más. El motor de la base de datos proporcionaría la identificación del usuario, el usuario no tendría acceso directo a las tablas de la base de datos, solo a los sp que realizaron consultas en función de su identificación de inicio de sesión.
Por supuesto, esto no siempre es factible, pero puede serlo. El mejor enfoque dependerá de sus requisitos y recursos.
fuente
Lo que insinúa como 'servicio web' se llama arquitectura de n niveles . En general, es el camino a seguir en los casos en que es probable que haya problemas de seguridad o configuración (por ejemplo, distribución de una aplicación en muchas oficinas). Sin embargo, no tiene que estar basado en la web. Muchos trabajan con otros protocolos.
Crea un servidor de aplicaciones para actuar como intermediario entre el cliente y la base de datos (y otros recursos). El servidor de aplicaciones maneja su autenticación basada en aplicaciones y realiza acciones en nombre del cliente. De hecho, idealmente no estaría haciendo ningún SQL en su cliente, sino que llama a métodos en el servidor de aplicaciones. El servidor de aplicaciones manejaría toda la manipulación de datos.
Hay una serie de beneficios para el enfoque. No necesita configurar conexiones de base de datos y controladores en clientes. No almacena usuarios de bases de datos, contraseñas y servidores. La configuración de los clientes ni siquiera es necesaria, solo apúntelos en código a la dirección o URL correcta. Además, con la 'lógica' en el servidor de aplicaciones, no tiene que repetirlo cuando desarrolla otras aplicaciones: los diferentes tipos de clientes pueden reutilizar el mismo servidor de aplicaciones.
fuente
La tecnología ha cambiado un poco. Si autentica a cada usuario en la base de datos y usa roles de base de datos, ahora puede usar lo que se llama una vista actualizable para resolver este problema, al menos en SQL Server.
Así es como se vería una vista actualizable para una tabla llamada
SomeTable
donde cada fila de esa tabla está vinculada a un empleado. El empleado debería poder ver las filas vinculadas a ellos, y los miembros de la función de recursos humanos deberían poder ver todas las filas, por ejemplo:Entonces, lo que debe hacer es otorgar permisos de lectura (y posiblemente escritura) en la vista (
vwSomeTable
) a todos los usuarios, y no otorgar permisos en la tabla (SomeTable
).Puedes probar esto así:
... que solo debería devolver sus filas. O:
... que devolverá todas las filas. Tenga en cuenta que necesitará los permisos de ejecución como (suplantación) para hacer esta prueba.
Las vistas son actualizables, por lo que incluso el usuario normal puede hacer esto, siempre que la fila esté vinculada a su
Employee
fila:fuente
El uso de la autenticación basada en certificados es la forma "correcta" de implementar una cuenta sql compartida. El objetivo es eliminar el uso de contraseña para este tipo de cosas.
Actualizar:
Supongo que entendió mal la pregunta. Pensé que tenía que ver con tratar de encontrar una alternativa a poner un nombre de usuario y contraseña de db en la configuración de una aplicación o respaldados en la aplicación misma.
Puede eliminar el problema de administrar las contraseñas en las aplicaciones mediante el uso de certificados del lado del cliente. El certificado en sí no es suficiente, debe tener un sistema de distribución y gestión capaz de realizar operaciones como la revocación del certificado.
Referencia: http://en.wikipedia.org/wiki/Public-key_infrastructure
fuente
Al construir una nueva solución de seguridad de escritorio, optamos por la solución de servicio web que intentaré describir a continuación.
Compilamos los ejecutables de la aplicación de escritorio en un entorno separado de los desarrolladores. Y calcule un HASH a partir de ese ejecutable que se registra en la base de datos.
Un servicio web que proporciona toda la información necesaria para que se ejecute la aplicación, la contraseña de la base de datos, la información de la cadena de conexión, los permisos del usuario, etc.
Utilizamos el inicio de sesión único de DB por aplicación y registramos los detalles del usuario en la base de datos en las variables de sesión para poder auditar los registros.
Una DLL maneja toda la comunicación desde la aplicación de escritorio al servicio web, a la que solo se puede acceder con un token integrado en la DLL.
Para poder obtener la contraseña de la base de datos de la aplicación del servicio web, la DLL calcula el HASH de los llamadores de DLL en tiempo de ejecución y pasa como un parámetro al servicio web que valida el token de DLL y el tiempo de ejecución ejecutable calculó el HASH al registrado cuando se implementó (la aplicación solo está disponible en una única instalación compartida de red).
De esa forma, nos dimos cuenta de que es una buena solución al problema de seguridad que más nos preocupaba y que conocemos algunos defectos de diseño. Estamos casi terminando esta implementación y hasta ahora estamos contentos con los resultados.
Editar: puede reemplazar la idea de hash utilizando firmas digitales y certificados X.509.
fuente