Jueves, 21-Sep-17, 12:18 PM
Le saludo Visitante | RSS
Menú del sitio
Búsqueda

byronlcl, Access y algunas cosillas...

Seguridad en Access 3

Páginas de este artículo:  1  2  3

9.13 Funciones útiles
íFelicitaciones!
En este punto ya sabes como operar los permisos, y como ya te aprendiste todo muy bien, ya podemos empezar a simplificar el código y crear nuestros procedimientos:
 
Function ExistePermisoEnObjeto(ByVal strContainer, _
                               ByVal strDocument As String, _
                               ByVal strUsuarioGrupo As String, _
                               ByVal lngPermiso As Long) As Boolean
'Byron Contreras - byronlcl@gmail.com - 2,009
'.............................................
Dim db As DAO.Database
   Set db = CurrentDb
   With db.Containers(strContainer).Documents(strDocument)
      .UserName = strUsuarioGrupo
      If (.Permissions And lngPermiso) Then ExistePermisoEnObjeto = True
   End With
   Set db = Nothing
End Function
 
Function ExistePermisoCrearObjetos(ByVal strContainer, _
                                   ByVal strUsuarioGrupo As String) As Boolean
'Byron Contreras - byronlcl@gmail.com - 2,009
'.............................................
Dim db As DAO.Database
   Set db = CurrentDb
   With db.Containers(strContainer)
      .UserName = strUsuarioGrupo
      If (.Permissions And dbSecCreate) Then ExistePermisoCrearObjetos = True
   End With
   Set db = Nothing
End Function
 
Sub AgregarPermisoEnObjeto(ByVal strContainer, _
                           ByVal strDocument As String, _
                           ByVal strUsuarioGrupo As String, _
                           ByVal lngPermiso As PermissionEnum)
'Byron Contreras - byronlcl@gmail.com - 2,009
'.............................................
Dim db As DAO.Database
   Set db = CurrentDb
   With db.Containers(strContainer).Documents(strDocument)
      .UserName = strUsuarioGrupo
      .Permissions = .Permissions Or lngPermiso
   End With
   Set db = Nothing
End Sub
 
Sub PermitirCrearObjetosNuevos(ByVal strContainer, _
                               ByVal strUsuarioGrupo As String, _
                               ByVal Permitir As Boolean)
'Byron Contreras - byronlcl@gmail.com - 2,009
'.............................................
Dim db As DAO.Database
   Set db = CurrentDb
   With db.Containers(strContainer)
      .UserName = strUsuarioGrupo
      If Permitir Then
         .Permissions = .Permissions Or dbSecCreate
      Else
         .Permissions = .Permissions And Not dbSecCreate
      End If
   End With
   Set db = Nothing
End Sub
 
Sub EliminarPermisoEnObjeto(ByVal strContainer, _
                            ByVal strDocument As String, _
                            ByVal strUsuarioGrupo As String, _
                            ByVal lngPermiso As PermissionEnum)
'Byron Contreras - byronlcl@gmail.com - 2,009
'.............................................
Dim db As DAO.Database
   Set db = CurrentDb
   With db.Containers(strContainer).Documents(strDocument)
      .UserName = strUsuarioGrupo
      .Permissions = .Permissions And Not lngPermiso
   End With
   Set db = Nothing
End Sub
 
Function ObtenerPropietarioObjeto(ByVal strContainer, _
                                  ByVal strDocument As String) As String
'Byron Contreras - byronlcl@gmail.com - 2,009
'.............................................
Dim db As DAO.Database
   Set db = CurrentDb
   ObtenerPropietarioObjeto = db.Containers(strContainer).Documents(strDocument).Owner
   Set db = Nothing
End Function
 
Sub CambiarPropietarioObjeto(ByVal strContainer, _
                             ByVal strDocument As String, _
                             ByVal strUsuario As String)
'Byron Contreras - byronlcl@gmail.com - 2,009
'.............................................
Dim db As DAO.Database
   Set db = CurrentDb
   db.Containers(strContainer).Documents(strDocument).Owner = strUsuario
   Set db = Nothing
End Sub
 
Sub QuitarTodosLosPermisos(ByVal strUsuarioGrupo As String)
'Byron Contreras - byronlcl@gmail.com - 2,009
'.............................................
Dim db As DAO.Database
Dim cont As DAO.Container
Dim doc As DAO.Document
   On Error Resume Next
   Set db = CurrentDb
   For Each cont In db.Containers
      'permisos en los objetos
      For Each doc In cont.Documents
         doc.UserName = strUsuarioGrupo
         doc.Permissions = dbSecNoAccess
      Next doc
      'permisos para objetos nuevos
      cont.UserName = strUsuarioGrupo
      cont.Permissions = dbSecNoAccess
   Next cont
   Set db = Nothing
End Sub
 
Sub AsignarTodosLosPermisos(ByVal strUsuarioGrupo As String)
'Byron Contreras - byronlcl@gmail.com - 2,009
'.............................................
Dim db As DAO.Database
Dim cont As DAO.Container
Dim doc As DAO.Document
 
   On Error Resume Next
   For Each cont In db.Containers
      'permisos para objetos nuevos
      cont.UserName = strUsuarioGrupo
      cont.Permissions = dbSecFullAccess
      'permisos en los objetos
      For Each doc In cont.Documents
         doc.UserName = strUsuarioGrupo
         doc.Permissions = dbSecFullAccess
      Next doc
   Next cont
   Set db = Nothing
End Sub
 
 
9.14 ¿Cómo Puedo Abrir Una Base De Datos Definida Con Seguridad Por Usuarios?
Eso depende que quieras hacer con la base de datos, puedes tener dos intenciones:
   - Acceder a los datos (tablas y consultas)
   - Automatizar la base de datos, es decir, tener acceso también a los objetos como reportes, formularios, macros, módulos, barras de herramientas, etc.
 
Abrir Base De Datos Y Acceder A Los Datos (Tablas Y Consultas)
Puedes usar el siguiente procedimiento:
 
Sub DAO_AbrirBaseDatosSegura()
'Byron Contreras - byronlcl@gmail.com - 2,009
'.............................................
On Error GoTo Err_Procedimiento
Dim strArchivoMDB As String
Dim strContraseñaBD As String
Dim dbe As DAO.DBEngine
Dim db As DAO.Database
 
   'Definir datos de apertura...
   strArchivoMDB = "Archivo de base de datos .mdb"
   strContraseñaBD = "Contraseña de la base de datos"
   'Crear una nueva instancia del objeto DBEngine (Motor de base de datos Microsoft Jet)
   Set dbe = New DAO.DBEngine
   dbe.SystemDB = "Ruta completa archivo de grupo de trabajo .mdw"
   dbe.DefaultUser = "Nombre del usuario"
   dbe.DefaultPassword = "Contraseña del usuario"
 
   'abrir la base de datos
   Set db = dbe.OpenDatabase(strArchivoMDB, False, False, "MS Access;PWD=" & strContraseñaBD)
 
   MsgBox "Base de datos abierta: " & vbCrLf & db.Name, _
          vbInformation, _
          "Operación exitosa!"
 
   db.Close
 
Salir_Procedimiento:
   Set db = Nothing
   Set dbe = Nothing
   Exit Sub
 
Err_Procedimiento:
   MsgBox Err.Description, vbCritical, "Error número " & Err.Number
   Resume Salir_Procedimiento
End Sub
 
 
Abrir Base De Datos Y Automatizarla
Puedes usar el siguiente procedimiento:
 
Sub Shell_AbrirBaseDatosSegura()
'Byron Contreras - byronlcl@gmail.com - 2,009
'.............................................
'Procedimiento que abre una base de datos definida con Seguridad Por Usuarios _
y devuelve el objeto Application para poder automatizarlo
'El procedimiento no funciona si existe contraseña de base de datos
On Error GoTo Err_Procedimiento
Dim strArchivoEXE As String
Dim strArchivoMDB As String
Dim strArchivoMDW As String
Dim strUsuario As String
Dim strContraseña As String
Dim aplAccess As Access.Application
Dim strShell As String
 
   'Definir datos de apertura...
   'Archivo ejecutable de Microsoft Access
   strArchivoEXE = SysCmd(acSysCmdAccessDir) & "MSACCESS.exe"
   strArchivoMDB = "Archivo de base de datos .mdb"
   strArchivoMDW = "Archivo de grupo de trabajo .mdw"
   strUsuario = "Nombre de usuario"
   strContraseña = "Contraseña del usuario"
 
   'Construir la cadena para la función Shell
   strShell = """" & strArchivoEXE & """" & " " & _
              """" & strArchivoMDB & """" & " " & _
              "/User " & strUsuario & " " & _
              "/Pwd " & strContraseña & " " & _
              "/NoStartup " & _
              "/Wrkgrp " & """" & strArchivoMDW & """"
 
   'Si la función Shell tiene éxito tomamos el archivo/objeto(aplicación Access)
   If Shell(strShell, vbHide) Then
      'A veces el archivo tarda en abrir. Si GetObjet no lo encuentra
      'nos dará error, entonces lo metemos a un bucle hasta que lo encuentre
      Do
         On Error Resume Next
         Set aplAccess = GetObject(strArchivoMDB)
         DoEvents
      Loop Until Err.Number = 0
   End If
   MsgBox "Proyecto abierto: " & aplAccess.CurrentProject.Name, _
          vbInformation, _
          "Operación exitosa!"
 
   'Acceso a datos:
   'aplAccess.CurrentDB...
 
   aplAccess.Quit
 
Salir_Procedimiento:
   Set aplAccess = Nothing
   Exit Sub
Err_Procedimiento:
   MsgBox Err.Description, vbCritical, "Error número " & Err.Number
   Resume Salir_Procedimiento
End Sub
 
 
9.15 ¿Cómo valida Access los permisos?
Cuando creas un usuario nuevo, tienes que asignarle un ID. Este ID queda guardado en ambos archivos, en el Grupo de trabajo y en tu base de datos, este ID es el que realmente cuenta todo el tiempo.
Cuando ingresas a la base de datos proporcionas un nombre de usuario y contraseña, con estos datos Access recupera el ID del usuario internamente, luego va al archivo de grupo de trabajo y revisa si el nombre del usuario y el ID corresponden, de allí Access determinará si eres un usuario válido ó no.
Esto es lógico, porque imagínate que en tu base de datos tienes un usuario llamado "Byron Contreras" con su respectiva contraseña, este usuario tiene permisos completos sobre todo. Alguien podría intentar crear un nuevo grupo de trabajo y agregar un usuario llamado también "Byron Contreras" y que no tenga contraseña, luego puede intentar abrir la base de datos mencionada con este nuevo grupo de trabajo, esperando poder entrar con el usuario "Byron Contreras" y sin contraseña. Esto no es posible porque al crear el usuario en ambos grupos de trabajo se les asignó un ID diferente, y por lo tanto no hay permiso de ingreso.
Si alguien conociera el ID con el que "Byron Contreras" fue ingresado en el grupo de trabajo original, si le funcionaría el truco, porque en el nuevo grupo de trabajo crearía al usuario "Byron Contreras" con el mismo ID.
Esto es importante entenderlo porque:
¿Qué pasaría si alguien por error te borra el archivo de grupo de trabajo?
Si tienes debidamente guardados los ID y nombres de los usuarios y grupos, solo creas un nuevo grupo de trabajo con esos datos.
Si no tienes guardada esa información es casi seguro que pierdes tu base de datos porque no habrá como accesar a ella.
¿Has pensado como se manejan los permisos entre bases de datos creadas en diferentes máquinas?, ¿Por qué puedo abrir tus bases de datos y tu las mías?
La respuesta es simple, si recuerdas, Access trabaja predeterminadamente con el grupo de trabajo "System.mdw", que es el mismo en tu máquina y en la mía. Este grupo de trabajo tiene dos usuarios predeterminados "Admin" y "User", los cuales contienen cada uno un ID, que es el mismo también en ambas máquinas.
Si creas un nuevo grupo de trabajo, se crearán estos mismos usuarios y el ID se mantendrá.
Los usuarios Admin y User ya vienen predeterminados y no podemos conocer su ID porque nosotros no los hemos creado, solo la gente de Microsoft sabrá cual es.
Con esto podemos deducir que:
Si tú tienes una base de datos definida con Seguridad por usuarios, al usuario "Admin" le borras la contraseña de ingreso, y además le concedes todos los permisos, casi le estas eliminando la seguridad por usuarios, porque si recuerdas, Access predeterminadamente te ingresa con el grupo de trabajo "System.mdw" y con el usuario "Admin" y sin contraseña, y como el ID del usuario "Admin" es el mismo en ambas bases de datos y grupos de trabajo, te dejará entrar libremente.
 
 
9.16 ¿Cómo Puedo Quitarle La Seguridad Por Usuarios A Una Base de Datos?
Tendrías que seguir los siguientes pasos:
- Ingresar a la base de datos con una cuenta de Administrador
- Asignarle permisos completos de todos los objetos y de la base de datos a los usuarios Admin y User
- Poner como propietario de todo al usuario Admin
- Agregar al usuario Admin al grupo de Admins (Administradores)
- Por último crear una nueva base de datos y desde allí realizar la importación de todos los objetos
Aquí te dejo el código:
 
Sub EliminarSeguridadPorUsuarios()
'Byron Contreras - byronlcl@gmail.com - 2,009
'.............................................
'Para correr este procedimiento debes ser miembro del grupo _
de Administradores
On Error Resume Next
Dim db As DAO.Database
Dim i As Integer
Dim strUsuarioGrupo As String
Dim cont As DAO.Container
Dim doc As DAO.Document
Dim usr As DAO.User
   Set db = CurrentDb
   'asignarle todos los permisos al usuario Admin y al grupo Users,
   'poner como propietario de todos los objetos al usuario Admin
   For i = 1 To 2
      strUsuarioGrupo = IIf(i = 1, "Admin", "Users")
      For Each cont In db.Containers
         'objetos nuevos
         cont.UserName = strUsuarioGrupo
         cont.Permissions = dbSecFullAccess
         'objetos existentes
         For Each doc In cont.Documents
            doc.UserName = strUsuarioGrupo
            doc.Permissions = dbSecFullAccess
            If strUsuarioGrupo = "Admin" Then doc.Owner = strUsuarioGrupo
         Next doc
      Next cont
   Next i
   'agregar al usuario Admin al grupo Admins
   With DBEngine.Workspaces(0).Groups("Admins")
      Set usr = .CreateUser("Admin")
      .Users.Append usr
      .Users.Refresh
   End With
   Set db = Nothing
End Sub
 
 
9.17 Consultas Con Acceso De Propietario (With OwnerAccess Option)
Existe una opción para que nadie tenga acceso a tus tablas y que a la vez puedan ser actualizadas. Para lograr esto, primero debes quitarle a los usuarios todos los permisos sobre la tabla que deseas proteger, luego debes crear una Consulta de Acción (sobre la tabla) y la defines con With Owner Access Option.
Através de esta consulta cualquier usuario puede modificar la tabla, aunque no tenga ningún permiso sobre la misma. Este tipo de consulta no puede ser modificada por nadie, solo por el propietario (creador). Si un usuario intenta cualquier cosa directamente sobre la tabla los permisos serán denegados.
 
Manualmente:
Crea tu consulta en la vista de diseño, en el área vacía donde se muestran las tablas le das un clic secundario, en el menú desplegable seleccionas "Propiedades", dentro de las propiedades busca por "Permisos de Ejecución", allí escoges "De Propietario"
 
Si estas creando la sentencia SQL:
Crea tu cadena normalmente y al final de la sentencia SQL le agregas WIHT OWNER ACCESS OPTION
 
 
9.18 Para Finalizar
Utilizando la Seguridad Por Usuarios estamos Administrando a nuestros usuarios tal y como Access nos Administra a nosotros
Algunas personas crean sus propias tablas para manejar sus Usuarios, Objetos y Permisos, pero en lo personal me parece que es no aprovechar las herramientas que Access ya nos ha dado, además tienen que volver a inventar lo mismo, y lo que me parece más delicado es que el usuario Admin sigue con los permisos completos, lo cual quiere decir que por automatización podemos abrir esas bases de datos y hacerles lo que deseemos. Tengo un ejemplo que hace eso, demostrar lo vulnerable que pueden ser esas bases de datos con esas condiciones, por ahí se los pongo también...
La seguridad por usuarios funciona completamente en Access 2,003 ó inferior, en Access 2,007 también es compatible pero ya no da la opción de asegurar bases de datos en el formato 2,007, y este es un gran tema de debate...
 
Saludos cordiales,
 
Byron Contreras