Ich versuche, ein flexibles ACL-Framework in Java für meine Anwendung zu erstellen.
Viele ACL-Frameworks basieren auf einer Whitelist von Regeln, wobei eine Regel die Form Eigentümer: Aktion: Ressource hat . Beispielsweise,
- "JOHN kann die Ressource FOOBAR-1 ANZEIGEN"
- "MARY kann die Ressource FOOBAR-1 ANZEIGEN"
- "MARY kann Ressource FOOBAR-1 BEARBEITEN"
Dies ist attraktiv, da die Regeln einfach in einer Datenbank serialisiert / beibehalten werden können. Meine Anwendung verfügt jedoch über eine komplexe Geschäftslogik. Beispielsweise,
- "Alle Benutzer in Abteilung 1 mit einem Dienstalter von über 5 Jahren können die Ressource FOOBAR-1 ANZEIGEN, die sonst nicht autorisiert ist."
- "Alle Benutzer in Abteilung 2 können die Ressource FOOBAR-2 anzeigen, wenn das Datum nach dem 15.03.2016 liegt. Andernfalls sind sie nicht autorisiert."
Auf den ersten Blick wäre es ein Alptraum, ein Datenbankschema zu entwickeln, das mit unendlich komplexen Regeln wie diesen umgehen kann. Daher scheint es, als müsste ich sie in die kompilierte Anwendung "backen", sie für jeden Benutzer auswerten und dann als Ergebnis der Auswertung Regeln für Eigentümer: Aktion: Ressource erstellen . Ich möchte vermeiden, die Logik in die kompilierte Anwendung einzubinden.
Daher habe ich mir überlegt, eine Regel in Form eines Prädikats darzustellen : action: resource , wobei das Prädikat ein boolescher Ausdruck ist, der festlegt, ob ein Benutzer zulässig ist. Das Prädikat wäre eine Zeichenfolge eines JavaScript-Ausdrucks, der von Javas Rhino-Engine ausgewertet werden könnte. Beispielsweise,
return user.getDept() == 1 && user.seniority > 5;
Auf diese Weise können die Prädikate problemlos in der Datenbank gespeichert werden.
Ist das schlau ? Ist das schlampig ? Ist das eine Spielerei ? Ist das überarbeitet ? Ist das sicher (anscheinend kann Java die Rhino Engine sandboxen).
quelle
Antworten:
Das Weiterleiten dynamischer Daten in einen Interpreter Ihrer Implementierungssprache ist in der Regel eine schlechte Idee, da hierdurch die Möglichkeit einer Datenbeschädigung in die Möglichkeit einer böswilligen Übernahme von Anwendungen eskaliert. Mit anderen Worten, werden Sie aus dem Weg zu schaffen , eine Code - Injektion Verwundbarkeit.
Ihr Problem kann besser durch eine Regelengine oder möglicherweise eine domänenspezifische Sprache (DSL) gelöst werden . Schauen Sie sich diese Konzepte an, Sie müssen das Rad nicht neu erfinden.
quelle
==
anstelle von===
in Ihrem Beispiel verwendet. Wollen Sie wirklich vollständige Angaben machen, wenn alle Regeln wohl immer enden sollten? Warum schreiben Sie nicht einfach einen einfachen Parser und Interpreter, wie Kilian es vorgeschlagen hat, anstatt durch die Rahmen zu springen, um sicherzustellen, dass alle Interaktionen zwischen Java und JavaScript koscher sind? Es wird viel einfacher sein, auf Ihre Bedürfnisse zuzuschneiden und zu sichern. Benutze ANTLR oder so.while (true) ;
Ich habe das getan, und ich empfehle Ihnen, das nicht zu tun.
Ich habe die gesamte Geschäftslogik in Lua geschrieben und dieses Lua-Skript in einer Datenbank gespeichert. Beim Start meiner Anwendung wurde das Skript geladen und ausgeführt. Auf diese Weise konnte ich die Geschäftslogik meiner Anwendung aktualisieren, ohne eine neue Binärdatei zu verteilen.
Ich habe immer festgestellt, dass ich die Binärdatei immer aktualisieren muss, wenn ich Änderungen vornehme. Einige Änderungen wurden im Lua-Skript vorgenommen, aber ich hatte immer eine Liste der Änderungen, die vorgenommen werden mussten, und so musste ich fast immer einige Änderungen in der Binärdatei und einige Änderungen im Lua-Skript vornehmen. Meine Vorstellung, dass ich es vermeiden könnte, ständig Binärdateien zu verteilen, kam einfach nicht auf.
Ich fand es viel hilfreicher, die Verteilung von Binärdateien zu vereinfachen. Meine Anwendung sucht beim Start automatisch nach Updates, lädt diese herunter und installiert sie. Meine Benutzer sind also immer auf den neuesten Binärdateien, die ich gepusht habe. Es gibt fast keinen Unterschied zwischen einer Änderung in der Binärdatei und einer Änderung in den Skripten. Wenn ich es noch einmal machen würde, würde ich mich noch mehr bemühen, das Update nahtlos zu machen.
quelle
Ich hätte nicht die Datenbank Code enthalten. Sie können jedoch etwas Ähnliches tun, indem Sie die Datenbank Funktionsnamen enthalten lassen und diese dann mithilfe von Reflection aufrufen. Wenn Sie eine neue Bedingung hinzufügen, müssen Sie sie zu Ihrem Code und Ihrer Datenbank hinzufügen. Sie können jedoch Bedingungen und Parameter kombinieren, die an sie übergeben werden, um recht komplexe Auswertungen zu erstellen.
Mit anderen Worten, wenn Sie über nummerierte Abteilungen verfügen, ist es einfach, eine UserDepartmentIs-Prüfung und eine TodayIsAfter-Prüfung durchzuführen und diese dann zu einer Abteilung = 2 und Today> 15.03.2016 zu kombinieren. Wenn Sie dann eine TodayIsBefore-Überprüfung durchführen möchten, damit Sie das Datum der Berechtigung beenden können, müssen Sie die TodayIsBefore-Funktion schreiben.
Ich habe dies nicht für Benutzerberechtigungen getan, sondern für die Datenüberprüfung, aber es sollte funktionieren.
quelle
XACML ist die Lösung, nach der Sie wirklich suchen. Es handelt sich um eine Art Regelmodul, das sich nur auf die Zugriffssteuerung konzentriert. XACML, ein von OASIS definierter Standard, besteht aus drei Teilen:
Die Architektur ist wie folgt:
So sieht Ihr erster Anwendungsfall aus:
Ihr zweiter Anwendungsfall wäre:
Sie können beide Anwendungsfälle in einer einzigen Richtlinie kombinieren, indem Sie Verweise verwenden:
Und du bist fertig!
Weitere Informationen zu XACML und ALFA finden Sie unter:
quelle
Was Sie hier wirklich wollen, ist XACML . Es gibt Ihnen so ziemlich genau das, was Sie wollen. Sie müssen nicht unbedingt die gesamte Architektur implementieren, da alle Rollen vollständig voneinander getrennt sind. Wenn Sie nur eine einzige Anwendung haben, können Sie wahrscheinlich mit balana die Integration von PDP und PEP in Ihre App vermeiden Ihre vorhandene Benutzerdatenbank ist.
Jetzt erstellen Sie überall in Ihrer App, wo Sie etwas autorisieren müssen, eine XACML-Anforderung, die den Benutzer, die Aktion und den Kontext enthält, und die XACML-Engine trifft die Entscheidung auf der Grundlage der von Ihnen geschriebenen XACML-Richtliniendateien. Diese Richtliniendateien können in der Datenbank, im Dateisystem oder an einem beliebigen Ort gespeichert werden, an dem die Konfiguration gespeichert werden soll. Axiomatics bietet eine nette Alternative zur XACML-XML-Darstellung namens ALFA, die etwas einfacher zu lesen ist als die unformatierte XML-Darstellung, und ein Eclipse-Plugin zum Generieren von XACML-XML aus ALFA-Richtlinien.
quelle
Das haben wir in meiner jetzigen Firma gemacht und wir sind sehr zufrieden mit den Ergebnissen.
Unsere Ausdrücke sind in js geschrieben und wir verwenden sie sogar, um die Ergebnisse einzuschränken, die Benutzer durch die Abfrage von ElasticSearch erhalten können.
Der Trick besteht darin, sicherzustellen, dass genügend Informationen zur Verfügung stehen, um die Entscheidung zu treffen, sodass Sie wirklich schreiben können, was immer Sie möchten, ohne Codeänderungen, aber gleichzeitig schnell.
Wir sind nicht wirklich besorgt über Code-Injection-Angriffe, da die Berechtigungen von denen geschrieben werden, die das System nicht angreifen müssen. Gleiches gilt für DOS-Attacken wie die
while(true)
Beispiel. Die Administratoren des Systems müssen das nicht tun, sie könnten einfach alle Berechtigungen entfernen ...Aktualisieren:
So etwas wie XACML scheint als zentraler Authentifizierungsverwaltungspunkt für eine Organisation besser zu sein. Unser Anwendungsfall unterscheidet sich insofern geringfügig, als unsere Kunden typischerweise keine IT-Abteilung haben, um all dies auszuführen. Wir brauchten etwas Eigenständiges, versuchten aber, so viel Flexibilität wie möglich zu bewahren.
quelle