Gestión de grupos de usuarios
Los desarrolladores siempre nos encontramos con situaciones que no sabemos cómo resolver, o, en el mejor de los casos, resolvemos a medias o mediante algoritmos ineficientes hasta la complejidad.
Muchas veces, por
desconocer las metodologías de programación, o, más sencillamente, por ignorar
el potencial de los lenguajes de programación, nos vemos acorralados frente
a problemas que en muchos casos tienen una solución verdaderamente fácil.
La mayoría nos habremos
preguntado alguna vez: para qué tanta matemática en las carreras informáticas.
Más de uno se habrá preguntado para qué puede servirnos la matemática discreta,
por ejemplo. Y, aunque algunas veces nos disgusta estudiarla, hay que reconocer
que su lógica ayuda a resolver muchisimos aspectos de la programación. En el
presente artículo veremos por qué es así.
Recientemente, me
vi en la tarea de realizar la intranet de una organización mediana. Uno de los
requisitos (como en la mayoría de estas aplicaciones) era la creación de grupos
de usuarios con diferentes niveles de privilegios.
El problema se plantea
a la hora de planificar de qué manera podemos desarrollar un sistema eficiente
para la utilización de grupos de usuarios. Cómo podemos hacer que la aplicación
reconozca los privilegios de cada usuario dependiendo del grupo al que pertenezca.
Por qué utilizar grupos y no darle privilegios a cada usuario en particular?
En el ejemplo, más adelante, veremos por qué.
Es probable que a
simple vista parezca algo sencillo de resolver, porque nuestra lógica resuelve
este tipo de problemas rápidamente. Pero, que tan fácilmente puede hacerlo una
computadora sin nuestra intervención?
Primero, planteemos el problema.
Vamos a suponer que nuestro sistema tiene varias funciones:
- Consulta de datos
- Modificación de datos
- Eliminación de datos
- Alta/Modificación de usuarios
- Eliminación de usuarios
Es probable que algunas
personas resuelvan este problema asignando un número de identifiación a cada
usuario en particular. Por ejemplo, algunos usuarios podrían tener un campo
en su registro con el número 1, correspondiente a los administradores, otros
con el número 2, correspondiente a los operadores, y, por último, con el número
3 los usuarios comunes o invitados. El grupo de Administradores posee todos
los privilegios, el grupo Operadores está autorizado sólo a consultar y modificar
datos, y el grupo Invitados sólo tiene permiso para consultar datos. Según el
número asignado a cada usuario podríamos decirle a la aplicación qué permisos
tiene.
El problema se torna
complejo cuando queremos quitar o añadir un permiso específico a todo un grupo
de usuarios. Por ejemplo, si quisieramos que también los operadores puedan agregar
usuarios, pero, sólo algunos operadores. Es esto sencillo? Si nos detenemos
a pensar un momento, esta situación empieza a complicarse.
Queremos que cinco de nuestros operadores estén autorizados para agregar usuarios,
entonces, le asignamos el número 4 a su registro… tendremos que modificar
la aplicación!
También queremos quitarle una función a todos los usuarios comunes… también
tendremos que modificar toda la aplicación para que reconozca el cambio!
A simple vista está claro que sería mucho más sencillo utilizar grupos con distintos
niveles de privilegios y realizar los cambios directamente sobre el grupo y
no sobre cada uno de los usuarios.
A partir de estas funciones, necesitamos
armar grupos con diferentes permisos para ejecutarlas, por ejemplo:
- Administradores
- Operadores
- Invitados
A toda una serie
de usuarios le asignaremos el identificador 1, correspondiente a los administradores,
y así sucesivamente con los demás.
En este momento podríamos pensar: “Aún seguimos con el mismo problema!”. Y eso
será cierto si no le damos valores a las funciones del sistema.
Para quienes estén habituados al diseño de aplicaciones la respuesta será casi
instantánea: operaciones bit a bit.
Aunque algo complejas para aquellos que no entiendan el sistema binario, las
operaciones bit a bit son una solución eficiente para este tipo de problemas.
Veamos ahora cómo implementarlas.
Necesitamos que cada
grupo de usuario tenga ciertos privilegios sobre las funciones del sistema.
Numerando dichas funciones, podemos decir cuáles de ellas están habilitadas
a un grupo específico. Siguiendo con el ejemplo:
1 – Consulta de datos
2 – Modificación de datos
3 – Eliminación de datos
4 – Alta/Modificación de usuarios
5 – Eliminación de usuarios
Empecemos con los
administradores. Ellos tendrán todas las funciones disponibles. Cómo representar
estos permisos? Lo haremos de la siguiente manera:
El bit
más significativo es siempre el que se encuentra más a la izquierda.
Función:
5 4 3 2 1
Permiso: 1 1 1 1 1
Donde 1 equivale
a autorizado y 0 a no autorizado.
El grupo de operadores
debería tener, entonces, los siguientes valores:
Función:
5 4 3 2 1
Permiso: 0 0 1 1 1
Las últimas dos funciones
no están habilitadas para este grupo.
Por último, para
los usuarios comunes:
Función:
5 4 3 2 1
Permiso: 0 0 0 0 1
Este grupo solo puede
ejecutar la primer función: “Consultar datos”.
Lo interesante de
este modelo es la posibilidad de utilizar operaciones bit a bit para consultar
qué funciones están habilitadas para cada grupo.
En nuestro ejemplo, los administradores, tienen asignados el número binario
11111, que en decimal se representa como 31. Entonces, en el registro del grupo,
deberemos poner como privilegios el valor 31; paciencia, ya veremos por qué.
Ahora, tenemos que asignarles un valor a cada función de la aplicación para
que pueda evaluarse con los privilegios de cada grupo de usuarios.
Veamos la representación decimal de cada número binario en nuestro ejemplo:
Funcion 1: 0 0 0 0 1 = 1
Funcion 2: 0 0 0 1 0 = 2
Funcion 3: 0 0 1 0 0 = 4
Funcion 4: 0 1 0 0 0 = 8
Funcion 5: 1 0 0 0 0 = 16
Esto nos abre la
posibilidad de asignar diferentes niveles a cada grupo de la siguiente forma:
3 – Usuarios : 0 0 0 0 1 = 1
2 – Operadores : 0
0 1 1 1 = 7
1 – Administradores: 1 1 1 1 1 =
31
Ahora, en nuestra
aplicación queremos consultar cuáles privilegios tiene un usuario en particular.
El programa debería verificar a cuál grupo pertence el usuario que quiere ejecutar
la función y a partir de los permisos que tenga el grupo habilitar dicha función.
En pseudocódigo ésta operación sería:
valor_funcion = 4 grupo_usuario = 2 permisos_grupo = 7 si ( 4 está en 7 ) ejecuta funcion sino "No está autorizado para ejecutar esta función" fin si
Para este tipo de operaciones
se utiliza el operador lógico AND. Veamos el mismo
ejemplo a nivel bits:
4
= 0 0 1 0 0 -> Valor de la función
AND
7 = 0 0 1 1 1 -> Valor del grupo de usuario
————–
0 0 1 0 0 = 4
-> Resultado
Este resultado nos
dice que el bit comparado está puesto a 1 en el número consultado.
Veamos un ejemplo en el cual el mismo grupo no está autorizado a ejecutar la
función:
16
= 1 0 0 0 0
AND
7 = 0 0 1 1 1
————–
0 0 0 0 0 = 0
El resultado es 0,
por lo tanto, ese grupo de usuarios no está autorizado a ejecutar la función.
Volviendo al problema, ahora resulta mucho
más sencillo agregar o eliminar privilegios a un grupo: basta con modificar
el estado de un bit en el número asignado. Si ahora quisieramos que el grupo
Operadores tuviese permiso para eliminar usuarios (sólo a manera de ejemplo!)
bastaría con poner el bit correspondiente a 1. Este tipo de operación se realiza
con el operador OR:
7
=0 1 1 1
OR
16 = 1 0 0 0 0
————–
1 0 1 1 1
0 = 23
En un principio puede resultar difícil
comprender las operaciones bit a bit, pero, a medida que van surgiendo situaciones
como la planteada en este artículo, nos damos cuenta que es una solución sencilla
y, sobre todo, eficiente.
Como novato en PHP este problema también se me ha planteado y tuve que resolverlo, asi que, en
un próximo artículo, veremos cómo aplicar estas operaciones con dicho lenguaje.
Hola!
A mí se me ha planteado hace unos meses el mismo problema pero con una salvedad. Necesitaba que, cada uno de los usuarios (más de 150), estuvieran clasificados dentro de un grupo determinado de usuarios. Lo que pasaba es que, el administrador del web tendría la posibilidad de poder modificar los permisos de un usuario en particular. He solucionado el problema creando unos valores predeterminados en una tabla de la BD y creando otra tabla para almacenar los permisos de seguridad para cada opción del web de cada usuario en concreto. Lo he desarrollado en ASP. Si a alguien le interesa el tema escribidme a [email protected].
Un saludo a todos,
Alberto
Muy, pero muy buen articulo ahora esperando el…
Si tienes el codigo en PHP, favor enviar
muy bueno, no todo es html,
El artículo está bueno, pero tiene la limitante de que la cantidad de bits de un número es limitada en una PC, normalmente(32 ó 64), por lo que la cantidad de funciones no pueden pasar de la longitud de un integer o un longint(Piensen en una libreta de direcciones, la cantidad de grupos estaría limitada), el algoritmo se puede extender si se usa la misma idea pero en cadenas de caracteres, claro perdería la comodidad de las operaciones bit a bit.
Voltus
[email protected]
No entendí muy bien la relación que hiciste con la libreta de direcciones, pero esta metodología es para asignar niveles de acceso (o lo que quieras) a distintos grupos (que pueden ser tantos como necesités).
En cuanto a funciones, sí, es limitado, quizás si hicieran falta más funciones o niveles de acceso habría que recurrir a una BD.
Siguiendo la siguiente ecuación:
decimal = 2^x-1
donde x es la cantidad de niveles de acceso que querés, podrías tener hasta 53, lo cual está bien para un sistema mediano.
Saludos y gracias por la crítica.
Aleph… Maestro!!!
Excelente articulo, contiene una lógica que no se puede discutir, además el ejemplo no podría haber sido mejor. Es super práctico y se va directo a atacar el problema sin tanta palabrería.
Muchas gracias Santiago.
Saludos desde
Santiago
CHILE
AsterizKo
Coldfusion Developer
Me parece muy interesante la forma de trabajar los permisos.
Ahora entiendo algo las matematicas… espero el articulo con php ya que tambian soy novato en este lengiaje….
Encontré este artículo de casualidad, al poner en google ‘”operaciones bit a bit” php’, porque tengo que resolver un problema de privilegios de usuarios en php, pero no pensé que justament fuera a encontrar aquí la respuesta. Bueno, solo queda tratar de encontrar la adaptación al PHP.
Muchas gracias!
[font=courier new]Es interesantísimo este punto. Pero cómo comprobar los permisos? Un ejemplo de código… yo había hecho algo parecido pero con números primos. Esto es muchísimo más sencillo![/font]
Claro que es una exelente idea! como muchas otras que han tenido los diseñadores del sistema unix.
EL articulo es excelente ero tengo una duda tengo un sistema con 90 opciones y mi ultima funcion es un numero de 4951760157141521099596496896 y cuando lo operao con otro se desborda el entreo es de 64 bits y aun asi no lo soporta como puedo hacer para que pueda efetuarse el and entre 2 decimales grandes saludos
Amigos comparto como logre solucionar mi problema lo uni co que hice es segmentar mi numero de funcion en 4 partes como un IP y opere por partes 255.255.255.255 = 4294967296 listo gracias el articulo esta impeclable y esta respuesta daria como sulucion a la Libarta de DIRECCIONES jeje saludos a todos desde lima peru
Oye felicitaciones, no se de cuando es este articulo, pero esta excelente. Yo estaba buscando algo asi, pues deseo algo parecido para el control y administración de grupos usando RBAC (Roles-Based Acces Control). Bueno espero el codigo en PHP, para yo pasarlo a J2EE.
Si puedes enviálo a mi correo.
[email protected]
muy buen artivulo.. esperare elarticulo de php paraa adaptarlo
como para repetir es muy bueno, gracias por los copnsejillos
la verdad me parece muy interesante la forma para dar los permisos a los usuarios, creo que la forma sencilla pero eficaz de otorgar diferentes tipos de permisos a los usuarios de distintos tipos de grupos
es bueno saber que hay personas q no vacilan en compartir sus conocimientos… me pareceria interesante saber la manera de dar los permisos a los usuarios a traves de php porq me seria de gran utilidad en estos momentos otras ideas para mi trabajo de grado
Yo lo que kiero es ke los usuarios cuando no tengan permiso no se muestre la opcion en el menu, como lo hago?
Tengo un portal que utiliza un xml para definir las opciones del menu que vera un usuario. Simplemente defines la estructura del xml, de tal forma que cada una de las opciones del menu tenga una propiedad llamada “nivel_privilegio” que necesitara el usuario para ver esa opcion..
le pones un valor minimo, y comparas el nivel de privilegio del usuario con el de la opcion, si es igual o mayor, pones la opcion, si no, pues no..
Hola a todos. Antes que nada quiero agradecer que compartan sus conocimientos con el resto.
Tengo un gran problema y no se me ocurre como resolverlo, habia estado pensando en manejarlo a nivel de bits como lo plantearon aqui, pero se me genera la siguiente complicacion:
Tengo una tabla donde cada usuario cuando se loguea al sistema carga datos. Necesito que segun si el usuario tiene privilegios o no pueda ver solo sus registros cargados y los del resto. Pueda modificar los suyos solamente, o los suyos y los del resto, y asi sucesivamente.
Entonces un usuario con privilegios de administrador, podria ver,modificar y borrar los suyos y los del resto.
Otra cosita, me interesaria Raul, como implementaste el menu xml con privilegios
Estimado Santiago De Bernardez, la solución para este tipo de requerimientos, ni siquiera específicos, no es la MATEMÁTICA, en la LÓGICA, mi estimado, y la TÉCNICA.
Muchos se rompen la cabeza con técnicas tradicionales “estructuralistas”, si vale el término. Ahora existe la Tecnología Orientada a Objeto, donde esta problemática se resuelve de formas muy simple.
Este modelo, que nuestro amigo Santiago nos muestra, es un modelo basado en diseño estructurado, que por tal naturaleza, es limitado y es no recomentable.
Digo “no recomendable”, por que este sistema pertenece a la parte no-funcional del software, por tal razón no debe ser de carácter específico. Todo lo contrario, para el sistema de seguridad, así como operacional, comunicación, debe ser diseñado con carácter genérico: “por que son sistemas reutilizables” en un proyecto-software.
Además la solución planteada, definitivamente, es inútil, demasiado inútil.
Se está haciendo lo mismo que nada. Si quieres mantener la idea de trabajar en Bit’s, pues mejor es hacer dos cosas: 1) tener tantos campos de “funciones” (consultas, agregar, quitar, etc.) en la tabla de grupos; o, 2) tener un solo campo donde guardas toda la cadena “00110”, por ejemplo.
Y francamente, me quedaría con el segundo (2). Puesto me ayudaría a “crecer” en funciones, o acciones como lo llamó yo, que podría ejercer el usuario cobre un registro, tales como: finalización de estados de registros, anulaciones de documentos, impresión de copias oficiales, impresiones de copias borradores, bloqueo por seguridad de registro, etc., etc. Con esto, si se podría catalogar como un sistema de no-funcional, por que no estaría sujeto explícitamente a la parte funcional del software; más bien se convierte en un sistema de bajo nivel, donde la parte funcional de “ancla” sobre él. La solución planteada se perfila más a una Regla de Negocio, que a un sistema de seguridad.
Además, existen principios, que lamentablemente hoy en día no se practica. Y son principios básicos para diseñar soluciones, como conceptos de pertenencia, jerarquía, etc.
tandher, vuelvo a este artículo después de casi siete años y me encuentro con un comentario de 2009. Francamente ya no recuerdo por qué escribí esta nota, pero ya ha pasado tanto tiempo… Te agradezco mucho las opiniones y recomendaciones.