Artículo Bases de Datos Seguras
Autor / Fuente Harvey Triana
Tema Bases de datos
Creado Junio 28 de 1998

Bases de Datos Seguras

Descripción y código Visual Basic para el modelo de seguridad MS Jet


zap_fs.jpg (38244 bytes)
Asegurar los datos es cosa seria...


Una paso fundamental para crear un software de base de datos para entornos multiusuario es implantar un sistema de seguridad. Conozco aplicaciones bastante sofisticadas que usan un sistema de seguridad completamente programado, incluso he tenido intensiones de crear mi propio sistema. Sin embargo, el éxito de emplear los servicios que ofrece Microsoft es excelente y francamente difícil de superar. El sistema de seguridad MS-Jet esta bien diseñado y no ha sufrido evolución sustancial desde MS Access 2.0©. Sin embargo desde el punto de visual Basic las cosas parecen complicadas, inclusive para programadores con recorrido -¿Por qué?, Quizá la razón es que la concepción debe partir de Access y no de Visual Basic. Una vez más: Visual Basic no es una aplicación administradora de bases de datos, es una aplicación para accesar datos y suministrar interfaces especiales.

Este articulo tratara los principales puntos sobre el código Visual Basic que se aplica al servicio de una base de datos asegurada. Tomaré como punto de partida de que el programador que lee este articulo tiene cierto conocimiento de que es una base de datos del sistema, como crearla, y como mantenerla con MS Access. Si desconoce este tema es importante leer el capitulo Protección de la Aplicación, en el manual Creación de aplicaciones que vienen con Microsoft Access (cualquier versión es útil).


Creación del Sistema de Seguridad

Básicamente, el sistema de MS-Jet tiene como misión una protección al estilo de Red corporativa. Los usuarios son obligados a identificarse y escribir una contraseña cuando inician MS-Access o una Aplicación que usa la Base de Datos protegida. La seguridad se basa en permisos, los cuales son atributos para un grupo o usuario. Por ejemplo, a un grupo particular de usuarios se les permita visualizar, introducir o modificar datos en una tabla Clientes, pero no se les permita cambiar el diseño de esa tabla, ni accesar otras tablas. Así un usuario que pertenezca a este grupo sólo tendrá estos atributos y, en particular, los que le quiera dar un Administrador. En realidad, la seguridad MS-Jet se extiende no solo a datos, si no en general a todos objetos en una base de datos Jet, tales como Formularios, Reportes, Consultas, etc.

El Anexo 1 de este documento es un resumen describe los pasos para asegurar una Base de Datos MDB con MS Access.


Accesar con Visual Basic

Visual Basic es una herramienta sumamente potente para accesar datos, de hecho no tiene restricciones (como OBDC puede utilizarse en conjunto con DAO, es posible utilizar virtualmente cualquier sistema de bases de datos). Visual Basic tiene la capacidad de administrar al sistema de seguridad de cuentas en su plenitud, sin embargo es algo complicado dado la gran cantidad de objetos y el manejo que estos requieren. Trataré por separado los diferentes temas de manera escalonada. Estimo ser didáctico.

Tenga en cuenta los siguientes parámetros del ejemplo:

Parámetro

Información

Variable / Objeto

Base de Datos Asegurada miDB.mdb miMDB
Base de Datos del Sistema SysAdmin.mdw miMDW
Objeto de Base de Datos dbMain dbMain
Administrador Admin miUsuario
Contraseña de Administrador admin1 miClave

 

  1. Apertura de una Bases de Datos Asegurada

En su manera más simple abrimos con el Workspace predeterminado, es decir, DBEngine.Workspaces(0) o simplemente DBEngine(0), es:

    With DBEngine
        .SystemDB = miMDW
        .DefaultUser = miUsuario
        .DefaultPassword = miClave
    End With
    Set dbMain = DBEngine(0).OpenDatabase(miMDB)
    ...

 Con un espacio de trabajo Workspace definido en tiempo de ejecución:

   Dim ws As Workspace
   DBEngine.SystemDB = miMDW
   Set ws = DBEngine.CreateWorkspace("miWS", miUsuario, miClave)
   Set dbMain = ws.OpenDatabase(miMDB)

Empleamos Workspace para tareas como Transacciones, con el objetivo de emplear espacios de trabajo diferentes. Importante en bases de datos remotas y de trabajo pasado.

Observe la tercera línea del ejemplo (Set ws = ...), el nombre del Workspace creado es #Default Workspace# y no «miWs» como se especifica en los parámetros de CreateWorkspace. La razón es que este es el nombre del Workspace predeterminado que pasa a ser del usuario que inicio la sesión. Para hacer referencia al Workspace por su nombre tendríamos que agregarlo a la colección WorkSpaces con:

DBEngine.Workspaces.Append ws

Así podremos usar Workspaces(miNombre); por ejemplo, sería valido:

DBEngine.Workspaces("miWS").OpenDatabase(miMDB).

Abrir una base de datos en un entorno mutiusuario debe hacerse con un procedimiento bien elaborado con todas las capturas de error posibles, es decir, nunca omita la línea On Error Goto Label en procedimientos que acceden una base de datos multiusuario.

medieval.gif (1144 bytes) Una buena estrategia de una aplicación que usa una base de datos multiusuario es emplear un objeto Database global (public), el cual se abre al iniciar la aplicación y cierra al terminar la aplicación. Los resultados se traducen en optimo rendimiento. En mis aplicaciones uso dos procedimientos personalizados: OpenMainDatabase y CloseMainDatabase; el primero al iniciar la aplicación y el segundo antes de terminar la aplicación, es decir, antes de End.


Administrar con Visual Basic

Realmente administrar completamente la seguridad MS-Jet con Visual Basic es una tarea titánica y deberíamos de mantenernos al nivel requerido y compartir la tarea con MS-Access. Realmente es difícil sostener esta apreciación porque frecuentemente se requiere mayor capacidad Visual Basic de dominio sobre el sistema. Podemos administrar en un cien por cien la seguridad MS-Jet con Visual Basic, pero estiramos programando partes de MS-Access, cosa que por demás especializada, requiere mucho empeño y trabajo. Seré franco, los sistemas multiusuario que he desarrollado (o hemos desarrollado en equipo) se ataca con dos frentes: Visual Baisc y Access. Visual Basic lo empleamos para controlar el acceso a datos, mientras que la concesión de permisos, creación y organización Usuarios-Grupos, se logra fácilmente desde Access. No obstante, daré unas pautas de lo que se debe hacer en Visual Basic para alcanzar un nivel de administración sobre la seguridad.

La administración en informática la podemos centrar en dar niveles de autorización a usuarios para acceder a un sistema. Una sistema de seguridad MS-Jet se perfila en este mismo sentido. Primero que todo, planeamos unos pocos grupos con niveles específicos. Desde el punto de vista básico, generalmente clasificamos en Visitantes (solo pueden consultar y generar reportes), Digitadores (ingresan datos en niveles específicos), Jefes de Proyecto (crean los niveles primarios de ingreso a datos), y Administradores (personalmente no considero práctico un grupo Administradores como lo menciono más adelante). Dependiendo de las exigencias de los datos, se generaran más grupos intermedios.


Crear Grupos y Usuarios

Después de tener una organización básica de la jerarquía de permisos para la(s) base de datos (en papel), si es requerido, podemos crear los Grupos y asignarles sus permisos correspondientes, y luego creamos los usuarios pertinentes a cada grupo. Con Visual Basic creamos un grupo a través del método CreateGroup

Set grp = objeto.CreateGroup (nombre, pid)

Puede utilizar el método CreateGroup para crear un objeto Group nuevo para un User o Workspace (según parámetro Objeto).

Pocas veces, o si no mal recuerdo nunca (en el ámbito de gestión), he creado grupos con Visual Basic. Mientras que la creación de usuarios y asignación a grupos Visual Basic tiene un perfil útil y de cierta manera ágil, comparado a seguir los cuadros de dialogo de Access.

La base de datos MDW suministra unos grupos básicos que dependiendo de la estrategia que planeamos, podemos o debemos usar. Por ejemplo, todos los usuarios nuevos deberán ser miembros por lo menos del grupo Users, aunque parezca una redundancia (User a Users), es algo que debemos hacer. Esto se debe a que Users tiene privilegios intrínsecos en el sistema (recuerde que un paso de asegurar una base de datos es recortar autorizaciones a este grupo). Luego que un usuario pertenece a Users, podemos hacerlo pertenecer a un grupo personalizado (p.e. Administradores o Invitados). Hacer pertenecer un usuario al grupo Administradores realmente no tiene sentido práctico, dado que es suficiente con un administrador, además, aparte del Administrador predeterminado admin los privilegios de administración son pobres (he realizado pruebas para comprobar esto). Así, que para ser prácticos usemos como administrador la cuenta predeterminada admin (por supuesto que debe poseer contraseña y por seguridad, cambiarla de vez en cuando).

El siguiente procedimiento crea un usuario y lo anexa a un grupo en particular:

'//------------------------------------------------------------
'// Registrar Usuario
'//------------------------------------------------------------
Private Sub RegistrarUsuario _
    ( _
    Nombre As String, Grupo As String, Contraseña As String _
    )
    Dim ws     As Workspace
    Dim usrNew As User
    Dim usrTem As User
    Dim grp    As Group
    
    Randomize Timer
    On Error GoTo RegistrarUsuario_Err

    DBEngine.SystemDB = miMDW
    Set ws = DBEngine.CreateWorkspace("", "Admin", "admin", dbUseJet)
    
    With ws
        Set usrNew = .CreateUser(Nombre)
        usrNew.PID = Nombre & Int(1000 * Rnd)
        usrNew.Password = Contraseña
       .Users.Append usrNew
        
        '//Debemos agregarlo a Users para heredar sus permisos
        Set grp = .Groups("Users")
        Set usrTem = grp.CreateUser(usrNew.Name)
        grp.Users.Append usrTem
        
        '//Lo agrego al grupo que deseo y hereda sus permisos
        Set grp = .Groups(Grupo)
        Set usrTem = grp.CreateUser(usrNew.Name)
        grp.Users.Append usrTem
       
    End With
    ws.Close
    Exit Sub
    
CrearUsuario_Err:
    '//Tratamiento de errores
End Sub


Asignar Permisos

Desde una perspectiva práctica, no me preocupo porque al grupo al cual voy a anexar el usuario en particular me suministra las autorizaciones necesarias. Conceptualmente Las Autorizaciones representan un gran árbol lógico en el cual es fácil perderse. Más aun cuando Access aplica autorizaciones a su nivel de objetos, es decir, Formularios, Reportes, Consultas, Macros y Módulos. Desde Visual Basic solo aplican las Autorizaciones para Base de Datos, Tablas y Consultas (aunque esta afirmación tiene límite cuando deseamos accesar con Automatización OLE). Como cada tabla y cada consulta pueden tener autorizaciones particulares, hace del tema de asignación de permisos una tarea ardua sin apoyarse en Grupos.

Tenga en cuanta que los permisos se heredan de una manera lógica, por ejemplo, el permiso de Actualizar dará permiso de Lectura.

Si voy a suministrar un permiso extra, tendré que definir sobre que objeto se dará el permiso y el permiso en particular (dado por una contante Visual Basic).

Ejemplo, deseo dar permiso al usuario Pepe para que inserte datos en la tabla miTabla, de la base de datos miBD:

Dim db  As Database
Dim doc As Document

DBEngine.SystemDB = "miMDW"
Set db = OpenDatabase("MiBD")
Set doc = db.Containers("Tables").Documents("miTabla")

With doc
    .UserName = "Pepe"
    .Permissions = dbSecRetrieveData
     '//Verificación
     If (.Permissions And dbSecInsertData) = dbSecInsertData Then
        '//Puede insertar datos."
     Else
        '//No puede insertar datos."
    End If
End With
db.Close

Realmente es difícil interpretar o dar lectura a los permisos con Visual Basic, dado los casos en que estos se suman y hacer un seguimiento es imposible (por ejemplo sabes que 7 + 4 es 11, pero 11 puede ser 2 + 9, 5 + 6, etc., aunque realmente no sé sí exista una lógica dentro de esas constantes que evite este declive, pero no voy a investigarlo).


Enumerar Grupos y Usuarios

Para esto si es de especial utilidad con Visual Basic, dado que nos permite producir reportes personalizados y enumerar las cosas de tajo. El procedimiento ColecciónContainers() del ejemplo que suministro con este documento es una buena muestra de un reporte del sistema de seguridad.


Monitor a Modo de Ejemplo

Bien, para corroborar los planteamientos y dar una base tangible a mis lectores, aunque no sea la más formal, suministro un monitor a modo de ejemplo para que se ejecuten ciertos procedimientos y se obtengan conocimiento sobre lo que sucede y de cómo aplicar una manera idónea el código.

DbSecTesting (dbSec.vbp) es un proyecto sencillo, que contiene un Formulario, con una ventana de salida de texto estilo terminal. Presenta un menú simple para ejecutar unas acciones de código referente a seguridad. Se pueden cambiar los valores de las siguientes constantes para ejecutar una prueba sobre su sistema:

Private Const miMDW = "SysAdmin.mdw"
Private Const miMDB = "miDB.mdb"
Private Const miUsuario = "Admin"
Private Const miClave = "admin1"

De resto, para dar una utilidad a las funciones podría eliminar o cambiar por comentario los fprint, y dar retoque a las funciones. Sin embargo, soy franco, el dominio sobre un sistema a de seguridad requiere una extensión considerable del código de ejemplo.

El ejemplo incluye las bases de datos: MIDB.MDB y SYSADMIN.MDW, creadas con Access97 (DAO 3.5). Si desea investigar el sistema de seguridad del ejemplo con Access97 deberá utilizar el programa WRKGADM.EXE y unirse a SYSADMIN.MDW en la ruta donde haya copiado los archivos. Para retornar al grupo predeterminado de Access nuevamente abrimos WRKGADM.EXE y especificamos SYSTEM.MDW en su ruta que generalmente es C:\WINDOWS\SYSTEM\.

Por ultimo, para más información recomiendo la documentación Visual Basic y, su Ayuda y ejemplos aplacados a los diferente objetos sobre el tema.

NOTA. El proyecto dbSecTesting y sus bases de datos pueden ser bajados del magazin Algoritmo del grupo Eidos (buscar por tema o autor).


Anexo 1

Resumen de Pasos para Asegurar una Base de Datos Jet

1. Crear a o unirse a grupo de trabajo. Textualmente, Un grupo de trabajo de Microsoft Access es un grupo de usuarios en un entorno multiusuario que comparten datos. Un Grupo de Trabajo se sirve de un archivo donde se almacenan las cuentas. Puede usar una predeterminado, uno existente o crear uno nuevo. Para esto emplea el Administrador para grupos de trabajo. , Busque el archivo Wrkgadm.exe (Access 2.0 o superior). Finalmente este llamado grupo de trabajo será un archivo especial que se denomina base de datos del sistema y se reconoce por las extensiones MDA y MDW (Access 32Bits)

2. Cree una Cuenta de Propietario y Una de Administrador. Con el Grupo de Trabajo activo, inicie MS Access, abra una base de datos, menú Usuarios, Usuario, del cuadro de dialogo escoja Nuevo, del cuadro de dialogo escriba el Nombre y un ID personal (esta combinación identificara al usuario de aquí en adelante) y Aceptar. Para crear la cuenta de propietario siga las mismas instrucciones. El Administrador administrara el Grupo de Trabajo, el propietario como su nombre lo indica, será el dueño de la base de datos y sus objetos.

3. Activar el procedimiento de inicio de sesión. Una base de datos será protegida cuando el administrador tenga contraseña y tenga Titularidad. Con el Grupo de Trabajo activo, inicie MS Access, abra una base de datos, menú Cambiar Contraseña, Cambiar Contraseña. Siga el cuadro de dialogo. La próxima vez que inicie Access, el cuadro de dialogo Conexión solicitara el nombre de un usuario y su contraseña.

4. Cambie la Titularidad. Inicie la sesión con la cuenta del nuevo Administrador creado anteriormente, Cree una nueva base de datos: menú Archivo, Complementos, Importar Base de Datos. Seleccione el archivo MDB cuya titularidad desea cambiar, y de Aceptar. También puede cambiar la titularidad de un objeto individual, desde los diálogos Cambiar Propietario, pero no desviemos la atención. Valga aclara que las bases de datos creadas desde una sesión de grupo, no necesitan cambiar su titularidad porque la traen de nacimiento.

5. Cree las cuentas de los Usuarios. Cree grupos y usuarios de la siguiente manera. Abra la base de datos, menú seguridad, Grupos o Usuarios, siga los diálogos. Los PID son importantes para el administrador, no para los usuarios, anótelos. Después de creados los usuarios y grupos, puede hacer que un usuario, digamos John, pertenezca a un grupo y así limite sus permisos. Para generalizar, recuerde, la administración de las cuentas se lleva a cabo desde el menú Seguridad, creo que no necesitas memorizar más recetas.

6. Asignar Autorizaciones. Una vez creadas las cuentas, puede asignar autorizaciones a esas cuentas. Menú seguridad, autorizaciones. Importante: la base de datos no estará segura hasta no eliminar las autorizaciones del usuario Administrador y del grupo Usuarios (cuentas predeterminadas de Access). En realidad la administración de autorizaciones es el proceso donde invertirá la mayor parte del tiempo (la lógica de autorizaciones se aprende ensayando). Tenga presente en autorizaciones no solo a las tablas, también a las consultas, módulos y formularios.


7. Asignar Contraseñas

Al fin llegamos al paso fácil. Asígnele una contraseña a cada uno de sus usuarios. Es más rápido con código Visual Basic. Con Access, tiene que iniciar Access con cada cuenta, ir al menú Seguridad, Cambiar Contraseña y asignar la contraseña. Si un usuario no tiene contraseña, cualquiera puede entrar con el nombre de ese usuario, en ese momento la contraseña es una cadena vacía. Un usuario puede cambiar su contraseña en el momento que lo desee.

Otro nivel es la codificación de la base de datos, pero aun no he llegado a este extremo. Es útil para protegerse de extraterrestres (hackers sí quiere). No es difícil, pero de cuidado. Desde el menú Archivo, seleccionamos Codificar/Decodificar base de datos y seguimos los diálogos.


Harvey Triana
Derechos Reservados. Autorización solo para programación