Filtern Sie den Zugriff auf Ihre Daten mit einem umfassenden System von Berechtigungen

Der Filterzugriff auf Daten ist eine unverzichtbare Funktion, um den böswilligen Zugriff auf Ihre Anwendung zu verhindern.

Bislang konnten Sie eine Datenklasse und einige ihrer Attribute als REST-Ressource freigeben oder nicht freigeben. Das war bereits ein bequemes Mittel, um den Zugriff auf Ihre Daten zu beschränken. Dennoch freuen wir uns, mit v19R8 ein leistungsfähiges und vollständig anpassbares System zum Schutz Ihrer Daten vor unbefugten Nutzern anbieten zu können. Ein System zum Schutz Ihrer Daten hängt davon ab, wer auf sie zugreift und auf welche Daten zugegriffen wird.

Wie Sie im Rahmen des Kundenaustauschs gefordert haben, können Sie nun mit vielen Benutzern umgehen, die an verschiedenen Unternehmen arbeiten, und den Zugriff auf Ihre Daten mit mehreren Granularitätsstufen abstimmen, von der allgemeinsten bis zur genauesten.

In Anlehnung an die skalierbaren Web-Sessions ermöglicht Ihnen diese Funktion den Aufbau einer zuverlässigen und geschützten Anwendung.

HDI_Zugriffsrechte

allgemeiner Kontext

Diese neue Funktionalität basiert auf ORDA-Konzepten und Websessions (genauer gesagt auf skalierbaren Web-Sessions).

Sie deckt alle Web-Prozesse ab, wie z.B. REST-Anfragen und Anfragen, die auf einem Remote-Datenspeicher empfangen werden, aber auch Web-Prozesse wie 4DACTION oder 4D-Tags.

Hauptkonzepte

In Ihrer Anwendung können Sie nun erlaubte Berechtigungen definieren.

Eine Berechtigung bezeichnet eine Ressource und die mit Aktionen auf dieser Ressource verbundenen Privilegien.

Ressourcen sind ein Datenklassenattribut, eine ORDA-Datenmodellfunktion, eine Datenklasse und der gesamte Datenspeicher.

Aktionen sind: Erstellen, Lesen, Aktualisieren, Löschen, Beschreiben, Ausführen (eine Funktion) und Weiterleiten (eine Funktion).

eine Berechtigung für ein Datenklassen-Attribut

Das Attribut personalNotes der Datenklasse Records kann von der Berechtigung medicalAction gelesen werden.

Ressource Records.personalNotes Privilegien
Lesen medicalAction

eine Berechtigung für eine Datenklassenfunktion

Die in der Datenklasse Records definierte Funktion deleteOldRecords() kann mit dem Privileg administrate ausgeführt werden.

Ressource Records.deleteOldRecords() Privilegien
Ausführen Verwalten

eine Berechtigung für eine Datenklasse

Die Datenklasse Records kann sowohl vom medicalAction- als auch vom administrate-Recht gelesen werden, und Entitäten können mit dem medicalAction-Recht erstellt werden.

Ressource Datensätze Privilegien
Lesen medicalAction, administrieren
Erstellen medicalAction

eine Berechtigung für den gesamten Datenspeicher

Das Administrationsrecht kann Entitäten in jeder Datenklasse des Datenspeichers löschen

Ressource ds Privilegien
Löschen Verwalten

Um Ihre benutzerdefinierten Regeln für Berechtigungen einzurichten, müssen Sie lediglich eine roles. json-Datei im Ordner Project/Sources Ihrer Anwendung erstellen.

Einige Rollen(d. h. eine Reihe von Privilegien) können auch von Ihnen selbst definiert und mit jedem Benutzer Ihrer Anwendung verknüpft werden.

Denken Sie daran, dass Sie einer skalierbaren Websession bestimmte Rechte zuordnen können. Wenn das System dann eine Anfrage erhält, wird geprüft, welche Berechtigungen des Benutzers in der Websession gespeichert sind und welche Aktionen für diese Berechtigungen in der Datei roles.json zulässig sind.

Ein Berechtigungsfehler wird ausgelöst, wenn die Aktion auf der Ressource nicht erlaubt ist.

Der Mechanismus im Detail

Wenn in der Websession keine Privilegien festgelegt wurden, handelt es sich um eine Gast-Session. Standardmäßig sind alle Daten für dieses Gastrecht zugänglich. Auch wenn Sie in der Datei roles.json keine Berechtigung festlegen, sind alle Daten für jeden zugänglich.

Danach kommen die von Ihnen in der Datei roles.json eingerichteten Berechtigungen ins Spiel und schränken den Zugriff auf die Daten ein.

Berechtigungen können für Ressourcen auf verschiedenen Granularitätsebenen eingerichtet werden. Diese Ressourcen sind im Folgenden nach Granularitätsstufen aufgeführt (von der allgemeinsten bis zur genauesten):

– der Datenspeicher
– eine Datenklasse
– ein Datenklassenattribut / eine Datenklassenfunktion

Die auf einer bestimmten Ebene eingerichteten Privilegien werden durch die auf einer genaueren Ebene festgelegten Privilegien außer Kraft gesetzt oder ergänzt.

Das nachstehende Diagramm zeigt eine anschaulichere Darstellung der Privilegien, die mit Aktionen auf einer Ressource verbunden sind.

Das Gastrecht kann Aktionen auf Ressourcen ausführen, die mit keinen Rechten verbunden sind. Sie schränken den Zugriff auf Ihre Daten ein, sobald Sie ein Privileg mit einer Ressource/Aktion verknüpfen.

TIPP: Wenn Sie möchten, dass Ihre Daten standardmäßig unerreichbar sind, verknüpfen Sie mit dem Datenspeicher ein „nobody“-Privileg für alle Aktionen und stellen Sie sicher, dass dieses Privileg niemals in die Sitzung aufgenommen wird.

Details mit Beispielen

Lassen Sie uns mit diesem einfachen Datenmodell arbeiten.

blank

 

In dieser Anwendung wollen wir diese Regeln implementieren:

  • nur das Administrationsrecht kann Entitäten auf dem gesamten Datenspeicher löschen und erstellen
  • die Datenklasse Patients kann nur von der Berechtigung medicalAction gelesen werden
  • das Attribut Records.personalNotes kann nur vom medicalAction-Privileg gelesen werden (auch wenn die Datenklasse von mehreren anderen Privilegien gelesen werden kann)
  • die in der Datenklasse Records definierte Funktion deleteOldRecords() kann nur vom administrate-Recht ausgeführt werden
  • eine Funktion authenticate() behandeln, die von jedem ausgeführt werden kann (Gastrecht)

 

das Administrator-Recht kann Entitäten im gesamten Datenspeicher löschen und erstellen

In der Datei roles.json haben wir ein administrate-Recht definiert. Dieses Privileg ist autorisiert zu:

  • löschen
  • erstellen

Entitäten in der gesamten datastore (alle Datenklassen).

Nur dieses Administrationsrecht ist berechtigt, diese Aktionen durchzuführen. Da standardmäßig alle Aktionen für alle Daten erlaubt sind und wir keine Berechtigung für die Leseaktion für den Datenspeicher zugewiesen haben, kann jeder alle Datenklassen des Datenspeichers lesen.

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

Die Datenklasse „Patienten“ kann nur mit der Berechtigung „medicalaction“ gelesen werden.

In der Datei roles.json haben wir ein medicalAction-Recht hinzugefügt.

Nur dieses medicalAction-Privileg ist berechtigt, die Datenklasse Patients zu lesen. Da diese Berechtigung auf Datenklassenebene eingerichtet ist, hat sie Vorrang vor den auf Datenspeicherebene eingerichteten Berechtigungen + den Gastberechtigungen. Daher kann nur die Berechtigung medicalAction die Datenklasse Patients lesen. Andere Datenklassen können von jedem gelesen werden.

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

Das Attribut records.personalnotes ist nur für die Berechtigung medicalaction lesbar.

In diesem Beispiel haben wir ein readRecords-Recht hinzugefügt. Da das readRecords-Recht im medicalAction-Recht enthalten ist, kann das medicalAction-Recht alle für das readRecords-Recht zulässigen Aktionen ausführen.

Sowohl readRecords als auch medicalAction können die Datenklasse Records lesen, aber das Attribut personalNotes kann nur von der Berechtigung medicalAction gelesen werden.

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

Die Funktion deleteoldrecords der Datensatzklasse ist nur mit dem administrate-Recht ausführbar.

Da im folgenden Beispiel nur der Administrator des Systems alte Datensätze löschen darf, haben wir für das Administratorrecht das Recht hinzugefügt, die Funktion deleteOldRecords() auszuführen, die in der Datenklasse Records definiert ist.

Nur dieses Privileg kann sie ausführen.

Wir haben dem Administrationsprivileg auch die Berechtigung hinzugefügt, die Records-Datenklasse zu lesen, da das Lesen der Entitäten erforderlich ist, um sie zu löschen.

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

Handhabung einer von einem Gast ausführbaren Authentifizierungsfunktion

Um zu verhindern, dass ein fremder Benutzer eine Funktion in unserer Anwendung ausführt, haben wir die Ausführung von Funktionen auf der Datenspeicherebene auf das Recht none beschränkt (es wird nie in die Websession gestellt).

In unserem System haben wir eine authenticate() Funktion (definiert in der DataStore Klasse), die von Benutzern ausgeführt werden soll, um die Anwendung zu betreten. Wir haben die Berechtigung zur Ausführung dieser Funktion authenticate() hinzugefügt.

Da sie von jedem ausgeführt werden kann, wurde die Ausführungsaktion für das Gastrecht festgelegt. Wir haben auch die hr-Berechtigung hinzugefügt, um zu verhindern, dass die Datenklasse Users von jemandem gelesen wird, der nicht zur Anwendung gehört.

Die Funktion authenticate() muss die Datenklasse Users lesen, um die Existenz und das Passwort des Benutzers zu überprüfen. Daher wird sie mit dem hr-Recht befördert. Die Promote-Aktion fügt ein Privileg in der Web-Session hinzu (nur während der Ausführung der Funktion).

{ "privileges": [ {"privilege": "administrate"}, {"privilege": "readRecords"}, {"privilege": "medicalAction", "includes": ["readRecords"] }, {"privilege":"hr"}, {"privilege":"keine"} ],
 "roles": [ {} ],
 "permissions": {
  "erlaubt": [
   {"applyTo": "ds", "type": "datastore", "drop": ["administrate"], "create": ["administrate"], "execute": ["none"] },
   {"applyTo": "Patients", "type": "dataclass", "read": ["medicalAction"] },
   {"applyTo": "Benutzer", "Typ": "dataclass", "read": ["hr"] },
   {"applyTo": "Datensätze", "Typ": "dataclass", "read": ["readRecords", "administrate"] },
   {"applyTo": "Records.personalNotes", "type": "attribute", "read": ["medicalAction"] },
   {"applyTo": "Records.deleteOldRecords", "type": "method", "execute": ["administrate"] },
   {"applyTo": "ds.authenticate", "type": "method", "promote": ["hr"], "execute": ["guest"]
   }
  ]
 }
}

die Autentifizierungsphase

In der Datei roles.json können Sie Rollen definieren, d . h. eine Reihe von Berechtigungen. Im folgenden Beispiel haben wir die Rolle “ The Secretary“ (Die Sekretärin) hinzugefügt, die die Berechtigungen createPatient und readRecords enthält.

Die mit dieser Rolle verbundenen Benutzer können alle Aktionen ausführen, die für die Privilegien createPatient und readRecords (einen neuen Patienten anlegen und Datensätze lesen) zulässig sind.

{ "Privilegien": [ { "privilege": "administrate" }, {"privilege":"readRecords" }, {"privilege": "medicalAction", "includes": ["readRecords"] }, {"privilege": "hr"  }, {"privilege": "keine"},
  {"privilege":"createPatient" } ],
 "Rollen": [ {"role":"The Secretary", "privileges": ["createPatient","readRecords" ] } ],
 "permissions": {
  "allowed": [
   {"applyTo": "ds", "type": "datastore", "drop": ["verwalten"], "erstellen": ["verwalten"], "ausführen": ["none"] },
   {"applyTo": "Patients", "type": "dataclass", "read": ["medicalAction"], "create": ["createPatient"] },
   {"applyTo": "Users", "type": "dataclass", "read": ["hr"] },
   {"applyTo": "Datensätze", "Typ": "dataclass", "read": ["readRecords", "administrate"] },
   {"applyTo": "Records.personalNotes", "type": "attribute", "read": ["medicalAction"] },
   {"applyTo": "Records.deleteOldRecords", "type": "method", "execute": ["administrate"] },
   {"applyTo": "ds.authenticate", "type": "method", "promote": ["hr"], "execute": ["guest"] }
  ]
 }
}

In Ihrer Anwendung müssen Sie jeden Benutzer einer Rolle in einer Datenklasse zuordnen (in diesem Beispiel die Datenklasse Users ).

Hier ist die Datenklasse

blank

und die Daten

blank

 

Während der Authentifizierungsphase können Sie die mit dieser Rolle verbundenen Berechtigungen in die Web-Session einfügen.

Hier ist ein Beispiel für eine authenticate() Funktion.

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 

Lesen Sie die Dokumentation sorgfältig durch, um mehr über die Berechtigungen zu erfahren, und laden Sie das obige HDI herunter, um ein Demo-Beispiel auszuführen.

Diskutieren Sie gerne im Forum.

Avatar
- Product Owner - Marie-Sophie Landrieu-Yvert ist seit 2017 als Product Owner im 4D Produktteam tätig. Als Product Owner ist sie für das Schreiben der User Stories und deren Umsetzung in funktionale Spezifikationen zuständig. Ihre Aufgabe ist es auch, sicherzustellen, dass die Implementierung der Funktionen den Anforderungen des Kunden entspricht. Marie-Sophie ist Absolventin der ESIGELEC Ingenieurschule und begann ihre Karriere als Ingenieurin bei IBM im Jahr 1995. Sie nahm an verschiedenen Projekten teil (Wartungs- oder Build-Projekte) und arbeitete als Cobol-Entwicklerin. Dann arbeitete sie als UML-Designerin und Java-Entwicklerin. In letzter Zeit bestand ihre Hauptaufgabe darin, funktionale Anforderungen zu analysieren und zu schreiben sowie Geschäfts- und Entwicklungsteams zu koordinieren.