Standardowe praktyki kontroli dostępu (wzorzec projektowy)

9

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ę useri subject, do userktó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):

  1. Zapytaj subjecto listę uprawnień, które userma -subject.allowAccess(user.getPermissionSet)
  2. Zapytaj usero listę uprawnień, które subjectwymagają -user.hasPermissionTo(subject.getRequiredPermissions())
  3. Zapytaj firmę zewnętrzną, aby zlokalizować skrzyżowania uprawnień - accessController.doPermissionSetsIntersect(subject.permissionSet, user.getPermissionSet())
  4. Zapytaj albo subject/ user, delegując „decyzję” do klasy innej firmy
  5. Spróbuj useruzyskać dostęp subjecti wyrzucić błąd, jeśli dostęp nie jest dozwolony

Przechylam się do opcji czwartej - Niech subjectzawiera accessControllerpole, 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 accessControllerbyć 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 powinny subject.display()wiedzieć, że obowiązuje kontrola dostępu? (gdzie subject.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.

kwah
źródło

Odpowiedzi:

7

Najlepszą praktyką jest użycie czegoś znanego jako wzorzec przechwytywania do przechwytywania połączeń do obszarów chronionych.

Można to osiągnąć za pomocą AOP lub problemów przekrojowych stosowanych w punktach dostępu.

Badany nigdy nie powinien wiedzieć, kto może go zobaczyć. To komplikuje niepotrzebnie kod tematu i nie ma powodu, aby był wymagany, chyba że przypadkowo zapewnisz mechanizm bezpośredniego dostępu do tej samej funkcji.

Najlepiej, gdy dzwoniący i osoba odbierająca nie powinni wiedzieć o dostępie, oprócz obsługi odrzuceń. Problem będzie jednak zależeć od systemu, w którym wdrażasz i od tego, w jaki sposób uzyskasz dostęp do poświadczeń bezpieczeństwa / nazwy głównej osoby dzwoniącej. Na przykład w systemach SOAP informacja ta jest dodawana do nagłówka komunikatu SOAP, podczas gdy w systemie Windows byłaby dostępna za pośrednictwem mechanizmu uwierzytelniania systemu Windows.

Jeśli użyjesz metody AOP lub wzorca przechwytywania, wygeneruje on wszelkie niezbędne wyjątki, a klient (osoba dzwoniąca) zajmie się wszystkimi zgłoszonymi wyjątkami.

W ten sposób Twój klient, usługa i kod uwierzytelniający są oddzielne, bez przenikania się wiedzy i funkcjonalności.

sweetfa
źródło
2

Myślę, że opcja 3 jest najbliżej, ale zamiast odpytywania useroraz subjecto ich zestawy uprawnień należy przekazać useri subjectdo kontrolera dostępu.

class Subject {
    public function display(user) {
        if(!accessController.checkAccess(this, user, AccessControl.Read)) {
            display403(); //Or other.. eg, throw an error..
        }
    }
}

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 checkAccesssposób na kontroler dostępu z trzech parametrów: user, subject, operation. Możesz także podać dodatkowe informacje, checkAccessaby 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.

Rory
źródło