Ich bin an meinem Interface - Design suchen , und ich kämpfe , um zu entscheiden , welche die „richtige“ Art und Weise ist die rollenbasierte Zugriffssteuerung zu implementieren, einen gegebenen user
und ein , subject
dass die für user
den Zugriff möchte.
Soweit ich sehen kann, habe ich drei Kernoptionen (wobei eine vierte eine Bastardisierung der ersten drei und eine fünfte eine Optimierung der vierten ist):
- Fragen Sie das
subject
mit einer Liste von Berechtigungen ab, die dasuser
hat -subject.allowAccess(user.getPermissionSet)
- Fragen Sie die
user
mit einer Liste der Berechtigungen ab, diesubject
erforderlich sind -user.hasPermissionTo(subject.getRequiredPermissions())
- Fragen Sie einen Drittanbieter ab, um die Schnittpunkte der Berechtigungen zu ermitteln.
accessController.doPermissionSetsIntersect(subject.permissionSet, user.getPermissionSet())
- Fragen Sie entweder das
subject
/ abuser
, während Sie die "Entscheidung" an eine Drittanbieterklasse delegieren - Haben Sie den
user
Versuch , die für den Zugriff aufsubject
und wirft einen Fehler , wenn der Zugriff nicht erlaubt ist
Ich neige zu Option vier - Lassen Sie das Feld subject
enthalten accessController
, in dem Aufrufe zum subject.userMayAccess(User user)
Delegieren der Operation a la:
class Subject {
public function display(user) {
if(!accessController.doPermissionSetsIntersect(this.permissionSet, user.getPermissionSet())) {
display403(); //Or other.. eg, throw an error..
}
}
}
.. aber dann wirft dies weitere Fragen auf:
- sollte das
accessController
ein Feld gegen eine statische Klasse sein ..? - Sollte jemand
subject
wissen, welche Berechtigungen erforderlich sind, um es anzeigen zu können? - Wo kommt hier das Prinzip des geringsten Wissens in Bezug auf die Berufung ins Spiel
subject.display()
? Sollten Anrufersubject.display()
jemals wissen, dass die Zugriffskontrolle wirksam ist? (Wosubject.display()
ist eine endgültige "Vorlagenmethode") - Haben Sie
subject.display()
die Zugriffskontrolle verwaltet und eine Ausnahme ausgelöst, bei der der Benutzer nicht über die erforderliche Berechtigung verfügt?
Was würde in dieser Situation als "Best Practice" angesehen? Wo sollte die Verantwortung für die Durchführung der Prüfungen tatsächlich liegen?
Da dies sowohl eine akademische Übung als auch eine Umsetzung ist, sind Verweise auf Entwurfsmuster willkommen.
Ich denke, Ihre Option 3 ist die nächstgelegene, aber anstatt die
user
undsubject
über ihre Berechtigungssätze abzufragen, sollten Sie dasuser
undsubject
an den Zugriffscontroller übergeben.Der Zugriffscontroller sollte sowohl dafür verantwortlich sein, die Berechtigungssätze abzurufen als auch zu überprüfen, ob der Zugriff ausreichend ist. Auf diese Weise isolieren Sie sowohl die Speicherlogik als auch die Überprüfungslogik in Ihrem Zugriffscontroller, getrennt von Benutzer und Subjekt.
Das andere Element, das in Ihrem Beispiel möglicherweise fehlt, ist, welche Operation ausgeführt wird. Einige Benutzer können das Recht haben , einige Daten zu lesen , aber nicht zu aktualisieren, zu löschen, führen usw. So haben Sie eine haben könnten
checkAccess
Methode auf den Access - Controller mit drei Parametern:user
,subject
,operation
. MöglicherweisecheckAccess
möchten Sie auch einige zusätzliche Informationen zurückgeben , um Informationen darüber zurückzugeben, warum der Zugriff nicht gewährt wurde.Wenn Sie dies beispielsweise später an den Zugriffscontroller delegieren, können Sie die Darstellung Ihrer Berechtigungen ersetzen. Sie können mit der rollenbasierten Zugriffskontrolle beginnen und später zur anspruchsbasierten wechseln. Sie können Berechtigungen zunächst in einer einfachen Struktur speichern und später hierarchische Gruppen / Rollen und zulässige Operationen für verschiedene Arten von Themen hinzufügen. Wenn Sie Ihre Berechtigungssätze nicht in die Benutzeroberfläche einfügen, können Sie dies aktivieren.
Ob Sie AOP oder einen Boilerplate-Code verwenden, um dies anzuschließen, ist meiner Meinung nach weniger wichtig.
quelle