2008-08-04 21 views
17

A menudo encuentro la siguiente situación en la que necesito ofrecer muchos tipos diferentes de permisos. Yo uso principalmente ASP.NET/VB.NET con SQL Server 2000.¿Cuál es la mejor manera de manejar múltiples tipos de permisos?

Escenario

quiero ofrecer un sistema de permiso dinámico que puede trabajar en diferentes parámetros. Digamos que quiero dar acceso a una aplicación a un departamento o simplemente a una persona específica. Y pretendemos que tenemos una serie de aplicaciones que sigue creciendo.

En el pasado, he elegido una de las siguientes dos formas en que sé hacer esto.

1) Use una sola tabla de permisos con columnas especiales que se utilizan para determinar cómo aplicar los parámetros. Las columnas especiales en este ejemplo son TypeID y TypeAuxID. El SQL se vería así.

SELECT COUNT(PermissionID) 
FROM application_permissions 
WHERE 
(TypeID = 1 AND TypeAuxID = @UserID) OR 
(TypeID = 2 AND TypeAuxID = @DepartmentID) 
AND ApplicationID = 1 

2) Utilizar una tabla de asignación para cada tipo de permiso, a continuación, unirse a todos juntos.

SELECT COUNT(perm.PermissionID) 
FROM application_permissions perm 
LEFT JOIN application_UserPermissions emp 
ON perm.ApplicationID = emp.ApplicationID 
LEFT JOIN application_DepartmentPermissions dept 
ON perm.ApplicationID = dept.ApplicationID 
WHERE [email protected] 
    AND ([email protected] OR [email protected] OR 
(emp.UserID IS NULL AND dept.DeptID IS NULL)) AND ApplicationID = 1 
ORDER BY q.QID ASC 

Mis pensamientos

espero que los ejemplos tienen sentido. Los improvisé juntos.

El primer ejemplo requiere menos trabajo, pero ninguno de ellos parece ser la mejor respuesta. ¿Hay una mejor manera de manejar esto?

Respuesta

10

Estoy de acuerdo con John Downey.

Personalmente, a veces utilizo una enumeración de permisos marcada. De esta forma puede usar las operaciones AND, OR, NOT y XOR bit a bit en los elementos de la enumeración.

"[Flags] 
public enum Permission 
{ 
    VIEWUSERS = 1, // 2^0 // 0000 0001 
    EDITUSERS = 2, // 2^1 // 0000 0010 
    VIEWPRODUCTS = 4, // 2^2 // 0000 0100 
    EDITPRODUCTS = 8, // 2^3 // 0000 1000 
    VIEWCLIENTS = 16, // 2^4 // 0001 0000 
    EDITCLIENTS = 32, // 2^5 // 0010 0000 
    DELETECLIENTS = 64, // 2^6 // 0100 0000 
}" 

Luego, puede combinar varios permisos usando el operador AND bit a bit.

Por ejemplo, si un usuario puede ver & editar usuarios, el resultado de la operación binaria es 0000 0011, que convierte a decimal es 3.
A continuación, puede almacenar el permiso de un usuario en una sola columna de la base de datos (en nuestro caso sería 3).

Dentro de su aplicación, solo necesita otra operación bit a bit (O) para verificar si un usuario tiene un permiso particular o no.

+1

El problema que encontré con este enfoque es que es muy fácil quedarse sin papeles utilizando este enfoque. Como puede ver, 6 roles tienen un valor de 2^6 = 64, cuando 31 roles tendrán 2^31 = 2,147,483,647, que es el valor máximo int. Entonces, en T-SQL, el tipo de datos más grande que se puede usar es 'bigint' (2^63). Por supuesto, puede usar el tipo varchar, pero prefiero usar la solución de John Downey cuando tengo muchos roles. –

10

La forma en que generalmente utilizo los sistemas de permisos de codificación es tener 6 tablas.

  • Usuarios - esto es bastante sencillo es su tabla de usuarios típica
  • Grupos - esto sería sinónimo de sus departamentos
  • roles - esto es una tabla con todos los permisos en general, incluyendo también un nombre legible por humanos y una descripción
  • Users_have_Groups - esta es una tabla de lo que los grupos un usuario pertenece a
  • Users_have_Roles muchos-a-muchos - otra tabla de qué funciones se asignan a un usuario individual muchos-a-muchos
  • Groups_have_Roles - la mesa de muchos a muchos finales de lo que los roles que cada grupo tiene

Al comienzo de una sesión de usuarios debe ejecutar alguna lógica que se saca cada papel que han asignado, ya sea de directorio oa través de un grupo . Luego codifica contra esos roles como sus permisos de seguridad.

Como dije, esto es lo que suelo hacer, pero su millage puede variar.

0

Un enfoque que he utilizado en diversas aplicaciones es tener una clase de PermissionToken genérica que tiene una propiedad Value variable. Luego consultas la aplicación solicitada, te dice qué PermissionTokens son necesarios para usarla.

Por ejemplo, la aplicación de envío le puede decir que necesita:

new PermissionToken() 
{ 
    Target = PermissionTokenTarget.Application, 
    Action = PermissionTokenAction.View, 
    Value = "ShippingApp" 
}; 

Obviamente, esto puede ser extendido para crear, editar, borrar, etc y, debido a la propiedad Valor de encargo, cualquier aplicación, módulo o el widget puede definir sus propios permisos requeridos. YMMV, pero este siempre ha sido un método eficiente para mí que he encontrado que escala bien.

2

Además de las soluciones de John Downey y jdecuyper, también agregué un bit de "Denegación explícita" al final/principio del campo de bits, para que pueda realizar permisos adicionales por grupo, membresía de funciones y restar permisos basado en entradas de denegación explícitas, al igual que NTFS funciona, en cuanto al permiso.

2

Honestamente las características de Membresía/Roles de ASP.NET funcionarían perfectamente para el escenario que describió. Escribir tus propias tablas/procs/clases es un gran ejercicio y puedes obtener un control muy bueno sobre detalles minuciosos, pero después de hacer esto yo mismo he llegado a la conclusión de que es mejor usar las cosas incorporadas de .NET. Una gran cantidad de código existente está diseñado para solucionarlo, lo que es bueno en general. Escribir desde cero me llevó unas 2 semanas y no fue tan robusto como .NET. Tienes que codificar tanta mierda (recuperación de contraseña, bloqueo automático, encriptación, roles, una interfaz de permiso, toneladas de procs, etc.) y el tiempo podría ser mejor gastado en otro lugar.

Disculpa si no respondí tu pregunta, soy como el tipo que dice aprender C# cuando alguien hace una pregunta vb.

Cuestiones relacionadas