2008-12-02 26 views
35

Necesito agregar roles de usuario y sistema de permisos en mi aplicación web creada usando PHP/MySQL. Quiero tener esta funcionalidad:¿Mejores prácticas para diseñar roles de usuario y sistema de permisos?

  1. Un usuario root puede crear subraíces, grupos, reglas y usuarios normales (todos los privilegios).
  2. Las raíces secundarias solo pueden crear reglas, permisos y usuarios para su propio grupo (sin grupos).
  3. Un usuario puede acceder a cualquier contenido creado por él o por su grupo, según el permiso que se le haya asignado, por grupo raíz.

Necesito que el sistema sea lo suficientemente flexible, por lo que los nuevos roles y permisos se asignan al contenido.

Tengo una clave de grupo de almacenamiento de tabla users junto con otra información. Actualmente estoy usando dos feilds en cada tabla de contenido, es decir, createdBy y CreatedByGroup, y lo uso como el punto si un determinado usuario tiene permisos. Pero no es lo suficientemente flexible, porque para cada nuevo contenido, tengo que ir a través de todas las actualizaciones de datos y permisos. Por favor, ayúdenme discutiendo sus mejores prácticas para el diseño de esquemas.

Respuesta

33

El patrón que se adapta a sus necesidades se llama role-based access control.

Hay varias implementaciones buenas en PHP, incluyendo Zend_Acl (buena documenation), phpGACL y . La mayoría de los marcos también tienen sus propias implementaciones de una LCA de alguna forma.

Incluso si elige hacer su propia versión, le ayudará a revisar soluciones bien factorizadas como esas.

+0

El enlace de Zend_Acl está roto – reformed

+1

http://framework.zend.com/manual/1.12/en/zend.acl.html –

6

Tenía una estructura ligeramente diferente, pero debería poder servir como referencia.

Cada usuario tiene asociado un 'Rol', 'GroupID' y una tabla de Grupo a la que hace referencia el GroupID. Luego tengo 3 tablas de permisos.

PermissionMaster(FormName) 

PermissionChild(PermissionMasterID, PermissionName, Desc, DefaultValue, DependOn) y

PermissionGroupChild(GroupID, PermissionChildID, Allow) 

PermissionMaster contiene el nombre/forma/módulo para el que el permiso se refiere a. PermissionChild mostrará una lista de todos los permisos posibles disponibles para cada maestro, como 'Crear', 'Ver', 'Editar', 'Eliminar' y la descripción (No tuve esto en la primera versión, y comenzó a ser confuso cuando hay demasiadas configuraciones de permisos incluso para 1 módulo). Permití agregar más hijos para referirme específicamente a alguna función como 'ChangeTimeStamp', que también permitiría permisos más específicos y luego 'Editar'

Luego, PermissionGroupChild es el enlace entre la tabla PermissionChild y Group. Cada grupo tendrá un conjunto de PermissionChild copiado y configurado con la configuración predeterminada. Luego tuve una clase de permiso que hace la consulta de la tabla y verifica para cada usuario. Solo lo cargo durante el inicio de sesión. Luego, en cada formulario/módulo, verifico si es el permiso apropiado y aplica la UI correctamente.

En cuanto a la función, solo la utilizo en la página de configuración de inicio de sesión. El valor de rol más pequeño significa más alto. Por lo tanto, el usuario solo puede verse a sí mismo y a aquellos con un valor de Rol superior a sí mismo. Él/ella puede editar los de rango inferior a sí mismo, pero no similar.

+0

¿Puede explicar cómo usó PermissionChild? Trabajando en algo y esto pareció interesante. ¿Cómo se usó el valor predeterminado? 'PermissionChild (PermissionMasterID, PermissionName, Desc, DefaultValue, DependOn)' – rizwaniqbal

+1

Para cada formulario tengo el permiso básico para 'Crear' (Agregar nuevas entradas),' Ver' (Sin esto, el formulario tiene acceso denegado), 'Editar' (Edición de entradas existentes) y 'Eliminar' (eliminar una entrada). En algún momento tengo 'PermisoNiño' adicional como' ChangePassword' (cambiar la contraseña del usuario en la administración de usuarios) etc. El valor predeterminado es 'Boolean' para indicar cuándo no se reemplaza, si el permiso está permitido por defecto. La forma más común tendría 'View'' DefaultValue = 1' – faulty

6

Es posible que no desee grupos de permisos. En su lugar, cree grupos de usuarios, conceda permisos a los grupos de usuarios y coloque a los usuarios en grupos. Los usuarios también deben poder anular los permisos de los grupos en los que se encuentran. Denegar siempre debe anular la concesión cuando un usuario se encuentre en más de un grupo con el permiso.

En resumen:

  • usuario tiene cero o más permisos (grany, Denegar)
  • usuario está en cero o más grupos
  • Grupo tiene cero o más permisos (subvención, negar)
23

Creo que el operador bit a bit es la mejor manera de implementar el permiso del usuario. Aquí estoy mostrando cómo podemos implementarlo con MySQL.

a continuación es una tablas de ejemplo con algunos datos de muestra:

Tabla 1: mesa de Permiso para el permiso nombre de la tienda junto con él poco como 1, 2, 4, 8, etc .. (múltiplo de 2)

CREATE TABLE IF NOT EXISTS `permission` (
    `bit` int(11) NOT NULL, 
    `name` varchar(50) NOT NULL, 
    PRIMARY KEY (`bit`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

Inserte algunos datos de muestra en la tabla.

INSERT INTO `permission` (`bit`, `name`) VALUES 
(1, 'User-Add'), 
(2, 'User-Edit'), 
(4, 'User-Delete'), 
(8, 'User-View'), 
(16, 'Blog-Add'), 
(32, 'Blog-Edit'), 
(64, 'Blog-Delete'), 
(128, 'Blog-View'); 

Tabla 2: mesa usuario almacenar la identificación del usuario, nombre y función. El rol se calculará como la suma de permisos.
Ejemplo:

Si el usuario 'Ketan' tiene permiso de 'User-Add' (bit = 1) y 'Blog-Delete' (bit-64), entonces el rol será 65 (1 + 64).
Si el usuario 'Mehata' tiene permiso de 'Blog-View' (bit = 128) y 'User-Delete' (bit-4), entonces el rol será 132 (128 + 4).

CREATE TABLE IF NOT EXISTS `user` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(50) NOT NULL, 
    `role` int(11) NOT NULL, 
    `created_date` datetime NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

Muestra Data-

INSERT INTO `user` (`id`, `name`, `role`, `created_date`) 
    VALUES (NULL, 'Ketan', '65', '2013-01-09 00:00:00'), 
    (NULL, 'Mehata', '132', '2013-01-09 00:00:00'); 

permiso Loding de usuario Después de inicio de sesión si queremos cargar el permiso del usuario, entonces podemos consultar aquí para obtener los permisos:

SELECT permission.bit,permission.name 
    FROM user LEFT JOIN permission ON user.role & permission.bit 
WHERE user.id = 1 
Aquí

usuario .role "&" permission.bit es un operador Bitwise que dará salida como -

User-Add - 1 
Blog-Delete - 64 

Si queremos comprobar el tiempo de un usuario en particular tienen fácil de permisos de edición o no-

SELECT * FROM `user` 
    WHERE role & (select bit from permission where name='user-edit') 

salida = No hay filas.

Se puede ver también: http://goo.gl/ATnj6j

+0

¿Cuál es el valor máximo permitido para la tabla de permisos? ¿Cuántos permisos únicos se pueden insertar en la tabla de permisos? ¿Qué tal si agregas la suma de todos los permisos posibles en la columna del rol de usuario? – traditional

+1

@traditional: el tamaño sería usar un bigint, que es de 64 bits, lo que permite 64 permisos. Si eso es suficiente, esta es una manera ordenada de hacer las cosas. Si eso no es suficiente y no te preocupa el espacio, tener columnas separadas para cada permiso probablemente estaría bien. –

+2

Aquí no hay un concepto de "rol"; lo que tienes es una lista de permisos por usuario. –

1

tengo grupos y usuarios (como solución LDAP Active Directory). Entonces, si doy acceso al grupo, necesito que los usuarios de este grupo tengan acceso herido.

Por lo tanto, en base a la @ respuesta Suresh-kamrushi continuación, hice esto:

INSERT INTO `permission` (`bit`, `name`) VALUES 
(1, 'add-yes'), 
(2, 'add-no'), 
(4, 'edit-yes'), 
(8, 'edit-no'), 
(16, 'del-yes'), 
(32, 'del-no'), 
(64, 'view-yes'), 
(128, 'view-no'); 

Si el usuario tiene poco 00000000, tomo dos primeros dígitos 00 que significa add-yes y add-no están heredada de permisos de grupo.

Si el usuario tiene el bit 01010110, tomo los primeros dos dígitos 01 que significa add-no se cebará en permisos de grupo, por lo que este usuario no tiene permiso para agregar. Este bitwise dice que el usuario solo puede ver.

También está trabajando con grupos de padres.

¿Qué opina de esta solución? ¿Alguien tiene una mejor manera de hacerlo?

Cuestiones relacionadas