Filtre el acceso a sus datos gracias a un completo sistema de permisos

Filtrar el acceso a los datos es una funcionalidad imprescindible para evitar accesos maliciosos a su aplicación.

Hasta ahora, podía exponer o no como recurso REST una clase de datos y algunos de sus atributos. Ya era un medio práctico para restringir el acceso a sus datos. Aún así, estamos encantados de ofrecer en la v19R8 un sistema poderoso y totalmente personalizable para proteger sus datos de usuarios no autorizados. Un sistema de protección de sus datos depende de quién accede a ellos y a qué datos se accede.

Tal y como no lo han pedido durante los intercambios con los clientes, ahora pueden gestionar muchos usuarios que trabajen en diferentes actividades y regular el acceso a sus datos con varios niveles de granularidad, desde el más general al más preciso.

Siguiendo con las sesiones web escalables, esta funcionalidad le permite construir una aplicación fiable y protegida.

HDI_Permisos

contexto general

Esta nueva funcionalidad se basa en los conceptos ORDA y las sesiones web (más concretamente en las sesiones web escalables).

Cubre todos los procesos web como las peticiones REST y las peticiones recibidas en un almacén de datos remoto, pero también procesos web como 4DACTION o 4D tags.

conceptos principales

En su aplicación, ahora puede definir los permisos autorizados.

Un permiso indica un recurso y los privilegios asociados a las acciones sobre este recurso.

Los recursos son un atributo de clase de datos, una función del modelo de datos ORDA, una clase de datos y todo el almacén de datos.

Las acciones son: crear, leer, actualizar, borrar, describir, ejecutar (una función) y promover (una función).

UN Permiso para un atributo DE CLASE DE datOS

El atributo personalNotes de la clase de datos Records puede ser leído por el privilegio medicalAction.

Recurso Records.personalNotes Privilegios
Leer medicalAction

un permiso para una función de clase de datos

La función deleteOldRecords() definida en la clase de datos Records puede ser ejecutada por el privilegio administrate.

Recurso Records.deleteOldRecords() Privilegios
Ejecutar administrate

un Permiso para una clase de datos

Los privilegios medicalAction y administrate pueden leer la clase de datos Records, y el privilegio medicalAction puede crear entidades.

Recurso Records Privilegios
Lectura medicalAction, administrate
Crear medicalAction

un permiso para todo el almacén de datos

El privilegio administrate puede soltar entidades en cualquier dataclass del datastore

Recurso ds Privilegios
Soltar administrate

Para configurar sus reglas personalizadas para los permisos, sólo tiene que crear un archivo roles.json en la carpeta Project/Sources de su aplicación.

Algunos roles (es decir, un conjunto de privilegios) también pueden ser definidos y asociados por usted mismo a cada usuario de su aplicación.

Recuerde que puede asociar algunos privilegios a una sesión web escalable. Entonces, cuando el sistema recibe una petición, se realiza un control sobre los privilegios del usuario almacenados en la sesión web y las acciones autorizadas para esos privilegios en el archivo roles.json.

Se genera un error de permiso si la acción sobre el recurso no está permitida.

el mecanismo en detalle

Cuando no se han definido privilegios en la sesión web, se trata de una sesión invitado. Por defecto, todos los datos son accesibles para este privilegio invitado. Además, si no se define ningún permiso en el archivo roles.json, todos los datos son accesibles por cualquier persona.

A continuación, los permisos configurados en el archivo roles.json entran en juego y restringen el acceso a los datos.

Los permisos se pueden configurar para los recursos en varios niveles de granularidad. Esos recursos se listan a continuación por niveles de granularidad (del más general al más preciso):

– el almacén de datos
– una clase de datos
– un atributo de clase de datos / una función de clase de datos

Los privilegios establecidos en un nivel determinado son anulados o completados por los privilegios especificados en un nivel más preciso.

El siguiente diagrama ofrece una representación más gráfica de los privilegios asociados a acciones sobre algún recurso.

El privilegio invitado puede ejecutar acciones sobre recursos asociados a ningún privilegio. Usted limita el acceso a sus datos en cuanto asocia un privilegio a una pareja recurso/acción.

CONSEJO: si quiere que sus datos sean inaccesibles por defecto, asocie al datastore un privilegio nobody para todas las acciones y asegúrese de que este privilegio nunca se pondrá en la sesión.

entrar en LOS detalles con ejemplos

Trabajemos con este sencillo modelo de datos.

blank

 

En esta aplicación, queremos implementar estas reglas:

  • sólo el privilegio administrador puede eliminar y crear entidades en todo el almacén de datos
  • la clase de datos Patients sólo puede ser leída por el privilegio medicalAction
  • el atributo Records.personalNotes sólo puede ser leído por el privilegio medicalAction (aunque la clase de datos pueda ser leída por otros privilegios)
  • la función deleteOldRecords() definida en la clase de datos Records sólo puede ser ejecutada por el privilegio administrate
  • manipular una función authenticate() ejecutable por cualquiera (privilegio invitado)

 

El privilegio de administrador puede crear y eliminar entidades en todo el almacén de datos.

En el siguiente archivo roles.json, hemos definido un privilegio administrate. Este privilegio está autorizado a

  • soltar
  • crear

entidades en todo el datastore (todas las clases de datos).

Sólo este privilegio administrate está autorizado a realizar estas acciones. Como por defecto, todas las acciones están permitidas sobre todos los datos, y no hemos asociado ningún privilegio para la acción leer para el datastore, cualquiera puede leer todas las clases de datos del datastore.

{"privileges": [{"privilege": "administrate"}],
 "roles": [{}],
 "permissions": {
 "allowed": [{"applyTo": "ds","type": "datastore","drop": ["administrate"],"create": ["administrate"]}]
 }
}

la clase de datos patients solo puede ser leida por el privilegio medicalaction

En el siguiente archivo roles.json, hemos añadido un privilegio medicalAction.

Sólo este privilegio medicalAction está autorizado a leer la clase de datos Patients. Dado que este permiso se establece a nivel de la clase de datos, anula los permisos establecidos a nivel del almacén de datos + los permisos invitado. Por lo tanto, sólo el privilegio medicalAction puede leer la clase de datos Patients. Las demás clases de datos pueden ser leídas por todos.

{ "privileges": [{"privilege": "administrate"},{"privilege": "medicalAction"}],
 "roles": [ {} ],
 "permissions": 
  {"allowed": [
      {"applyTo": "ds","type": "datastore","drop": ["administrate"],"create": ["administrate"] },
      {"applyTo": "Patients", "type": "dataclass", "read": ["medicalAction"] }
  ]
 }
}

el atributo records.personalnotes sólo puede ser leído por el privilegio medicalaction

En este ejemplo, hemos añadido un privilegio readRecords. Dado que el privilegio readRecords está incluido en el privilegio medicalAction, el privilegio medicalAction puede ejecutar todas las acciones permitidas para el privilegio readRecords.

Tanto el privilegio readRecords como el privilegio medicalAction pueden leer la clase de datos Records, pero el atributo personalNotes sólo puede ser leído por el privilegio medicalAction.

{ "privileges": [{"privilege": "administrate"}, {"privilege": "readRecords"}, {"privilege": "medicalAction","includes": ["readRecords"] } ],
 "roles": [ {} ],
 "permissions": {
  "allowed": [
   {"applyTo": "ds", "type": "datastore", "drop": ["administrate"], "create": ["administrate"] },
   {"applyTo": "Patients", "type": "dataclass", "read": ["medicalAction"] },
   {"applyTo": "Records", "type": "dataclass", "read": ["readRecords"] },
   {"applyTo": "Records.personalNotes", "type": "attribute", "read": ["medicalAction"] }
  ]
 }
}

La función deleteoldrecords de la clase de datos records sólo puede ser ejecutada por el privilegio administrate.

En el ejemplo siguiente, como sólo el administrador del sistema debe poder borrar los registros antiguos, hemos añadido para el privilegio administrate el permiso para ejecutar la función deleteOldRecords() definida en la clase de datos Records.

Sólo este privilegio puede ejecutarla.

También hemos añadido el permiso para que el privilegio administrate pueda leer la clase de datos Records porque la lectura de las entidades es necesaria para eliminarlas.

{ "privileges": [ {"privilege": "administrate"}, {"privilege": "readRecords"}, {"privilege": "medicalAction", "includes": ["readRecords"] } ], "roles": [ {} ],
 "permissions": {
  "allowed": [
   {"applyTo": "ds", "type": "datastore", "drop": ["administrate"], "create": ["administrate"] },
   {"applyTo": "Patients", "type": "dataclass", "read": ["medicalAction"] },
   {"applyTo": "Records", "type": "dataclass", "read": ["readRecords","administrate"] },
   {"applyTo": "Records.personalNotes", "type": "attribute", "read": ["medicalAction"] },
   {"applyTo": "Records.deleteOldRecords", "type": "method", "execute": ["administrate"] }
  ]
 }
}

manejar una función de autenticación ejecutable para un invitado

Para evitar que un usuario ajeno ejecute una función en nuestra aplicación, hemos restringido la ejecución de funciones a nivel de datastore al privilegio none (nunca se pone en la sesión web).

En nuestro sistema, tenemos una función authenticate() (definida en la clase DataStore) que debe ser ejecutada por los usuarios para entrar en la aplicación. Hemos añadido un permiso para ejecutar esta función authenticate().

Debido a que debe ser ejecutable por cualquier persona, la acción ejecutar ha sido definida para el privilegio guest. También hemos añadido los privilegios hr para evitar que la clase de datos Users sea leída por alguien ajeno a la aplicación.

La función authenticate() necesita leer la clase de datos Users para verificar la existencia y la contraseña del usuario. Por lo tanto, se promueve con el privilegio hr. La acción de promoción añade un privilegio en la sesión web (sólo durante la ejecución de la función).

{ "privileges": [ {"privilege": "administrate"}, {"privilege": "readRecords"}, {"privilege": "medicalAction", "includes": ["readRecords"] }, {"privilege": "hr"}, {"privilege": "none"} ], "roles": [ {} ], "permissions": {
  "allowed": [
   {"applyTo": "ds", "type": "datastore", "drop": ["administrar"], "crear": ["administrate"], "execute": ["none"] },
   {"applyTo": "Patients", "type": "dataclass", "read": ["medicalAction"] },
   {"applyTo": "Users", "type": "dataclass", "read": ["hr"] },
   {"applyTo": "Records", "type": "dataclass", "read": ["readRecords", "administrate"] },
   {"applyTo": "Records.personalNotes", "type": "attribute", "read": ["medicalAction"] },
   {"applyTo": "Records.deleteOldRecords", "type": "method", "execute": ["administrar"] },
   {"applyTo": "ds.authenticate", "type": "method", "promote": ["hr"], "execute": ["guest"]
   }
  ]
 }
}

la fase de autenticación

En el archivo roles.json, puede definir roles: es decir, un conjunto de privilegios. En el ejemplo siguiente, hemos añadido el rol de The Secretary que contiene los privilegios createPatient y readRecords.

Los usuarios asociados a este rol pueden ejecutar todas las acciones permitidas para los privilegios createPatient y readRecords (crear un nuevo paciente y leer los registros).

{ "privileges": [ { "privilege": "administrate" }, {"privilege": "readRecords" }, {"privilege": "medicalAction", "includes": ["readRecords"] }, {"privilege": "hr" }, {"privilege": "none"},
 {"privilege": "createPatient" } ],
 "roles": [ {"role": "The Secretary","privileges": ["createPatient","readRecords" ] } ],
 "permissions": {
  "allowed": [
   {"applyTo": "ds", "type": "datastore", "drop": ["administrate"], "create": ["administrate"], "execute": ["none"] },
   {"applyTo": "Patients", "type": "dataclass", "read": ["medicalAction"], "create": ["createPatient"] },
   {"applyTo": "Users", "type": "dataclass", "read": ["hr"] },
   {"applyTo": "Records", "type": "dataclass", "read": ["readRecords", "administrate"] },
   {"applyTo": "Records.personalNotes", "type": "attribute", "read": ["medicalAction"] },
   {"applyTo": "Records.deleteOldRecords", "type": "method", "execute": ["administrar"] },
   {"applyTo": "ds.authenticate", "type": "method", "promote": ["hr"], "execute": ["guest"] }
  ]
 }
}

En su aplicación, debe asociar cada usuario a un rol en una clase de datos (la clase de datos Users en este ejemplo).

Esta es la clase de datos

blank

y los datos

blank

 

Durante la fase de autenticación, puede poner los privilegios asociados a este rol en la sesión web.

He aquí un ejemplo de función authenticate().

exposed Function authenticate($identifier : Text; $password : Text) : Text
	
var $user : cs.UsersEntity
	
Session.clearPrivileges()
	
$user:=ds.Users.query("identifier = :1"; $identifier).first()
	
If ($user#Null)
	If (Verify password hash($password; $user.password))
		Session.setPrivileges(New object("roles"; $user.role))
		return "Your are authenticated as "+$user.role
	Else 
		return "Your are authenticated as Guest"
	End if 
Else 
	return "Your are authenticated as Guest"
End if 

Lea atentamente la documentación para saber más sobre los permisos, y descargue el IDH anterior para ejecutar un ejemplo de demostración.

No dude en iniciar discusiones en el foro.

Avatar
• Propietario de producto - Marie-Sophie Landrieu-Yvert ingresó al equipo de 4D Product como Propietario de producto en 2017. Como tal, está a cargo de escribir las historias de los usuarios y luego traducirlas en especificaciones funcionales. Su papel es también asegurarse de que la implementación de la funcionalidad entregada cumpla con las necesidades del cliente. Marie-Sophie se graduó en la Escuela de Ingeniería de ESIGELEC y comenzó su carrera como ingeniera en IBM en 1995. Participó en varios proyectos (de mantenimiento y creación) y trabajó como desarrolladora de Cobol. Luego trabajó como diseñadora de UML y desarrolladora de Java. Sus principales funciones fueron analizar y redactar requisitos funcionales, coordinar los equipos de negocio y de desarrollo.