2012-03-06 12 views
8

En mi aplicación Symfony 2 Quiero usar el sistema ordinario de autorización de usuarios y roles (http://symfony.com/doc/2.0/book/security.html)Symfony framework; forma idiomática para almacenar el papel de un usuario

Mi El usuario es una entidad almacenada en una base de datos con doctrina (implementando la interfaz de usuario). Tendré 5 roles predefinidos en mi sistema, teniendo cada usuario posiblemente múltiples de estos roles.

¿Cuál sería la forma más idiomática de implementar esto? Estoy pensando en las siguientes tres soluciones.

  1. Hacer una entidad papel separada y crear una relación de muchos a muchos con la entidad de usuario

    • Plus: Es fácil llegar a todos los usuarios con un rol específico
    • contra: intensiva de recursos? (Siempre necesita una unión doble para obtener todos los roles para un usuario)
    • Con: ¿No es idóneo? El número de Roles (y sus nombres) nunca cambia, ¿tiene sentido almacenarlo en la base de datos como una entidad separada?
  2. tienen un campo dentro de usuario que es una lista ordenada, comas separadas de las funciones y getRoles() se implementa como explode(',',this.all_roles)

    • Plus: No es costoso computacionalmente
    • Contra: Es difícil conseguir todos los usuarios con un rol específico
    • contra: campos de base de este tipo hacen gatitos lloran (normalizaition y cosas)
  3. tener 5 campos binarios en la entidad de usuario para cada rol

    • Plus: No es costoso computacionalmente
    • Plus: Es fácil llegar a todos los usuarios con un rol específico
    • contra: Esto todavía no se siente bien

¿Cuál es la forma más idiomática de la implementación de este sistema?

+0

¿Cómo puedo solucionar el espaciado entre mis elementos de sublista? –

+1

La opción 1 es, por supuesto, la forma más segura de hacerlo.Si alguna vez necesita colgar relaciones adicionales en sus roles (permisos, etc.), entonces estaría todo configurado. La opción 2 probablemente funcionará bien. ¿Tal vez usar un número entero con asignación de bits para almacenar los roles? Sé algo más limpio, ampliable y cuestionable. Simplemente no dejes que los gatitos lo vean. – Cerad

+0

¿No podría usar [FOSUserBundle] (https://github.com/FriendsOfSymfony/FOSUserBundle) para esto? – Flukey

Respuesta

12

Por supuesto, una respuesta depende mucho de sus requisitos, pero intentaré responder de la manera más global posible.

Opción 1: La forma relacional

Desde un punto puramente relacional de vista, usted quiere que su base de datos normalizada lo que llevaría a su primera opción: Una mesa para los papeles con am: n relación con el usuario mesa. Esto tiene algunas ventajas:

  • Bueno, es la forma en que uno esperaría que tu base de datos funcione, por lo que no hay funcionalidad que esté oculta en tus entidades.
  • No hay manera de enredar las cosas (como cuando se tiene un campo varchar y esperamos que tenga algún tipo de formato como el coma-separación)
  • Sólo hay una manera de hacer las cosas

con respecto a su preocupación de que los roles nunca cambian: el almacenamiento de datos relacionales no se trata de la frecuencia con la que cambia. Y uno siempre debe recordar que los requisitos cambian. Cuanto más te equivoques en este momento en nombre de la optimización, más lucharás más tarde cuando exista la necesidad de más roles que cambien con más frecuencia.

Por supuesto, puede tener problemas de rendimiento, especialmente si se encuentra con algún tipo de problema de carga con ganas o si no guarda en caché las cosas y tiene que volver a cargar las funciones en cada carga de página. Pero, una vez más, las bases de datos relacionales están diseñadas para admitir ese tipo de cosas, por lo que debería haber formas de optimizar las consultas.

Opción 2: El truco

La segunda opción, sólo tiene que almacenar todos los papeles en un varchar, sería mucho mejor en términos de rendimiento. Solo un campo de texto para cargar, algo de procesamiento de PHP y listo. Por otro lado, es posible que encuentre varias cuestiones:

  • Usted no tiene control sobre el campo varchar por lo que uno mal funcionamiento del script puede comprometer toda su aplicación (Esto es realmente malo, pero dependiendo de su proyecto, si está el único desarrollador y usted sabe lo que está haciendo, podría funcionar bien)
  • Una actualización de un conjunto de datos es mucho más difícil, ya que tiene que extraer todos los roles, actualizar los que están en cuestión y almacenar de nuevo
  • para todos los usuarios con un rol específico es mucho más difícil
  • Eliminar un rol es mucho más difícil

Opción 3: La solución pragmática

La tercera opción con 5 booleanos para cada función está en el medio: No hay manera de meter la pata y el rendimiento no debería ser un problema. Actualizar es fácil así como eliminar una función o agregar una nueva. Está bastante claro lo que hacen los campos, así que tampoco hay daño en este lado. Hace que su entidad y su base de datos se vean un poco más feos y también tendría los nombres de rol en su modelo de usuario para asignar los campos verdadero/falso a los nombres de rol correctos, lo que podría ser un poco confuso.

Resultado

Todo esto en mente, me gustaría ir con la opción 1. Se puede suponer que el rendimiento es un problema, pero si no tengo prueba de ello, no pensar en esas cosas. Al final, ¿qué haces cuando realmente tienes un problema de rendimiento real? Puede agregar hardware adicional, optimizar su dbms, optimizar las consultas o tal vez usar un dbms con más rendimiento incorporado (¡Hola Oracle!).

Y siempre puede usar la opción 3 más adelante si ha demostrado que su aplicación es lenta debido a la tabla de roles. Simplemente tendría que cambiar su entidad de usuario y tener una consulta que extraiga los roles y establezca las combinaciones verdaderas/falsas correctas para cada usuario. Si el software está limpio, este es un problema de horas, por lo que no es necesario hacerlo ahora con la idea de que el rendimiento puede ser malo.

+0

+1 Respuesta impresionante. FOSUserBundle almacena los roles en una matriz. ¿Sería posible tener su opinión experta sobre esto? Muchas gracias @Sgoettschkes. – Mick

Cuestiones relacionadas