Permisos de usuarios
Permisos de usuarios
Posted in Personal / Reflexiones, Software, Programación by Nicolaspar on the Diciembre 8th, 2006
Aún recuerdo mi primer sistema web, este debía cumplir un requisito indispensable en el backoffice y era que los administradores pudieran contar con diferentes permisos sobre las diferentes 5 secciones que este tenia, para así poder por ejemplo, crear un administrador Juan que le cargase noticias, y uno que fuera Pepe, que le agregue encuestas y le administre los foros.
Para ese entonces, y aún teniendo la lógica de un ex estudiante de sistemas, no se me ocurrió más que agregar por cada sección un campo en la tabla de administradores del tipo “si/no”.
Aunque la vergüenza al comentar esto es muy grande, lo compensa el hecho de que creo que hoy en día he encontrado el equilibrio exacto para esta tarea a nivel de sistemas con permisos simples de este estilo.
Primer planteo, comparación bit a bit.
Unos años después comencé a conocer más en profundidad las ventajas de ASP y PHP, y ahí vi que en ambos casos se pueden usar estas comparaciones. No voy a explicar sistemas binarios, octanos, decimales, etc, solo contarles que trabajaremos con binarios, que estos son una notación en base dos (ceros y unos, hay excelentes manuales que google les puede mostrar en la web sobre este tema) y que lo que nos interesa saber es que usaremos el operador lógico “AND” y que lo que éste hace es evaluar los bits que están activos, tanto en A como en B, y si da alguno como activo será verdadero.
Esto sería lo siguiente llevado a un ejemplo cualquiera:
01001101
10101110
00001100
Noten que solo pasan activos la 5ta y 6ta posición, otro ejemplo:
111000111
001110101
001000101
Aclaro que los activos son los 1 (por si alguien esta dormido), y que si en el número de abajo esa posición esta también activa, pues nada mas baja como 1, sino quedará como cero. Si no lo entendiste aún reléelo que es simple de comprender.
Ahora, sabiendo la siguiente conversión:
0 = 00000000
1 = 00000001
2 = 00000010
3 = 00000011
4 = 00000100
5 = 00000101
6 = 00000110
7 = 00000111
8 = 00001000
9 = 00001001
Lo que haremos es, tomaremos el número 3 en binario, y nos fijaremos que nos enciende este 3 junto con un número 5:
00000011 = 3 en decimal
00000101 = 5 en decimal
00000001 = 1 en decimal
Veremos que nos devuelve 1, que sería un resultado positivo porque nos dice que hay un bit en 3 que también esta prendido en 5. Para el sistema que propongo se usarán los bits que no coincidan con los bits prendidos en las mismas posiciones, para lo que usaremos la simple formula que será la simple n^2 que sería mas simple de entender para muchos viendo como resultado de lo anterior los siguiente valores, 1,2,4,8,16,32,64,128, etc, etc: Para que se comprenda lo que trate de decir:
00000001 = 1
00000010 = 2
00000100 = 4
00001000 = 8
00010000 = 16
00100000 = 32
01000000 = 64
10000000 = 128
100000000 = 256
1000000000 = 512
Y para que vayamos entendiendo aún mas tomaremos hasta el 16 y le asignaremos secciones inventadas para ejemplificarlo.
00000001 = 1 = Usuarios
00000010 = 2 = Administradores
00000100 = 4 = Noticias
00001000 = 8 = Encuestas
00010000 = 16 = Foros
Con este método nos aseguramos que si por ejemplo, tenemos permisos 10 (en decimal, que no sería mas que administradores + encuestas o bien 2+8) no se pisen con otra combinación. Veamos como noticias que es 4 no nos encendería jamás un bit:
00000100 = 4 de noticias
00001010 = 10 de nuestros permisos asignados
00000000 = Es todo apagado.
Teniendo la seguridad que esto es 100% efectivo podemos hacer un formulario con unos checkbox donde cada uno tendrá unos de los valores del ejemplo y al guardarlos se sumarán guardando en un solo campo un único valor. Si el administrador tiene permisos sobre todas las secciones tendrá 31, si fueran noticias, encuestas y usuarios tendrá 13, y así sucesivamente.
Se preguntarán como aplicamos esto a nuestro sistema, y la respuesta es muy simple. Por ejemplo, en la botonera o link a la sección validamos de la siguiente manera:
if ( ($permisos & 2) == 2 ) { … Administradores … }
if ( ($permisos & 4) == 4 ) { … Noticias … }
Lo que hago acá es decirle, a mis 10 de permisos (variable $permisos) le prendo los mismos bits que el valor de la sección, ejemplifiquemos que se comprende mejor:
Administradores:
00001010 (mis permisos, 10 en dec)
00000010 (administradores, 2 en dec)
00000010 (Bárbaro, tengo un bit encendido)
Veamos con Noticias:
00001010 (mis permisos, 10 en dec)
00000100 (administradores, 2 en dec)
00000000 (No se prende ninguno, no tengo acceso)
En ASP es exactamente igual:
if (adm_permiso and 2) = 2 then … Administradores … end if
if (adm_permiso and 4) = 4 then … Noticias … end if
A esto le sumaremos la seguridad de agregar en cada pagina la misma validación, para asegurarnos que no entren vía URL directa, personalmente tengo hechas funciones donde le paso que valor evaluar y accedo a sus permisos que están en una session dando un true o false como salida en la misma.
Segundo planteo, string de datos.
Un día me encontré con la falencia de que el sistema tenía secciones dinámicas que se creaban de manera excesivas, por lo que el campo “int” que solía usar me quedaba chico, y no solo eso, sino que para PHP ya dejaba de ser un int este numerote que superaba los, si!, dos billones que es el valor usual (lo que es un valor de 32 bits con signo) . La solución que reemplazará a la anterior debía ser mejor que está.
Esta solución es mucho mas simple de comprender porque no requiere conocimientos de matemáticas o conocimientos sobre sistemas de numeración y demás yerbas, si un poco mas de sql que lo anterior, pero sql básico al fin.
La solución es la siguiente: Seguimos conservando la tabla de administradores pero sin el campo de permisos. A cambio de este crearemos una tabla de permisos y una de administradores permisos. En la tabla permisos tendremos una simple Primary Key y un nombre, en la de administradores permisos tendremos una relación de muchos a muchos con la PK del permiso y el PK del administrador.
Toda lo que resta es una vez logueado crear una variable que contenga todos los permisos que este administrador tenga separados por una coma (un while sobre la tabla de relación concatenando los valores). Lo importante en este paso es que todo quede entre comas, ej: 0,1,2,10,20,12,5,0, donde los ceros son “bobos”, para que por ejemplo el 5 no quede libre. Teniendo este formato podemos hacer una función que evalue si el string “permiso” esta dentro del string que conforma los permisos del usuario. En PHP podemos usar la funcion strstr() (http://www.php.net/strstr), y haríamos algo así:
$permisoAEvaluar = 2;
if( strstr( $permisos, ‘,’ . $permisoAEvaluar . ‘,’ ) ){
true
}else{
false
}
Obviamente esto queda mucho mejor en una función o classe que cada uno sabrá adaptar según las necesidades que tenga.
Espero que estas lógicas de aplicación les sean útiles y a programar!.
Posted in Personal / Reflexiones, Software, Programación by Nicolaspar on the Diciembre 8th, 2006
Aún recuerdo mi primer sistema web, este debía cumplir un requisito indispensable en el backoffice y era que los administradores pudieran contar con diferentes permisos sobre las diferentes 5 secciones que este tenia, para así poder por ejemplo, crear un administrador Juan que le cargase noticias, y uno que fuera Pepe, que le agregue encuestas y le administre los foros.
Para ese entonces, y aún teniendo la lógica de un ex estudiante de sistemas, no se me ocurrió más que agregar por cada sección un campo en la tabla de administradores del tipo “si/no”.
Aunque la vergüenza al comentar esto es muy grande, lo compensa el hecho de que creo que hoy en día he encontrado el equilibrio exacto para esta tarea a nivel de sistemas con permisos simples de este estilo.
Primer planteo, comparación bit a bit.
Unos años después comencé a conocer más en profundidad las ventajas de ASP y PHP, y ahí vi que en ambos casos se pueden usar estas comparaciones. No voy a explicar sistemas binarios, octanos, decimales, etc, solo contarles que trabajaremos con binarios, que estos son una notación en base dos (ceros y unos, hay excelentes manuales que google les puede mostrar en la web sobre este tema) y que lo que nos interesa saber es que usaremos el operador lógico “AND” y que lo que éste hace es evaluar los bits que están activos, tanto en A como en B, y si da alguno como activo será verdadero.
Esto sería lo siguiente llevado a un ejemplo cualquiera:
01001101
10101110
00001100
Noten que solo pasan activos la 5ta y 6ta posición, otro ejemplo:
111000111
001110101
001000101
Aclaro que los activos son los 1 (por si alguien esta dormido), y que si en el número de abajo esa posición esta también activa, pues nada mas baja como 1, sino quedará como cero. Si no lo entendiste aún reléelo que es simple de comprender.
Ahora, sabiendo la siguiente conversión:
0 = 00000000
1 = 00000001
2 = 00000010
3 = 00000011
4 = 00000100
5 = 00000101
6 = 00000110
7 = 00000111
8 = 00001000
9 = 00001001
Lo que haremos es, tomaremos el número 3 en binario, y nos fijaremos que nos enciende este 3 junto con un número 5:
00000011 = 3 en decimal
00000101 = 5 en decimal
00000001 = 1 en decimal
Veremos que nos devuelve 1, que sería un resultado positivo porque nos dice que hay un bit en 3 que también esta prendido en 5. Para el sistema que propongo se usarán los bits que no coincidan con los bits prendidos en las mismas posiciones, para lo que usaremos la simple formula que será la simple n^2 que sería mas simple de entender para muchos viendo como resultado de lo anterior los siguiente valores, 1,2,4,8,16,32,64,128, etc, etc: Para que se comprenda lo que trate de decir:
00000001 = 1
00000010 = 2
00000100 = 4
00001000 = 8
00010000 = 16
00100000 = 32
01000000 = 64
10000000 = 128
100000000 = 256
1000000000 = 512
Y para que vayamos entendiendo aún mas tomaremos hasta el 16 y le asignaremos secciones inventadas para ejemplificarlo.
00000001 = 1 = Usuarios
00000010 = 2 = Administradores
00000100 = 4 = Noticias
00001000 = 8 = Encuestas
00010000 = 16 = Foros
Con este método nos aseguramos que si por ejemplo, tenemos permisos 10 (en decimal, que no sería mas que administradores + encuestas o bien 2+8) no se pisen con otra combinación. Veamos como noticias que es 4 no nos encendería jamás un bit:
00000100 = 4 de noticias
00001010 = 10 de nuestros permisos asignados
00000000 = Es todo apagado.
Teniendo la seguridad que esto es 100% efectivo podemos hacer un formulario con unos checkbox donde cada uno tendrá unos de los valores del ejemplo y al guardarlos se sumarán guardando en un solo campo un único valor. Si el administrador tiene permisos sobre todas las secciones tendrá 31, si fueran noticias, encuestas y usuarios tendrá 13, y así sucesivamente.
Se preguntarán como aplicamos esto a nuestro sistema, y la respuesta es muy simple. Por ejemplo, en la botonera o link a la sección validamos de la siguiente manera:
if ( ($permisos & 2) == 2 ) { … Administradores … }
if ( ($permisos & 4) == 4 ) { … Noticias … }
Lo que hago acá es decirle, a mis 10 de permisos (variable $permisos) le prendo los mismos bits que el valor de la sección, ejemplifiquemos que se comprende mejor:
Administradores:
00001010 (mis permisos, 10 en dec)
00000010 (administradores, 2 en dec)
00000010 (Bárbaro, tengo un bit encendido)
Veamos con Noticias:
00001010 (mis permisos, 10 en dec)
00000100 (administradores, 2 en dec)
00000000 (No se prende ninguno, no tengo acceso)
En ASP es exactamente igual:
if (adm_permiso and 2) = 2 then … Administradores … end if
if (adm_permiso and 4) = 4 then … Noticias … end if
A esto le sumaremos la seguridad de agregar en cada pagina la misma validación, para asegurarnos que no entren vía URL directa, personalmente tengo hechas funciones donde le paso que valor evaluar y accedo a sus permisos que están en una session dando un true o false como salida en la misma.
Segundo planteo, string de datos.
Un día me encontré con la falencia de que el sistema tenía secciones dinámicas que se creaban de manera excesivas, por lo que el campo “int” que solía usar me quedaba chico, y no solo eso, sino que para PHP ya dejaba de ser un int este numerote que superaba los, si!, dos billones que es el valor usual (lo que es un valor de 32 bits con signo) . La solución que reemplazará a la anterior debía ser mejor que está.
Esta solución es mucho mas simple de comprender porque no requiere conocimientos de matemáticas o conocimientos sobre sistemas de numeración y demás yerbas, si un poco mas de sql que lo anterior, pero sql básico al fin.
La solución es la siguiente: Seguimos conservando la tabla de administradores pero sin el campo de permisos. A cambio de este crearemos una tabla de permisos y una de administradores permisos. En la tabla permisos tendremos una simple Primary Key y un nombre, en la de administradores permisos tendremos una relación de muchos a muchos con la PK del permiso y el PK del administrador.
Toda lo que resta es una vez logueado crear una variable que contenga todos los permisos que este administrador tenga separados por una coma (un while sobre la tabla de relación concatenando los valores). Lo importante en este paso es que todo quede entre comas, ej: 0,1,2,10,20,12,5,0, donde los ceros son “bobos”, para que por ejemplo el 5 no quede libre. Teniendo este formato podemos hacer una función que evalue si el string “permiso” esta dentro del string que conforma los permisos del usuario. En PHP podemos usar la funcion strstr() (http://www.php.net/strstr), y haríamos algo así:
$permisoAEvaluar = 2;
if( strstr( $permisos, ‘,’ . $permisoAEvaluar . ‘,’ ) ){
true
}else{
false
}
Obviamente esto queda mucho mejor en una función o classe que cada uno sabrá adaptar según las necesidades que tenga.
Espero que estas lógicas de aplicación les sean útiles y a programar!.