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.
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