none
Implementar Acceso de Usuario por Perfiles RRS feed

  • Pregunta

  • Como puedo hacer el acceso de usuarios de acuerdo al perfil que tiene, tengo estas tablas: me falta hacer la parte de los procedimientos almacenados y los formularios
    viernes, 16 de enero de 2015 13:15

Respuestas

  • Ok, lo mejor que puede hacer es idear un sistema de seguridad que NO dependa de las construcciones de interfase gráfica. ¿Por qué?  Porque el diseño de una interfase gráfica puede cambiar y entonces se verá obligado a trabajar nuevamente en el aspecto de seguridad.

    Lo que debe hacer:

    1. "Objetizar" los recursos que serán objeto de control de acceso.  Cuando hablamos de asegurar datos en una base de datos, un objeto suele estar definido por una table y vice versa.  Tenemos el objeto Cliente, el objeto Factura, etc.
    2. Definir qué acciones serán sujetas a control de acceso.  Normalmente esto es Leer, Actualizar, Crear Nuevo, Borrar.  A veces puede definirse algo más fino, como Leer y Leer Auditoria cuando queremos controlar la capacidad de los usuarios para leer los datos por un lado y los datos de auditoria por otro.  Estas acciones son lo que se llaman Permisos.
    3. Los permisos en #2 pueden ser distintos para distintos objetos.  No es problema.  Cree una lista de permisos para cada tipo de objeto.  Si un tipo de objeto comparte la misma lista de permisos que otro tipo de objeto, puede clasificar ambos bajo un mismo "tipo de objeto".
    4. Ahora tiene que decidir:  ¿Dará permisos por objeto o por tipo de objeto?  O sea:  ¿Será posible asignar permisos para cada uno de los registros individuales de una tabla, o se asignan permisos para todos los objetos de la tabla?

    Los puntos 1,2 y 3 se traduce a algo así en SQL Server:

    Create Table dbo.tblObjectTypes
    (
        ID int Not Null Identity(1, 1) Primary Key
        , Name nvarchar(50) Not Null Unique
    );
    
    Create Table dbo.tblPermissions
    (
        ID int Not Null Identity(1, 1) Primary Key
        , ObjectType int Not Null Foreign Key References dbo.tblObjectTypes (ID)
        , Value int Not Null Check (Value > 0)
        , Constraint UX_dbo_tblPermissions_UniqueValuePerObjectType Unique
        (
            ObjectType
            , Value
        )
    );
    
    Create Table dbo.tblObjects
    (
        ID int Not Null Identity(1, 1) Primary Key
        , Name nvarchar(50) Not Null Unique
        , ObjectType int Not Null Foreign Key References dbo.tblObjectTypes (ID)
    );
    
    

    Si en el punto 4 decidió que los permisos se asignan a tipo de objeto entonces creamos una tabla como esta:

    Create Table dbo.tblACL
    (
        ID int Not Null Identity(1, 1) Primary Key
        , Object int Not Null Foreign Key References dbo.tblObjects (ID)
        , SecurityPrincipal nvarchar(150) Not Null
        , AllowAccessMask int Not Null Default(0)
        , DenyAccessMask int Not Null Default(0)
    );

    Aquí hago una pausa:  No sé qué tipo de usuarios usa usted.  Si usa Active Directory, SecurityPrincipal podrían ser nombres de grupos de seguridad o nombres de usuarios.  Si no, sería major tener una tabla de usuarios y grupos de usuario (la misma tabla para ambos) y que SecurityPrincipal fuera un FK a esa tabla.

    Luego vamos a Allow y DenyAccessMask.  Como cada permiso es de sí o no, es muy cómodo usar un campo de 32 bit (tipo int en SQL Server) donde cada bit representa un permiso.  Ese bit estaría definido en el campo dbo.tblPermissions.Value.  Eso quiere decir que puede definer hasta 32 permisos diferentes para cada tipo de objeto.  Si no sabe de bitwise operations, este es el momento de aprender.

    Asumamos que tiene los siguientes permisos para objetos tipo "Estandar":

    • Leer, Value = 1 (primer bit)
    • Insertar, Value = 2 (Segundo bit)
    • Actualizar, Value = 4 (tercer bit)
    • Borrar, Value = 8 (cuarto bit)

    Queremos asignarle al usuario DOMINIO\usuario permisos de lectura y borrado al objeto Cliente que es de tipo estándar.

    Declare @objectID int;
    Select @objectID = ID
    From
        dbo.tblObjects
    Where
        Name = N'Cliente'
    ;
    Declare @readPerm int, @deletePerm int;
    Set @readPerm = 1;
    Set @deletePerm = 8;
    Insert Into dbo.tblACL (Object, SecurityPrincipal, AllowAccessMask)
    Values (@objectID, N'DOMINIO\usuario', @readPerm | @deletePerm);

    El valor final de AllowAccessMask es 1 | 8 = 9.

    DenyAccessMask serviría igual, pero no suelo usarlo.  Puede hacer una lógica compleja similar a permisos NTFS pero nunca he necesitado tal nivel de seguridad, así que le recomiendo en este punto ignorer este campo por el momento.  Para usarlo habría que definir prioridades de qué reemplaza qué y demás.  Si no se ocupa, major no se hace.

    En este punto usted ya tiene definida la seguridad.  No fue trivial pero espero que no haya sido demasiado complejo tampoco.

    ¿Cómo se usa esto?  Lo major es crear una function escalar que compruebe si un usuario tiene uno o más permisos.  Por ejemplo, un SP de borrado comprobaría que el usuario tenga permisos de borrado sobre el objeto en cuestión antes de proceder a borrarlo  llamando a una función que comprueba los valores en tblACL.

    El truco aquí está en descubrir si el usuario tiene el derecho basándose en membresía de grupo.  Cuando se usan grupos de Active Directory, SQL Server provee la función IsMember().  Si usted creó su propia tabla de Security Principals donde ahí se definen grupos, pues usted deberá usar un SELECT de su tabla de membresía de grupos para saber si un usuario pertenece o no a un grupo.

    Create Function dbo.fnHasPermissions
    (
        @userName nvarchar(150)
        , @requiredPermissions int
        , @objectID int
    )
    Returns bit
    As
    Begin
        if Exists(Select
            *
        From
            dbo.tblACL
        Where
            Object = @objectID
            And
            (
                SecurityPrincipal = @userName
                Or
                IsMember(SecurityPrincipal, @userName) = 1
            )
            And
            (AllowAccessMask & @requiredPermissions) = @requiredPermissions
        )
            Return 1;
        Return 0;
    End
    

    Algo así sería la función.  Es un SELECT basado en IsMember().  Si IsMember() da error con nombres de usuario en donde debería haber un nombre de grupo, deberá incluir en tblACL un campo IsGroup que dice qué SecurityPrincipals son grupos y qué no.  Sí, es una violación a la normalidad de la base de datos, pero es una que suelo pagar en este caso específico.  Si quiere seguir las reglas de normalización, deberá tener una tabla de security principals aún cuando sean de Active Directory.  Es decision suya.

    Como le decía, ese es un ejemplo.  Tal vez usted quiera trabajarlo diferente.  Lo importante aquí es ver la idea y el mecanismo:  Usamos BITWISE AND para saber si los registros seleccionados por las condiciones de objeto, SecurityPrincipal y membresía de grupo contienen exactamente los permisos almacenados en @requiredPermissions.  Si hay al menos un registro que sí los tiene, la función devuelve 1 (true).  Si quiere usar DenyAccessMask o tener una lógica más compleja, tal vez deberá cambiar esta sencilla funcionalidad.

    Entonces volviendo al SP que borra:

    Declare @objectID int;
    Set @objectID = dbo.fnGetObjectID(N'Cliente'); --Para facilidad hacemos una función.
    Declare @deletePerm int;
    Set @deletePerm = 8;
    If (dbo.fnHasPermissions(@userName, @deletePerm, @objectID) = 1)
    Begin
        Delete
        From
            dbo.tblClientes
        Where
            ID = @id;
    End
    Else
        Raiserror(N'No tiene permisos para realizar la operación de borrado de un cliente.', 16, 1);

    Y creo que ya cubrí al menos la mayoría. Fue bastante explicación. Es más fácil de lo que tardé explicando, jeje.


    Jose R. MCP
    Code Samples

    viernes, 16 de enero de 2015 16:22
    Moderador

Todas las respuestas

  • Creo que usted lo que quiere hacer es implementar seguridad. ¿Cierto?

    Si estoy en lo cierto, ¿dónde quiere implementar dicha seguridad?  Porque veo algo llamado formularios.  ¿Son esos formularios de alguna interfase gráfica, tal vez en Windows Forms?

    En mi no muy inexperta opinion, me parece que toma un mal camino, asumiendo que mis hipótesis anteriores son correctas.

    Tengo una reunion pronto, pero volveré a explicarle un poco más lo que en mi opinion debería usted (y cualquiera) hacer.


    Jose R. MCP
    Code Samples

    viernes, 16 de enero de 2015 13:46
    Moderador
  • Si seguridad quiero implementar y los formularios tiene interface grafica con windows forms, gracias por la respuesta espero tu opinion
    viernes, 16 de enero de 2015 13:50
  • Ok, lo mejor que puede hacer es idear un sistema de seguridad que NO dependa de las construcciones de interfase gráfica. ¿Por qué?  Porque el diseño de una interfase gráfica puede cambiar y entonces se verá obligado a trabajar nuevamente en el aspecto de seguridad.

    Lo que debe hacer:

    1. "Objetizar" los recursos que serán objeto de control de acceso.  Cuando hablamos de asegurar datos en una base de datos, un objeto suele estar definido por una table y vice versa.  Tenemos el objeto Cliente, el objeto Factura, etc.
    2. Definir qué acciones serán sujetas a control de acceso.  Normalmente esto es Leer, Actualizar, Crear Nuevo, Borrar.  A veces puede definirse algo más fino, como Leer y Leer Auditoria cuando queremos controlar la capacidad de los usuarios para leer los datos por un lado y los datos de auditoria por otro.  Estas acciones son lo que se llaman Permisos.
    3. Los permisos en #2 pueden ser distintos para distintos objetos.  No es problema.  Cree una lista de permisos para cada tipo de objeto.  Si un tipo de objeto comparte la misma lista de permisos que otro tipo de objeto, puede clasificar ambos bajo un mismo "tipo de objeto".
    4. Ahora tiene que decidir:  ¿Dará permisos por objeto o por tipo de objeto?  O sea:  ¿Será posible asignar permisos para cada uno de los registros individuales de una tabla, o se asignan permisos para todos los objetos de la tabla?

    Los puntos 1,2 y 3 se traduce a algo así en SQL Server:

    Create Table dbo.tblObjectTypes
    (
        ID int Not Null Identity(1, 1) Primary Key
        , Name nvarchar(50) Not Null Unique
    );
    
    Create Table dbo.tblPermissions
    (
        ID int Not Null Identity(1, 1) Primary Key
        , ObjectType int Not Null Foreign Key References dbo.tblObjectTypes (ID)
        , Value int Not Null Check (Value > 0)
        , Constraint UX_dbo_tblPermissions_UniqueValuePerObjectType Unique
        (
            ObjectType
            , Value
        )
    );
    
    Create Table dbo.tblObjects
    (
        ID int Not Null Identity(1, 1) Primary Key
        , Name nvarchar(50) Not Null Unique
        , ObjectType int Not Null Foreign Key References dbo.tblObjectTypes (ID)
    );
    
    

    Si en el punto 4 decidió que los permisos se asignan a tipo de objeto entonces creamos una tabla como esta:

    Create Table dbo.tblACL
    (
        ID int Not Null Identity(1, 1) Primary Key
        , Object int Not Null Foreign Key References dbo.tblObjects (ID)
        , SecurityPrincipal nvarchar(150) Not Null
        , AllowAccessMask int Not Null Default(0)
        , DenyAccessMask int Not Null Default(0)
    );

    Aquí hago una pausa:  No sé qué tipo de usuarios usa usted.  Si usa Active Directory, SecurityPrincipal podrían ser nombres de grupos de seguridad o nombres de usuarios.  Si no, sería major tener una tabla de usuarios y grupos de usuario (la misma tabla para ambos) y que SecurityPrincipal fuera un FK a esa tabla.

    Luego vamos a Allow y DenyAccessMask.  Como cada permiso es de sí o no, es muy cómodo usar un campo de 32 bit (tipo int en SQL Server) donde cada bit representa un permiso.  Ese bit estaría definido en el campo dbo.tblPermissions.Value.  Eso quiere decir que puede definer hasta 32 permisos diferentes para cada tipo de objeto.  Si no sabe de bitwise operations, este es el momento de aprender.

    Asumamos que tiene los siguientes permisos para objetos tipo "Estandar":

    • Leer, Value = 1 (primer bit)
    • Insertar, Value = 2 (Segundo bit)
    • Actualizar, Value = 4 (tercer bit)
    • Borrar, Value = 8 (cuarto bit)

    Queremos asignarle al usuario DOMINIO\usuario permisos de lectura y borrado al objeto Cliente que es de tipo estándar.

    Declare @objectID int;
    Select @objectID = ID
    From
        dbo.tblObjects
    Where
        Name = N'Cliente'
    ;
    Declare @readPerm int, @deletePerm int;
    Set @readPerm = 1;
    Set @deletePerm = 8;
    Insert Into dbo.tblACL (Object, SecurityPrincipal, AllowAccessMask)
    Values (@objectID, N'DOMINIO\usuario', @readPerm | @deletePerm);

    El valor final de AllowAccessMask es 1 | 8 = 9.

    DenyAccessMask serviría igual, pero no suelo usarlo.  Puede hacer una lógica compleja similar a permisos NTFS pero nunca he necesitado tal nivel de seguridad, así que le recomiendo en este punto ignorer este campo por el momento.  Para usarlo habría que definir prioridades de qué reemplaza qué y demás.  Si no se ocupa, major no se hace.

    En este punto usted ya tiene definida la seguridad.  No fue trivial pero espero que no haya sido demasiado complejo tampoco.

    ¿Cómo se usa esto?  Lo major es crear una function escalar que compruebe si un usuario tiene uno o más permisos.  Por ejemplo, un SP de borrado comprobaría que el usuario tenga permisos de borrado sobre el objeto en cuestión antes de proceder a borrarlo  llamando a una función que comprueba los valores en tblACL.

    El truco aquí está en descubrir si el usuario tiene el derecho basándose en membresía de grupo.  Cuando se usan grupos de Active Directory, SQL Server provee la función IsMember().  Si usted creó su propia tabla de Security Principals donde ahí se definen grupos, pues usted deberá usar un SELECT de su tabla de membresía de grupos para saber si un usuario pertenece o no a un grupo.

    Create Function dbo.fnHasPermissions
    (
        @userName nvarchar(150)
        , @requiredPermissions int
        , @objectID int
    )
    Returns bit
    As
    Begin
        if Exists(Select
            *
        From
            dbo.tblACL
        Where
            Object = @objectID
            And
            (
                SecurityPrincipal = @userName
                Or
                IsMember(SecurityPrincipal, @userName) = 1
            )
            And
            (AllowAccessMask & @requiredPermissions) = @requiredPermissions
        )
            Return 1;
        Return 0;
    End
    

    Algo así sería la función.  Es un SELECT basado en IsMember().  Si IsMember() da error con nombres de usuario en donde debería haber un nombre de grupo, deberá incluir en tblACL un campo IsGroup que dice qué SecurityPrincipals son grupos y qué no.  Sí, es una violación a la normalidad de la base de datos, pero es una que suelo pagar en este caso específico.  Si quiere seguir las reglas de normalización, deberá tener una tabla de security principals aún cuando sean de Active Directory.  Es decision suya.

    Como le decía, ese es un ejemplo.  Tal vez usted quiera trabajarlo diferente.  Lo importante aquí es ver la idea y el mecanismo:  Usamos BITWISE AND para saber si los registros seleccionados por las condiciones de objeto, SecurityPrincipal y membresía de grupo contienen exactamente los permisos almacenados en @requiredPermissions.  Si hay al menos un registro que sí los tiene, la función devuelve 1 (true).  Si quiere usar DenyAccessMask o tener una lógica más compleja, tal vez deberá cambiar esta sencilla funcionalidad.

    Entonces volviendo al SP que borra:

    Declare @objectID int;
    Set @objectID = dbo.fnGetObjectID(N'Cliente'); --Para facilidad hacemos una función.
    Declare @deletePerm int;
    Set @deletePerm = 8;
    If (dbo.fnHasPermissions(@userName, @deletePerm, @objectID) = 1)
    Begin
        Delete
        From
            dbo.tblClientes
        Where
            ID = @id;
    End
    Else
        Raiserror(N'No tiene permisos para realizar la operación de borrado de un cliente.', 16, 1);

    Y creo que ya cubrí al menos la mayoría. Fue bastante explicación. Es más fácil de lo que tardé explicando, jeje.


    Jose R. MCP
    Code Samples

    viernes, 16 de enero de 2015 16:22
    Moderador
  • Muchas gracias, hasta la creacion de tabla tblACL entendi bien, en mi caso tengo una tabla de usuarios, la tabla de grupo de usuarios a que se refiere? Luego en que parte se hace la asignacion de los permisos? se hace desde la aplicacion? o desde donde, podrias volver a repasarme esa parte? Saludos
    viernes, 16 de enero de 2015 17:48
  • Los grupos de usuario son objetos que agrupan usuarios que tienen roles en común.  Es bien molesto tener que asignarle los mismos permisos de usuarios a 30 usuarios distintos cuando puede uno hacer la asignación a un grupo y simplemente agregar usuarios (y remover) de los grupos.  Es mucho más fácil.

    Le aclaro que ACL en el nombre tblACL quiere decir Access Control List.  Se lo menciono porque es un término que puede buscar en Internet para aprender más del tema en general.  Cada entrada en el ACL es un ACE (Access Control Entry).

    La asignación de los permisos se hace así como muestra el bloque de código 3: Se inserta en la tabla tblACL un registro indicando qué permisos se le asignan a qué security principal, que puede ser un grupo o un usuario individual. Eso es T-SQL que puede usted correr desde SSMS, o puede ser T-SQL que se corre desde una aplicación de administración hecha en lo que usted quiera (asp.net, win forms, WPF).


    Jose R. MCP
    Code Samples

    viernes, 16 de enero de 2015 18:41
    Moderador
  • Entiendo, entonces resumiendo mi caso, como administracion la quiero hacer con winforms y como puedo diseñarlo para el caso en que un usuario que sea VENDEDOR tenga ciertos formularios habilitados como ser VENTAS, PRODUCTOS, ETC. me va servir el diagrama de la imagen que alce? o lo puedo hacer con las tablas que me dijo usted.

    Saludos

    Atte. Lorenzo Arce

    viernes, 16 de enero de 2015 19:23
  • Ok, para traducir el modelo de seguridad que yo le expuse hacia algo útil para "mostrar" gráficamente (por ejemplo, esconder botones de Borrar y cosas por el estilo), la interfase gráfica debe decidir qué permisos le interesan y averiguar si el usuario los tiene o no.

    Por ejemplo, un vendedor probablemente puede facturar, pero tal vez no puede crear nuevos clientes, solamente consultarlos.

    Entonces el formulario de Clientes, cuando carga, debería preguntarle a SQL Server a través de la función de SQL dbo.fnHasPermissions() si el usuario tiene permisos Leer, Actualizar, Insertar y Borrar.  Por cada respuesta negativa a cada una de esas últimas 3 preguntas, la interfase gráfica esconde los respectivos botones.  Además, si no puede Actualizar, entonces hacemos la grilla o las casillas de texto de sólo lectura.  Si además de no poder hacer cambios, no puede seleccionar (Leer), entonces tal vez el usuario recibe un MessageBox diciendo que la ventana de Clientes no está disponible para él o ella.

    ¿Contesta eso su pregunta?  Lo que quiero hacerle ver es:  La seguridad NO se diseña alrededor de una interfase gráfica.  La interfase gráfica, en cambio, se alinea a la seguridad existente y se adapta a ella lo mejor que pueda.


    Jose R. MCP
    Code Samples

    viernes, 16 de enero de 2015 20:44
    Moderador
  • Muchas Gracias, estoy entendiendo, la funcion isMember no me permite ejecutar en sql, me sale este error: Msg 195, Level 15, State 10, Procedure fnHasPermissions, Line 10
    'IsMember' is not a recognized built-in function name.

    Y lo cambie por is_Member y me sale este error: Msg 174, Level 15, State 1, Procedure fnHasPermissions, Line 10
    The is_member function requires 1 argument(s).

    Que puede faltarme?

    Saludos

    lunes, 19 de enero de 2015 12:42
  • Primero que nada: ¿Son sus usuarios usuarios de Active Directory? La función Is_Member() busca información en Active Directory.

    Segundo, viera que busqué la documentación de Is_Member() y resulta ser que no puede comprobar la membresía de otras cuentas de usuario distintas a la cuenta de usuario usada para hacer la conexión.  Esto debido a que la función lo que hace es examinar el token de usuario para determinar los SID's que le han sido asignados.  Si sus usuarios son de Active Directory pero usa una cuenta de servicio para conectar a SQL Server entonces Is_Member() no le funcionará  y necesitará crear su propia función.  En lo personal no usaría una cuenta de servicio.

    Finalmente, el mensaje de error que recibe dice que necesita pasar al menos un argumento.  Yo dejé un ejemplo con 2 argumentos, así que me parece curioso.  Le agradeceré muestre el código de su función.


    Jose R. MCP
    Code Samples

    lunes, 19 de enero de 2015 14:11
    Moderador
  • Los usuarios no son de Active Directory, ahi te envio mi funcion que quiero ejecutar
    lunes, 19 de enero de 2015 18:20
  • Entonces tiene que crear su propia versión de IsMember(). ¿Son usuarios definidos en su base de datos en una tabla tblUsuarios o algo así? Si es así, ¿tiene también por ahí una tabla tblGrupos o similar que define grupos de seguridad a los cuales se asignan usuarios mediante una tercera tabla?  Esta tabla tblGrupos define grupos pero a veces se le denomina roles o hasta perfiles.

    En fin, si respondió Sí a todas mis preguntas anteriores, una versión de IsMember puede ser algo así:

    Create Function dbo.IsMember
    (
        @nombreGrupo nvarchar(150)
        , @usuario nvarchar(150)
    )
    Returns Bit
    As
    Begin
        if Exists
        (
            Select
                au.*
            From
                tblGrupos As g
                Inner Join
                tblAsignacionUsuarios As au
                On au.IDGrupo = g.ID
                Inner Join
                tblUsuarios As u
                On au.IDUsuario = u.ID
            Where
                u.Name = @usuario
                And
                g.Name = @nombreGrupo
        )
            Return 1;
        Return 0;
    End

    Es una función sencilla que verifica si en la tabla de asignación de usuarios existe asignación para el usuario especificado y el grupo (o perfil, como quiera llamarle) especificado.  La función que escribí recibe como argumentos los nombres de grupo y de usuario, pero si piensa que puede manejar alguno (o ambos) como ID, entonces es más fácil porque no hay que hacer JOIN's a las tablas tblGrupos o tblUsuarios puesto que ya se tiene el ID correspondiente.


    Jose R. MCP
    Code Samples

    lunes, 19 de enero de 2015 22:32
    Moderador
  • Es asi que esta definido con tabla: usuario y perfil, en cuanto ala tabla de asignacion para que se usa porque yo no lo tengo, tengo que agregar esa tabla?.

    Saludos

    martes, 20 de enero de 2015 13:05
  • Sin una tercera tabla, ¿cómo sabe qué usuarios tiene asignados a qué perfiles?

    Jose R. MCP
    Code Samples

    martes, 20 de enero de 2015 14:33
    Moderador
  • Atraves de la siguiente relacion:

    Y cuales son los atributos que tengo que tener en la tecera tabla?

    martes, 20 de enero de 2015 15:09
  • Ya veo. Entonces un usuario solamente puede pertenecer a un perfil bajo ese modelo suyo. Si a usted le parece apropiado, a mí también. Es como a usted le parezca mejor, al fin y al cabo.

    Simplemente escriba una consulta dentro de la función IsMember() que se adapte a sus tablas.


    Jose R. MCP
    Code Samples

    martes, 20 de enero de 2015 15:15
    Moderador
  • Gracias y tengo que agregar la tabla de Asignacion de Permisos que columnas columnas debo poner en la tabla?
    martes, 20 de enero de 2015 17:56
  • No "tiene" que tenerla. Como le dije, sin la tercera tabla, que es básicamente una tabla de relación muchos-a-muchos, igual sirve. Solamente que tiene la limitante de que un usuario solamente puede pertenecer a un único perfil.

    Como mínimo la tercera tabla tiene que almacenar el ID de usuario y el ID del grupo (perfil) al cual se asigna el usuario.  Es una típica tabla muchos a muchos.


    Jose R. MCP
    Code Samples

    martes, 20 de enero de 2015 19:20
    Moderador
  • Buenas Jose, estimado llevo tiempo no accediendo aqui, sin embargo quiero retomar este caso..saludos
    jueves, 26 de mayo de 2016 19:56
  • Hola @webJose

    Asumamos que tiene los siguientes permisos para objetos tipo "Estandar":

    Leer, Value = 1 (primer bit)
    Insertar, Value = 2 (Segundo bit)
    Actualizar, Value = 4 (tercer bit)
    Borrar, Value = 8 (cuarto bit)

    ¿Que pasaría en vez de usar los Value = 1, Value = 2, usar directamente Leer, Insertar, Actualizar, Borrar?

    TypeObjeto = Standard ==> sus Permisos{1-Leer, 2-Insertar, 3-Actualizar, 4-Borrar} cada permiso tiene su id, utilizar el id de cada permiso para lo que se tenga que hacer.

    Saludos!


    Pedro Ávila
    "El hombre sabio querrá estar siempre con quien sea mejor que él."
    Lima - Perú

    viernes, 21 de junio de 2019 17:42