Zazwyczaj decyzje dotyczące autoryzacji umieszczam w moich kontrolerach po stronie serwera. To były ostatnio punkty końcowe RESTful, ale myślę, że to samo dotyczy architektur typu MVC. Dla argumentu załóżmy, że jest to autoryzacja oparta na rolach. Metoda chroniona zostanie opatrzona adnotacjami lub sprawdzi i zwróci 403 w razie potrzeby.
Teraz, biorąc pod uwagę, że autoryzacja jest w rzeczywistości regułą biznesową - na przykład „tylko administratorzy mogą wymienić X”, myślę, że powinni zostać zepchnięci na dół. Gdy kontroler prosi warstwę biznesową o wykonanie operacji, warstwa usługowa lub biznesowa informuje kontrolera, że nie jest autoryzowana.
Czy to rozsądne podejście? Czy są to wady?
Nienawidzę posiadania usługi AuthorisationService, która zasadniczo zawiera kilka statycznych, kodowanych reguł proceduralnych, aby to zrobić, ale być może ma sens utrzymanie całej logiki dostępu w jednym miejscu. Czy to kwestia przekrojowa, którą należy oddzielić?
Pytam więc, czy ktoś to zrobił i jak udało mu się to osiągnąć w czysty sposób, czy też czy są jakieś dobre zasoby, które mógłbym przeczytać. Używam Java Fwiw, ale jest to pytanie agnostyczne języka.
Sprawdziłem pokrewne pytania tutaj i są bardzo cienkie na ziemi i odpowiedzi. Na przykład: Sprawdzanie poprawności i autoryzacja w modelach domen i przenoszenie jej przez warstwę usług do MVC
Czytam wiosenne dokumenty bezpieczeństwa, które stanowią dobry argument za tym, że jest to problem przekrojowy, ale martwię się, że to tylko „wiosenna droga” i chciałbym szerszych perspektyw. Powiązuje również twoją aplikację z konkretną strukturą.
źródło
Odpowiedzi:
Dobrą praktyką jest ujawnianie tylko opcji, do których użytkownik jest upoważniony.
Wymusza to, aby zezwolenie było przekrojowe. „Widok” musi wiedzieć, co użytkownik może zrobić, zanim będzie mógł budować opcje i menu do wyświetlania.
Zaplecze nie powinno ufać frontonowi w podejmowaniu decyzji dotyczących bezpieczeństwa, dlatego musi sprawdzić samą autoryzację.
Mogą istnieć reguły biznesowe, które wpływają na autoryzację w zależności od danych, np. „Tylko użytkownicy z saldem powyżej 5000 $ mogą wykonać przelew walutowy” lub „Tylko użytkownicy z siedziby głównej mogą przeglądać te konta”. Dlatego w logice biznesowej wymagana jest pewna logika autoryzacji.
Należy również rozważyć uprawnienia techniczne - kto może przeglądać dzienniki, kto może tworzyć kopie zapasowe / przywracać bazę danych itp.
Tak więc ostatecznie każdy komponent może mieć określone wymagania bezpieczeństwa i / lub autoryzacji, w praktyce prawie niemożliwe jest zawinięcie go w osobną „warstwę autoryzacji”.
źródło
Myślę, że absolutnie rozsądne jest wprowadzenie autoryzacji w warstwie usług. Musisz chronić swoją usługę przed wykonywaniem nieautoryzowanych działań (szczególnie modyfikacji danych). Twoja warstwa usługi może znajdować się w jednej bibliotece i być używana przez różne warstwy prezentacji (możesz mieć różne aplikacje interfejsu użytkownika korzystające z tej samej warstwy usługi). I nie można polegać na tym, że określone warstwy prezentacji wykonują niezbędną weryfikację. Jest to szczególnie ważne, jeśli później zdecydujesz się przenieść warstwę usługi do osobnego procesu (np. Zgodnie z podejściem SOA).
Teraz o tym, jak to osiągnąć w „czysty sposób”. Nie podoba mi się pomysł zaśmiecania logiki biznesowej za pomocą kontroli autoryzacji, więc może pomóc konkretna implementacja podejścia do programowania aspektowego: może to być dekorowanie metod usług specjalnymi atrybutami lub używanie dynamicznych serwerów proxy z przechwytywaniem.
I, co ważne, muszę przyznać, że w bardzo prostych projektach możesz żyć bez oddzielnych walidacji, aby uprościć swoje życie. Ale ważne jest, aby nie przegapić momentu, w którym „prosty projekt” stał się „złożonym projektem”.
źródło
Lubię przesuwać kontrole autoryzacji tak nisko, jak to możliwe! (Ale nie dalej!)
Nadal masz swobodę pisania automatycznych testów autoryzacyjnych dla warstw „powyżej” tego. Niektóre reguły mogą mieć zastosowanie lub mieć sens tylko w wyższych warstwach, takich jak warstwa usługi (CanView / CanSerialize?). Ogólnie jednak uważam, że najbezpieczniejszą strategią autoryzacji jest również strategia „DRY-est”: utrzymuj autoryzację na jak najniższym poziomie, w najbardziej „powszechnym” lub „współdzielonym” kodzie, jak możesz (bez nadmiernego komplikowania reguł autoryzacji).
Pomyśl o alternatywie. Jeśli reguły autoryzacji są testowane i egzekwowane tylko w warstwie usług, pozostawiając słabe obiekty domeny do zgięcia do woli markotnych obiektów usług, często będziesz musiał egzekwować każdą regułę więcej niż raz, w wielu obiektach i wielu miejsca w każdym obiekcie oraz w bardziej skomplikowanym kodzie.
Ponadto, gdy Twój zespół analityczny zatrudnia firmę konsultingową do pisania usług raportowania przy użyciu obiektów domeny, nie musisz ufać tym programistom! (Lub cokolwiek. Budujesz dodatkowe usługi lub połączenia z tych samych obiektów z dowolnego powodu.) Nie będziesz chciał otworzyć dużej księgi reguł biznesowych i mieć nadzieję na prawidłowe egzekwowanie tych reguł ponownie ; chcesz, aby Twoja domena już je znała i egzekwowała.
źródło
Widget
, ta sama reguła ma zastosowanie wszędzie. (Więc nie ryzykować pozwalając ktoś go zignorować!) Jeśli zasada nie stosuje się wszędzie, to naprawdę nie jest to reguła oWidgets
i wyłącznieWidgets
. . Przesunąć reguły w dół tak daleko, jak to możliwe (poszczególne reguły); ale nie tak daleko, jak mogą sięgać „zasady” ... Czuję, że nie określam dobrze tego rozróżnienia. Ale powinno tam być rozróżnienie.