2014-05-05 22 views
31

Czytałem o DDD i kontroli dostępu, a znalazłem jakąś sprzeczność między dwiema następującymi opiniami:Access Control w Domain Driven Design

  • "obawy związane z bezpieczeństwem powinny być obsługiwane poza domeną"
  • „kontroli dostępu wymagania są specyficzne dla domeny "

Szukam najlepszej praktyki w tej sprawie. Więc gdzie powinienem umieścić logikę kontroli dostępu według projektu opartego na domenie i jak powinienem ją wdrożyć?

(A dokładniej przez DDD + CQRS + ES.)

myślę, że powinno być gdzieś w pobliżu logiki biznesowej, na przykład historia użytkownik może być coś takiego:

użytkownik może edytować swój profil, wysyłając nazwę użytkownika, listę hobby, CV, itp ...

na podstawie tej historii użytkownika wdrażamy model domeny i usługi, na przykład:

UserService 
    editProfile(EditUserProfileCommand command) 
     User user = userRepository.getOneById(command.id) 
     user.changeName(command.name) 
     user.changeHobbies(command.hobbies) 
     user.changeCV(command.cv) 

UserRepository 
    User getOneById(id) 

User 
    changeName(String name) 
    changeHobbies(String[] hobbies) 
    changeCV(String cv) 

To jest w porządku, ale gdzie jest część historii z HIS profile?

Jest to oczywiście przypisywać kontroli dostępu w oparciu, ponieważ powinniśmy napisać regułę coś takiego:

deny all, but if subject.id = resource.owner.id then grant access 

Ale gdzie powinniśmy egzekwować tę zasadę i jak powinniśmy je realizować?

+0

W tym identyfikator użytkownika w poleceniu ('command.id') wprowadza niejednoznaczność. Lepiej usunąć identyfikator użytkownika z komendy i przekazać użytkownikowi wzięty z kontekstu autoryzacji wraz z poleceniem. – Lightman

Odpowiedz

25

Więc gdzie powinienem umieścić logikę kontroli dostępu?

Zgodnie z tym: https://softwareengineering.stackexchange.com/a/71883/65755 punkt egzekwowania polityki powinno być tuż przed wywołaniem UserService.editProfile().

Doszedłem do tego samego wniosku: nie może być w interfejsie użytkownika, ponieważ w przypadku wielu interfejsów będziemy powtarzać kod. Powinno być przed stworzeniem zdarzeń domeny, ponieważ wskazywały, że już zrobiliśmy coś w systemie. Możemy więc ograniczyć dostęp do obiektów domeny lub usług, które używają tych obiektów domeny. Według CQRS nie musimy mieć obiektów domenowych przez model odczytu, tylko usługi, więc musimy ograniczyć dostęp do usług, jeśli chcemy ogólnego rozwiązania. Moglibyśmy umieścić decyzje dotyczące dostępu na początku każdej operacji serwisowej, ale byłby to wzór zabezpieczający w postaci grant all, deny x.

Jak należy go wdrożyć?

Zależy to od tego, który model kontroli dostępu pasuje do domeny, więc zależy to od historii użytkownika. Decyzją o dostępie zwykle wysyłamy żądanie dostępu i czekamy w zamian na pozwolenie. Żądanie dostępu zwykle składa się z następujących części: temat, zasób, działanie, środowisko. Tak więc podmiot wymaga uprawnień do wykonania operacji na zasobie w środowisku. Najpierw identyfikujemy temat, a następnie uwierzytelniamy go, a potem przychodzi autoryzacja, w której sprawdzamy, czy żądanie dostępu pasuje do naszej polityki dostępu. Każdy model kontroli dostępu działa w podobny sposób. Ofc.mogą brakować niektórych z tych kroków, ale to nie ma znaczenia ...

Stworzyłem krótką listę modeli kontroli dostępu. Włożyłem zasady, Polityk w adnotacji, ale zazwyczaj trzeba je przechowywać w bazie danych prawdopodobnie w formacie XACML jeśli chcemy mieć system dobrze w utrzymaniu ...

  • Przez tożsamości kontroli dostępu opartego (IBAC) mamy mieć tożsamość - magazyn uprawnień (lista kontroli dostępu, lista możliwości, macierz kontroli dostępu). Na przykład dzięki liście kontroli dostępu przechowujemy listę użytkowników lub grup, które mogą mieć uprawnienia.

    UserService 
        @AccessControlList[inf3rno] 
        editProfile(EditUserProfileCommand command) 
    
  • Przez kraty kontroli dostępu opartego (LBAC) przedmiot ma poziom luz, zasób posiada wymagany poziom luz, i sprawdzić, jaki poziom jest wyższy ...

    @posseses[level=5] 
    inf3rno 
    
    UserService 
        @requires(level>=3) 
        editProfile(EditUserProfileCommand command) 
    
  • By kontrola dostępu oparta na rolach (RBAC) definiujemy role podmiotu i udzielamy uprawnień podmiotom, których aktem jest faktyczna rola.

    @roles[admin] 
    inf3rno 
    
    UserService 
        @requires(role=admin) 
        editProfile(EditUserProfileCommand command) 
    
  • przez atrybut kontroli dostępu opartego (ABAC) definiujemy atrybuty zastrzeżeniem, zasobów i środowiska oraz piszemy nasze zasady oparte na nich.

    @attributes[roles=[admin]] 
    inf3rno 
    
    UserService 
        @policy(subject.role=admin or resource.owner.id = subject.id) 
        editProfile(EditUserProfileCommand command) 
        @attribute(owner) 
        Subject getOwner(EditUserProfileCommand command) 
    
  • polityką kontroli dostępu opartego (PBAC) my nie przypisywać nasze zasady do niczego innego, są samodzielnym.

    @attributes[roles=[admin]] 
    inf3rno 
    
    UserService 
        editProfile(EditUserProfileCommand command) 
        deleteProfile(DeleteUserProfileCommand command) 
        @attribute(owner) 
        Subject getOwner(EditUserProfileCommand command) 
    
    @permission(UserService.editProfile, UserService.deleteProfile) 
    @criteria(subject.role=admin or resource.owner.id = subject.id) 
    WriteUserServicePolicy 
    
  • kontrolą dostępu ryzyka adaptacyjny (RAdAC) opieramy naszą decyzję o względnej profilu ryzyka pacjenta i poziomu ryzyka związanego z operacją. Nie można tego opisać za pomocą reguł, które myślę. Nie jestem pewien co do implementacji, może to właśnie jest to, czego stackoverflow używa w swoim systemie punktowym.

  • Przez autoryzację opartą na kontroli dostępu (ZBAC) nie robimy identyfikacji i uwierzytelniania, zamiast tego przypisujemy uprawnienia do czynników identyfikacji. Na przykład, jeśli ktoś wyśle ​​token, może mieć dostęp do usługi. Wszystko inne jest podobne do poprzednich rozwiązań. Na przykład z ABAC:

    @attributes[roles=[editor]] 
    token:2683fraicfv8a2zuisbkcaac 
    
    ArticleService 
        @policy(subject.role=editor) 
        editArticle(EditArticleCommand command) 
    

    więc każdy, kto zna token 2683fraicfv8a2zuisbkcaac mogą korzystać z usługi.

i tak dalej ...

Istnieje wiele innych modeli, a najlepiej pasuje zawsze zależy od potrzeb klienta.

więc podsumować

- "security concerns should be handled outside the domain" 
- "access control requirements are domain specific" 

zarówno może być prawda, ponieważ bezpieczeństwo nie jest częścią modelu domeny, ale jego realizacja zależy od modelu domeny i logiki aplikacji.

edit po 2 latach 2016-09-05

Odkąd odpowiedział na moje własne pytanie, początkujących DDD, czytałem Implementing Domain-Driven Design od Vaughn Vernon.To była interesująca książka w temacie. Oto cytat z niego:

Stanowi nowy ograniczony kontekst - tożsamość i dostęp Kontekst - i będą wykorzystywane przez innych kontekstach ograniczony przez standardowe technik integracyjnych DDD. Do kontekstów konsumpcyjnych Kontekst Dostępu Identity i Generic to Generic Subdomain. Produkt będzie nosił nazwę IdOvation.

Tak więc według Vernona prawdopodobnie najlepszym rozwiązaniem jest przeniesienie kontroli dostępu do ogólnej poddomeny.

+0

Informacje na temat edycji można łatwo przenieść na podstawie ról, ACL lub na podstawie uprawnień do ogólnego kodu BC, ale nie w przypadku autoryzacji opartej na regułach. – plalx