Patrzę na projekt interfejsu i staram się zdecydować, który jest najbardziej „prawidłowym” sposobem wdrożenia kontroli dostępu opartej na rolach, biorąc pod uwagę user
i subject
, do user
którego chciałby uzyskać dostęp.
Z tego co widzę, mam trzy podstawowe opcje (czwarta to zlekceważenie pierwszych trzech, a piąta poprawa czwartej):
- Zapytaj
subject
o listę uprawnień, któreuser
ma -subject.allowAccess(user.getPermissionSet)
- Zapytaj
user
o listę uprawnień, któresubject
wymagają -user.hasPermissionTo(subject.getRequiredPermissions())
- Zapytaj firmę zewnętrzną, aby zlokalizować skrzyżowania uprawnień -
accessController.doPermissionSetsIntersect(subject.permissionSet, user.getPermissionSet())
- Zapytaj albo
subject
/user
, delegując „decyzję” do klasy innej firmy - Spróbuj
user
uzyskać dostępsubject
i wyrzucić błąd, jeśli dostęp nie jest dozwolony
Przechylam się do opcji czwartej - Niech subject
zawiera accessController
pole, w którym połączenia subject.userMayAccess(User user)
delegują operację a la:
class Subject {
public function display(user) {
if(!accessController.doPermissionSetsIntersect(this.permissionSet, user.getPermissionSet())) {
display403(); //Or other.. eg, throw an error..
}
}
}
.. ale to rodzi kolejne pytania:
- czy pole powinno
accessController
być polem a klasą statyczną? - Czy należy
subject
wiedzieć, jakie uprawnienia są wymagane, aby móc go wyświetlić? - gdzie w grę wchodzi zasada najmniejszej wiedzy w odniesieniu do powołania
subject.display()
? Czy osoby dzwoniące powinnysubject.display()
wiedzieć, że obowiązuje kontrola dostępu? (gdziesubject.display()
jest ostatnia „metoda szablonu”) - mają
subject.display()
zarządzać kontrolą dostępu, rzuca wyjątek, jeśli użytkownik nie posiada wymaganego pozwolenia?
Co byłoby uważane za „najlepszą praktykę” w tej sytuacji? Gdzie faktycznie powinna wystąpić odpowiedzialność za przeprowadzanie kontroli?
Ponieważ jest to w pewnym stopniu zarówno ćwiczenie akademickie, które następnie przejdzie do wdrożenia, mile widziane będą odniesienia do wzorców projektowych.
Myślę, że opcja 3 jest najbliżej, ale zamiast odpytywania
user
orazsubject
o ich zestawy uprawnień należy przekazaćuser
isubject
do kontrolera dostępu.Kontroler dostępu powinien być odpowiedzialny zarówno za uzyskanie zestawów uprawnień, jak i sprawdzenie, czy dostęp jest wystarczający. W ten sposób izolujesz zarówno logikę przechowywania, jak i logikę sprawdzania w kontrolerze dostępu, niezależnie od użytkownika i podmiotu.
Innym elementem, którego prawdopodobnie brakuje w twoim przykładzie, jest wykonywana operacja. Niektórzy użytkownicy mogą mieć prawo do odczytywania niektórych danych, ale nie do aktualizacji, usuwania, wykonanie, itd. Więc może masz
checkAccess
sposób na kontroler dostępu z trzech parametrów:user
,subject
,operation
. Możesz także podać dodatkowe informacje,checkAccess
aby zwrócić informacje o tym, dlaczego dostęp nie został przyznany.Na przykład delegowanie tego wszystkiego do kontrolera dostępu pozwala później zmienić sposób reprezentowania uprawnień. Możesz zacząć od kontroli dostępu opartej na rolach, a później przejść do roszczeń. Możesz przechowywać uprawnienia w prostej strukturze, aby rozpocząć i później dodać hierarchiczne grupy / role i dozwolone operacje na różnych typach tematów. Niewprowadzenie zestawów uprawnień do interfejsu pomaga to włączyć.
To, czy korzystasz z AOP, czy z jakiegoś kodu typu „płytka kotłowa”, jest moim zdaniem mniej ważne.
źródło