sql - usuario - ¿Cuál es la mejor manera de manejar múltiples tipos de permisos?
tipos de permisos sql server (5)
A menudo encuentro el siguiente escenario en el que necesito ofrecer muchos tipos diferentes de permisos. Principalmente uso ASP.NET / VB.NET con SQL Server 2000.
Guión
Quiero ofrecer un sistema de permiso dinámico que pueda funcionar 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 usan 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) Use una tabla de mapeo para cada tipo de permiso, luego júntelos 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 q.SectionID=@SectionID
AND (emp.UserID=@UserID OR dept.DeptID=@DeptID OR
(emp.UserID IS NULL AND dept.DeptID IS NULL)) AND ApplicationID = 1
ORDER BY q.QID ASC
Mis pensamientos
Espero que los ejemplos tengan sentido. Los improvisé juntos.
El primer ejemplo requiere menos trabajo, pero ninguno de ellos se siente como la mejor respuesta. ¿Hay una mejor manera de manejar esto?
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 luego restar permisos en función de negaciones explícitas entradas, al igual que NTFS funciona, en cuanto al permiso.
Estoy de acuerdo con John Downey.
Personalmente, a veces uso 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 y editar usuarios, el resultado binario de la operación es 0000 0011, que se convierte a decimal es 3.
A continuación, puede almacenar el permiso de un usuario en una sola columna de su 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.
La forma en que generalmente utilizo los sistemas de permisos de codificación es tener 6 tablas.
- Usuarios: esto es bastante directo, es la tabla de usuarios típicos
- Grupos: esto sería sinónimo de sus departamentos
- Roles: esta es una tabla con todos los permisos que generalmente también incluye un nombre legible por humanos y una descripción
- Users_have_Groups: esta es una tabla de varios a muchos de los grupos a los que pertenece un usuario
- Users_have_Roles: otra tabla de muchos a muchos con los roles asignados a un usuario individual
- Groups_have_Roles: la tabla final de muchos a muchos de los roles que tiene cada grupo
Al comienzo de la sesión de un usuario, ejecutará una lógica que extrae todas las funciones que tiene asignadas, ya sea directorio o grupo. Luego codifica contra esos roles como sus permisos de seguridad.
Como dije, esto es lo que normalmente hago, pero su millaje puede variar.
Un enfoque que he usado en varias aplicaciones es tener una clase 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 podría indicarle que necesita:
new PermissionToken()
{
Target = PermissionTokenTarget.Application,
Action = PermissionTokenAction.View,
Value = "ShippingApp"
};
Obviamente, esto se puede extender a Crear, Editar, Eliminar, etc. y, debido a la propiedad Valor personalizada, cualquier aplicación, módulo o artilugio puede definir sus propios permisos requeridos. YMMV, pero este siempre ha sido un método eficiente para mí que he encontrado que escala bien.
Honestamente, las características de Membresía / Funciones 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.
Lo siento si no respondí tu pregunta, soy como el chico que dice aprender c # cuando alguien hace una pregunta vb.