Próbuję utworzyć elastyczną strukturę ACL w Javie dla mojej aplikacji.
Wiele frameworków ACL jest zbudowanych na białej liście reguł, gdzie reguła ma postać właściciel: akcja: zasób . Na przykład,
- „JOHN może ZOBACZYĆ zasób FOOBAR-1”
- „MARY może ZOBACZ zasób FOOBAR-1”
- „MARY może EDYTOWAĆ zasób FOOBAR-1”
Jest to atrakcyjne, ponieważ reguły można łatwo serializować / utrwalać w bazie danych. Ale moja aplikacja ma złożoną logikę biznesową. Na przykład,
- „Wszyscy użytkownicy w dziale 1 z ponad 5-letnim stażem pracy mogą ZOBACZ zasób FOOBAR-1, w przeciwnym razie nie są autoryzowani”
- „Wszyscy użytkownicy w dziale 2, jeśli data jest późniejsza niż 15.03.2016, mogą ZOBACZ zasób FOOBAR-2, w przeciwnym razie nie autoryzowani”
Na pierwszy rzut oka koszmarem byłoby opracowanie schematu bazy danych, który mógłby obsługiwać nieskończenie złożone reguły takie jak te. Dlatego wydaje się, że musiałbym „upiec” je w skompilowanej aplikacji, ocenić dla każdego użytkownika, a następnie wygenerować reguły właściciel: akcja: zasoby w wyniku oceny. Chcę uniknąć upieczenia logiki w skompilowanej aplikacji.
Tak więc myślałem o reprezentowaniu reguły w formie predykatu : akcja: zasób , gdzie predykat jest wyrażeniem logicznym, które określa, czy użytkownik jest dozwolony. Predykat byłby ciągiem wyrażenia JavaScript, który mógłby być oceniany przez silnik Rhino Java. Na przykład,
return user.getDept() == 1 && user.seniority > 5;
W ten sposób predykaty można łatwo utrwalić w bazie danych.
Czy to jest sprytne ? Czy to jest niechlujne ? Czy to jest chwytliwe ? Czy to jest przeprojektowane ? Czy jest to bezpieczne (podobno Java może piaskownic silnik Rhino).
źródło
Odpowiedzi:
Pipowanie dynamicznych danych do interpretera języka implementacji jest zwykle złym pomysłem, ponieważ zwiększa ryzyko uszkodzenia danych do możliwości przejęcia złośliwych aplikacji. Innymi słowy, idziesz na drodze do stworzenia do wstrzyknięcia kodu usterki.
Twój problem można lepiej rozwiązać za pomocą mechanizmu reguł lub języka specyficznego dla domeny (DSL) . Spójrz na te koncepcje, nie ma potrzeby wymyślania nowego koła.
źródło
==
zamiast===
w swoim przykładzie. Czy naprawdę chcesz zapewnić kompletność, gdy wszystkie reguły powinny być zawsze wygasane? Zamiast przeskakiwać między obręczami, aby upewnić się, że wszystkie interakcje między Javą a JavaScript są koszerne, dlaczego nie napisać prostego parsera i interpretera, jak sugerował Kilian? O wiele łatwiej będzie dostosować się do twoich potrzeb i zabezpieczyć. Użyj ANTLR lub czegoś takiego.while (true) ;
Zrobiłem to i nie polecam.
Napisałem całą logikę biznesową w Lua i zapisałem ten skrypt Lua w bazie danych. Gdy moja aplikacja się uruchomi, załaduje się i wykona skrypt. W ten sposób mogłem zaktualizować logikę biznesową mojej aplikacji bez dystrybucji nowego pliku binarnego.
Zawsze stwierdziłem, że zawsze muszę aktualizować plik binarny podczas wprowadzania zmian. Niektóre zmiany były w skrypcie Lua, ale niezmiennie mam listę zmian, które należało wprowadzić, więc prawie zawsze musiałem wprowadzać pewne zmiany w pliku binarnym i pewne zmiany w skrypcie Lua. Moja wyobraźnia, że mogłabym cały czas unikać dystrybucji plików binarnych, po prostu się nie spełniła.
To, co uznałem za znacznie bardziej pomocne, było ułatwienie dystrybucji plików binarnych. Moja aplikacja automatycznie sprawdza dostępność aktualizacji podczas uruchamiania, pobiera i instaluje każdą aktualizację. Moi użytkownicy zawsze korzystają z najnowszych plików binarnych, które wypchnąłem. Nie ma prawie żadnej różnicy między zmianą pliku binarnego a zmianą skryptów. Gdybym to zrobił ponownie, włożyłbym jeszcze więcej wysiłku, aby aktualizacja była bezproblemowa.
źródło
Nie chciałbym, aby baza danych zawierała kod. Ale możesz zrobić coś podobnego, mając bazę danych zawierającą nazwy funkcji, a następnie używając refleksji, aby je wywołać. Kiedy dodajesz nowy warunek, musisz dodać go do kodu i bazy danych, ale możesz łączyć warunki i parametry, które są do nich przekazywane, aby tworzyć dość złożone oceny.
Innymi słowy, jeśli masz ponumerowane działy, łatwo byłoby sprawdzić czek UserDepartmentIs i TodayIsAfter, a następnie połączyć je, aby otrzymać Department = 2 i Today> 15/15/2016. Jeśli następnie chcesz sprawdzić TodayIsBefore, abyś mógł zakończyć datę uprawnienia, musisz napisać funkcję TodayIsBefore.
Nie zrobiłem tego dla uprawnień użytkownika, ale zrobiłem to dla sprawdzania poprawności danych, ale powinno działać.
źródło
XACML to rozwiązanie, którego naprawdę szukasz. Jest to rodzaj silnika reguł, który koncentruje się wyłącznie na kontroli dostępu. XACML, standard zdefiniowany przez OASIS, definiuje trzy części:
Architektura jest następująca:
Oto jak wygląda Twój pierwszy przypadek użycia:
Twój drugi przypadek użycia to:
Możesz połączyć oba przypadki użycia w jedną zasadę, używając odniesień:
I jesteś skończony!
Możesz przeczytać więcej o XACML i ALFA z:
źródło
To, czego naprawdę chcesz, to XACML . Daje to dokładnie to, czego chcesz. Niekoniecznie musisz wdrożyć pełną architekturę z całkowicie oddzielonymi rolami ... jeśli masz tylko jedną aplikację, prawdopodobnie uda Ci się zintegrować PDP i PEP z aplikacją za pomocą balana, a PIP jest czymkolwiek Twoja istniejąca baza danych użytkowników to.
Teraz, gdziekolwiek w aplikacji musisz coś autoryzować, tworzysz żądanie XACML, które zawiera użytkownika, akcję i kontekst, a silnik XACML podejmie decyzję na podstawie zapisanych plików zasad XACML. Te pliki zasad mogą być przechowywane w bazie danych lub w systemie plików lub w dowolnym miejscu, w którym chcesz zachować konfigurację. Axiomatics ma fajną alternatywę dla reprezentacji XML XACML o nazwie ALFA, która jest nieco łatwiejsza do odczytania niż nieprzetworzony XML, oraz wtyczkę Eclipse do generowania XACML XML na podstawie zasad ALFA.
źródło
Zrobiliśmy to w mojej obecnej firmie i jesteśmy bardzo zadowoleni z wyników.
Nasze wyrażenia są zapisane w js, a nawet używamy ich, aby ograniczyć wyniki uzyskiwane przez użytkowników z kwerendy ElasticSearch.
Sztuką jest upewnienie się, że dostępna jest wystarczająca ilość informacji, aby podjąć decyzję, abyś mógł naprawdę pisać dowolne perms bez zmian w kodzie, jednocześnie zachowując je szybko.
Naprawdę nie martwimy się atakami polegającymi na wstrzykiwaniu kodu, ponieważ uprawnienia są zapisywane przez tych, którzy nie muszą atakować systemu. To samo dotyczy ataków DOS, takich jak
while(true)
przykład. Administratorzy systemu nie muszą tego robić, mogą po prostu usunąć uprawnienia wszystkich ...Aktualizacja:
Coś takiego jak XACML wydaje się być lepszym centralnym punktem zarządzania autoryzacją dla organizacji. Nasz przypadek użycia jest nieco inny, ponieważ nasi klienci zazwyczaj nie mają działu IT, który prowadziłby to wszystko. Potrzebowaliśmy czegoś samodzielnego, ale staraliśmy się zachować jak największą elastyczność.
źródło