Spring Security i uprawnienia

0

Witajcie,
Mam problem z uprawnieniami użytkowników w Spring Security. Wiem jak sprawdzić za pomocą wyrażenia springa czy użytkownik jest w danej grupie (np. ROLE_ADMIN), ale czy istnieje możliwość sprawdzenia czy użytkownik ma konkretną permisję - np. PERM_addingposts. Bazę danych mam już w ten sposób zaprojektowaną, zastanawia mnie tylko jak sprawdzić czy ma permisję za pomocą wyrażeń springa, ponieważ hasRole() chyba powinno służyć do sprawdzania grupy, nie poszczególnych uprawnień

0

@PreAuthorize

0

Tak jak wyżej, tylko żeby móc z tego skorzystać, to trzeba sobie w global-method-securityustawić flagępre-post-annotations="enabled"

0

Mozesz uzyc wyrazenia hasPermission

0

Tak, chodziło mi o coś takiego jak hasPermission. Nie rozumiem tylko dlaczego tutaj jest hasPermission(#id, 'RouteRemove').
http://stackoverflow.com/questions/16164615/preauthorize-with-haspermission-executes-code-twice
Czym jest to #id?

0

Parametrem metody. Nie chce mi sie czytac calego wpisu na SO ale jest tam napisane cos o tym, ze sa jakies trasy (route) i uzytkownik moze skasowac trase tylko wtedy kiedy jest jej wlascicielem. Jak mozna sie domyslec ustala sie kto jest wlascicielem danej trasy na podstawie identyfikatora (parametr id).

Pewnie dlatego jest tam napisane hasPermission(#id, 'RouteRemove') co znaczy mniej wiecej tyle co "sprawdz czy ktos ma uprawnienia do usuniecia trasy na podstawie identyfikatora, ktorego wartosc przechowywana jest w parametrze id danej metody).

0

To #id odwołuje się w tym przykładzie do tego pola @PathVariable("id") Integer id , sprawdzasz po prostu czy użytkownik ma "przyzwolenie" RouteRemove dla danego id

EDIT:

dokładnie to co napisał @tk wyżej

0

Mam obiekt User, który implementuje UserDetailsService i jego instancja przechowywana jest jako principal. Jak mam do niego uzyskać dostęp z poziomu tego wyrażenia i w której metodzie muszę zwrócić listę uprawnień?

0

Możesz sobie dopisać takiego ControllerAdvice:

@ControllerAdvice
public class UserControllerAdvice {
 
    @ModelAttribute
    public User currentUser(Authentication authentication) {
        if (null != authentication){
            return (User) authentication.getPrincipal();
        }
        return null;
    }
} 

Wtedy do parametrów funkcji dopisujesz

@ModelAttribute User user
, i jest on tam wtedy wstrzykiwany.

0

Rozumiem, ale w takim przypadku za każdym razem będę musiał go również umieszczać w modelu (tak żeby plik jsp miał do niego dostęp). Korzystam z tagów springa security, gdzie jest to znacznie łatwiejsze.
Reasumując. Co musi implementować User, żebym mógł wykonać na nim hasPermission? Dalej nie rozumiem o co chodzi z tym #id. Przecież User na którym wykonane ma być to hasPermission powinien wynikać z kontekstu, tak jak to jest w przypadku hasRole

1
Zaprogramowany napisał(a):

Co musi implementować User, żebym mógł wykonać na nim hasPermission?

Jezeli wyraziles sie poprawnie w poprzednim poscie i User implementuje interfejs UserDetailsService to moim zdaniem w ogole nie powinienes wywolywac na nim wyrazenia hasPermission.

Inaczej sprawa wyglada w przypadku gdy User to klasa reprezentujaca konkretnego uzytkownika, ktora wcale nie implementuje interfejsu UserDetailsService (moze implementowac interfejs UserDetails) tylko cos co implementuje UserDetailsService zwraca obiekt klasy User. Wtedy ma to jakis sens.

Innymi slowy: jezeli wspomniales o interfejsie UserDetailsService to pewnie masz klase, ktora go implementuje. Jezeli tak jest to zwroc uwage na to, ze interfejs UserDetailsService posiada metode loadUserByUsername, ktora zwraca obiekt implementujacy interfejs UserDetails.

Ta metoda moze zwrocic Twoja wlasna klase, ale moze tez zwrocic klase org.springframework.security.core.userdetails.User, ktora implementuje interfejs UserDetails. Konstruktor tej klasy posiada parametr z kolekcja uprawnien i tam mozesz wlasnie przydzielic uzytkownikowi jakies tam zezwolenia.

Zaprogramowany napisał(a):

Dalej nie rozumiem o co chodzi z tym #id. Przecież User na którym wykonane ma być to hasPermission powinien wynikać z kontekstu, tak jak to jest w przypadku hasRole

OK, to moze inaczej: wyobraz sobie, ze tworzysz serwis internetowy gdzie uzytkownicy wrzucaja jakies pliki. Kazdy uzytkownik ma mozliwosc usuniecia dowolnego pliku pod warunkiem, ze jest to plik umieszczony przez niego - nie mozna kasowac plikow innym uzytkownikom. Zalozmy tez, ze wszelkie niezbedne informacje o plikach przechowujesz w tabeli bazy danych - kazdy plik ma swoj identyfikator w postaci klucza podstawowego.

Co w takiej sytuacji zrobisz? Zapewne napiszesz sobie usluge, w ktorej znajdzie sie metoda:

 
public void deleteFile(Long id);

Powyzsza metoda usunie plik o identyfikatorze id (w praktyce moze to byc cos innego niz id, np. encja). Tylko, ze te metode wywoluje nie tylko Zdzisia ale takze Marysia. Jak Zdzisia bedzie cwana i podmieni identyfikator (np. w adresie strony) to usunie zdjecie Marysi. Marysia w tym momencie kontaktuje sie z Toba i drze ryja na caly regulator bo przeciez nie po to robila przez pol godziny dziubek do lustra, zeby zazdrosna Zdzisia usunela jej jakze wazne zdjecie.

Aby tego uniknac nalezy sprawdzic nie tylko czy uzytkownik posiada uprawnienia usuwania plikow ale takze czy jest upowazniony do usuniecia akurat tego a nie innego zasobu. Dlatego wlasnie przed metoda deleteFile napiszesz sobie cos w stylu:

 
@PreAuthorize("hasPermission(#id, 'DeleteFile')")
public void deleteFile(Long id);

Wtedy jezeli Zdzisia wywola te metode, to zanim dojdzie do usuniecia pliku zostanie wykonana logika sprawdzajaca czy ten plik nalezy do Zdzisi. Logike sprawdzania wlasciciela pliku mozesz zawrzec w dowolnej klasie, ktora implementuje interfejs PermissionEvaluator - zostanie tam przekazany rozdzaj uprawnien oraz identyfikator. Musisz tylko w swojej konfiguracji dodac tego Twojego evaluatora do listy evaluatorow - jezeli Twoja konfiguracja dziedziczy po GlobalMethodSecurityConfiguration to mozesz uzyc metody setPermissionEvaluator.

0

Mój błąd, chodziło o UserDetails. Rozumiem :D Dzięki za tak obszerną wypowiedź. Gdybym chciał zrobić to samo na hasRole, to musiałbym dodać jeszcze sprawdzanie czy to zdjęcie należy do konkretnego Usera, a tu wszystko dzieje się w PermissionEvaluator.

0

Jeszcze jedno pytanko :) gdybym wykonywał hasPermission z poziomu pliku JSP, to wyglądało by było to tak? hasPermission(principal, 'addpost')? Czy w jaki sposób odwołać się do principal?

1

Technologia JSP nigdy nie bylem jakos szczegolnie zainteresowany wiec nie wiem, ale wydaje mi sie ze propozycja użytkownika @setsudanhana jest calkiem ok - mozesz napisac ControllerAdvice, ktory doda do modelu interesujace Cie dane.

To nie jest tez tak, ze bedziesz musial za kazdym razem dodawac jakies dane do modelu. Dane beda dodawane automatycznie poniewaz ControllerAdvice moze dzialac dla wszystkich kontrolerow. Dodanie danych do modelu nie powinno tez wykluczac mozliwosci uzywania wyrazen Springa. Innymi slowy: piszesz jednego ControlerAdvice'a, ktory dodaje principala do modelu i pozniej sobie w dowolnym widoku tego principala uzywasz.

Ponadto dostep do principala moze miec takze PermissionEvaluator, wiec nie zawsze jest sens umieszczania go w wyrazeniu. W Twoim przypadku to bym rozwazyl czy nie lepiej jest napisac po prostu hasPermission(null, 'addpost') o ile posty nie sa jakos powiazane np. z kategoria. Bo jezeli sa to wtedy hasPermission(category, 'addpost'). PermissionEvaluator sobie wtedy pobierze tego principala sam. No ale to taka moja koncepcja, niekoniecznie jedynie sluszna.

0

Dzięki za pomoc, już nie mam żadnych wątpliwości :) Zabieram się do pisania

1 użytkowników online, w tym zalogowanych: 0, gości: 1