Próbuję zrozumieć nieodłączny kompromis między rolami i uprawnieniami, jeśli chodzi o kontrolę dostępu (autoryzację).
Zacznijmy od danego: w naszym systemie pozwolenie będzie drobnoziarnistą jednostką dostępu („ Edytuj zasób X ”, „ Uzyskaj dostęp do strony panelu kontrolnego ” itp.). Rola będzie zbiorem 1+ uprawnienia. Użytkownik może mieć 1+ role. Wszystkie te relacje (użytkownicy, role, uprawnienia) są przechowywane w bazie danych i mogą być zmieniane na bieżąco i w razie potrzeby.
Moje troski:
(1) Co jest takiego „złego” w sprawdzaniu ról kontroli dostępu? Jakie korzyści można uzyskać, sprawdzając zamiast tego uprawnienia? Innymi słowy, jaka jest różnica między tymi dwoma fragmentami poniżej:
if(SecurityUtils.hasRole(user)) {
// Grant them access to a feature
}
// vs.
if(SecurityUtils.hasPermission(user)) {
// Grant them access to a feature
}
I:
(2) Jaką przydatną wartość Role w tym scenariuszu zapewniają? Czy nie moglibyśmy po prostu bezpośrednio przypisać uprawnień 1+ użytkownikom? Jaką konkretną wartość abstrakcji oferuje Role (czy ktoś może podać konkretne przykłady)?
Odpowiedzi:
W momencie sprawdzania kod wywołujący musi tylko wiedzieć „czy użytkownik X ma uprawnienia do wykonania akcji Y?” .
Kod wywołujący nie przejmuje się i nie powinien być świadomy relacji między rolami a uprawnieniami.
Warstwa autoryzacyjna sprawdzi następnie, czy użytkownik ma to uprawnienie, zwykle sprawdzając, czy rola użytkownika ma to uprawnienie. Umożliwia to zmianę logiki autoryzacji bez aktualizacji kodu wywołującego.
Jeśli bezpośrednio sprawdzasz rolę w witrynie wywołującej, domyślnie tworzysz relacje między uprawnieniami do roli i wstrzykujesz logikę autoryzacji do kodu wywołującego, co narusza rozdzielenie obaw.
Jeśli później zdecydujesz, że rola
foo
nie powinna mieć uprawnieńbaz
, będziesz musiał zmienić każdy kod, który sprawdza, czy użytkownik jest użytkownikiemfoo
.Role koncepcyjnie reprezentują nazwaną kolekcję uprawnień.
Załóżmy, że dodajesz nową funkcję, która pozwala użytkownikowi edytować niektóre ustawienia. Ta funkcja powinna być dostępna tylko dla administratorów.
Jeśli przechowujesz uprawnienia na użytkownika, musisz znaleźć wszystkich użytkowników w bazie danych, którzy w jakiś sposób znasz administratorów (jeśli nie przechowujesz informacji o rolach dla użytkowników, skąd miałbyś wiedzieć, którzy użytkownicy są administratorami?) I dołączyć to uprawnienie do ich listy uprawnień.
Jeśli używasz ról, musisz jedynie dołączyć uprawnienia do
Administrator
roli, która jest zarówno łatwiejsza do wykonania, bardziej wydajna pod względem miejsca, jak i mniej podatna na błędy.źródło
authorization layer
Prawdopodobnie oznacza nic więcej niż po prostu definicję funkcji (tj.)user->hasPermission(SOME_PERMISSION)
Najpierw sprawdź role użytkownika, a następnie sprawdź, czy którakolwiek z ról zawiera / wyklucza podaną pozwolenie. Na przykład,the calling code
można sprawdzić, czy dana strona jest widoczna dla użytkownika i nazywająuser->hasPermission(VIEW_GIVEN_PAGE)
, aauthorization layer
składa się z definicją zhasPermission
funkcji, która sprawdza role jak wyżej.hasPermission
to sprawdzićusersRole.HasPermission(VIEW_GIVEN_PAGE) && !user.Suspended
. Chodzi o to, że wszystko odbywa się w jednym miejscu, a nie w konsumującym (wywołującym) kodzie.W odpowiedzi na twoje pierwsze pytanie, największym problemem ze sprawdzeniem, czy użytkownik ma rolę, a nie konkretne uprawnienia, jest to, że uprawnienia mogą być przechowywane przez wiele ról. Na przykład programista może mieć dostęp do portalu dla deweloperów w intranecie firmy, co prawdopodobnie jest również pozwoleniem posiadanym przez jego menedżera. Jeśli użytkownik próbuje uzyskać dostęp do portalu dla deweloperów, masz czek podobny do:
(
switch
Wypowiedź w wybranym przez Ciebie języku byłaby lepsza, ale nadal niezbyt uporządkowana)Im bardziej powszechne lub powszechnie posiadane jest uprawnienie, tym więcej ról użytkowników należy sprawdzić, aby upewnić się, że ktoś może uzyskać dostęp do danego systemu. Doprowadziłoby to również do problemu polegającego na tym, że za każdym razem, gdy modyfikujesz uprawnienia do roli, musisz zmodyfikować czek, aby to odzwierciedlić. W dużym systemie bardzo szybko stałoby się to niewygodne.
Jeśli po prostu sprawdzisz, czy użytkownik ma uprawnienia, które zezwalają mu na przykład na dostęp do portalu dla programistów, nie ma znaczenia, jaką rolę pełnią, zostanie mu przyznany dostęp.
Aby odpowiedzieć na drugie pytanie, masz role, ponieważ działają one tak łatwo, jak modyfikować i dystrybuować „pakiety” uprawnień. Jeśli masz system, który ma setki ról i tysiące uprawnień, dodanie nowego użytkownika (na przykład nowego menedżera HR) wymagałoby przejścia przez użytkownika i przyznania mu każdego pozwolenia, które posiadają inni menedżerowie HR. Byłoby to nie tylko uciążliwe, ale również podatne na błędy, gdyby wykonano je ręcznie. Porównaj to z prostym dodaniem roli „HR manager” do profilu użytkownika, który zapewni mu taki sam dostęp jak każdy inny użytkownik z tą rolą.
Możesz argumentować, że możesz po prostu sklonować istniejącego użytkownika (jeśli twój system to obsługiwał), ale chociaż daje to użytkownikowi odpowiednie uprawnienia na ten moment, próba dodania lub usunięcia uprawnienia dla wszystkich użytkowników w przyszłości może być trudny. Przykładowym scenariuszem jest sytuacja, w której być może w przeszłości personel HR był również odpowiedzialny za płace, ale później firma staje się wystarczająco duża, aby zatrudnić pracowników specjalnie do obsługi listy płac. Oznacza to, że dział HR nie musi już uzyskiwać dostępu do systemu płac, aby zezwolenie można było usunąć. Jeśli masz 10 różnych członków HR, musisz ręcznie przejść i upewnić się, że usunąłeś odpowiednie uprawnienie, które wprowadza możliwość błędu użytkownika. Innym problemem jest to, że po prostu nie skaluje się; w miarę zdobywania coraz większej liczby użytkowników w danej roli znacznie utrudnia to modyfikację roli. Porównaj to z użyciem ról, w których wystarczy zmodyfikować nadrzędną rolę, o której mowa, aby usunąć uprawnienie, co będzie odzwierciedlone przez każdego użytkownika, który pełni tę rolę.
źródło