mundeck
5.11.2016, 16:45:09
Mam aplikację, w której każdy User może należeć do wielu Grup, a każda Grupa może mieć wielu Userów. Jeśli User się loguje, to tylko na konkretną Grupę, żeby w danej sesji nie mógł modyfikować danych innej grupy, nawet tej, do której należy. O tym, na którą Grupę w danym momencie się loguje, decyduje pole default_group, które jednakowoż może być zmienione, tak żeby przy następnym logowaniu można było zalogować się na inną Grupę, albo zeswitchować się na inną w trakcie sesji. Problem w tym, że o ile User jest oczywiście przechowywany w tokenStorage, o tyle Grupa za żadne skarby nie chce się tam zapisać. Korzystam z UserAuthenticatora, którego metoda authenticateToken zwraca token - w tym przypadku mój własny, do którego dodałem pole $group i wstawiłem tam obiekt Grupy (tej defaultowej dla tego Usera). Ale już po zalogowaniu to pole tokena ma wartość null. Domyślam się, że token jest w jakiś sposób regenerowany, ale np. przechowywane są atrybuty, a dlaczego pola już nie - nie mam pojęcia. Z atrybutem tokena też jest dziwna sprawa, bo teoretycznie powinien przechować obiekt, a go nie przechowuje. Trzyma tylko stringa. Mógłbym na jego podstawie zregenerować tokena już po zalogowaniu, pobierając obiekt Group, ale nie wiem czy to do końca wydajne rozwiązanie.
Może jest jakiś lepszy pomysł, jak zapewnić tego rodzaju izolację?
a nie za badzo jest to przekombinowane?
user się loguje - wiesz kto to jest, możesz sprawdzić do jakiej grupy ma w danej chwili dostęp (zapisane jest to gdzieś w bazie), określasz mu do jakiej grupy może wejść, co może edytować itd.
może napisz jakiegoś votera, który będzie sprawdzał do jakiej grupy ma mieć dostęp.
przełączenie się do innej grupy to tylko zmiana wpisu w bazie.
mundeck
6.11.2016, 03:16:50
Sam już wpadłem na to, żeby zapisywać to w bazie, ale początkowo chciałem uniknąć takiego rozwiązania, bo nie po to jest sesja, żeby zapisywać to w bazie. To dane sesyjne powinny określać, kto na jakie konto, z jakimi uprawnieniami do jakich zasobów jest zalogowany w danej chwili.
Jeśli chodzi o voterów, to właśnie ten mechanizm wydaje mi się przekombinowany.. Podobnie jak działanie Security w Symfony, które nawet w przypadku gdybym przełączył się na inną grupę, wylogowuje mnie, ponieważ zmieniły się dane Usera (np. pole "group_id" przybrało inną wartość). Pytanie teraz, jak zrobić, żeby przelogowanie następowało automatycznie, żeby user nie był zmuszony wpisywać hasło. Chodzi przecież nie o przelogowanie się na inne konto usera, tylko inną grupę.
Może nie napisałeś o wszystkich ważnych założeniach, ale wydaje mi się, że nadal za bardzo kombinujesz;)
Przełączenie się na inną grupą będzie polegało na zmianie jakiegoś rekordu w bazie na inne id grupy.
Po takiej zmianie user wchodząc na tą nową grupę, będzie miał dostęp, a wchodząc na starą nie będzie miał dostępu. wszystko to sprawdzasz w voter.
Czyli za każdym razem jak sprawdzasz dostęp, musisz pobrać aktualne dane - do której grupy jest przypisany.
A sprawdzanie dostępu zrobisz na początku każdej akcji, do której musi być ten specyficzny dostep określony.
zobacz jak to fajnie jest zrobione:
http://symfony.com/doc/current/security/voters.htmlw kontrolerze jedna linijka, a całe sprawdzanie dostępu do poszczególnych akcjach w jednej klasie.
mundeck
6.11.2016, 13:59:47
W tej chwili testuję możliwość zmiany tego id grupy w trakcie sesji - podczas poprzednich prób nie wiedzieć czemu wylogowywało mi Usera, a teraz nie - i bardzo dobrze, bo takie rozwiązanie byłoby najkorzystniejsze. Choć nadal uważam, że lepiej takich zmian dokonywać w obrębie danych sesji, a nie za pomocą bazy, no ale w tej chwili nie widzę innej możliwości. Zwłaszcza że Symfony przy każdej zmianie aktualizuje Usera i to jest akurat fajne.
Nie za bardzo znam ten mechanizm z Voterami, ale chyba ma on na celu nadawanie uprawnień do poszczególnych zasobów i wykonywaniu na nich akcji, a u mnie to jest określone przez role. Także właśnie prościej będzie zastosować tę zmianę pola w bazie. Ale dzięki za sugestie.
w sesji trzymać takie dane to głupi pomysł. admin zmieni uprawnienia i co?
user dalej będzie sobie hasał po zasobach do których już nie ma dostępu, tylko dlatego, że w sesji zostały jakieś stare dane.
markonix
7.11.2016, 14:13:18
Typowo FW Ci nie pomogę, ale koncepcyjnie j/w - też kiedyś trzymałem takie rzeczy w sesji, a potem się oduczyłem, nawet nie trzymam typu konta w sesji bo to wszystko może się zmienić i nie zawsze jesteś w PHP stanie tego nasłuchiwać - bo ok, profil user sam edytuje i możesz sesje odświeżyć ale co jak inny użytkownik zmodyfikuje Ci jakieś kluczowe parametry profilu, żeby to wykryć musiałbyś każdorazowo sprawdzać zmiany, a jeżeli to już robisz (zapytanie) to nie ma sensu trzymać w sesji.
Trzymasz globalnie listę dostępów do grup, możesz w widoku zrobić selecta - przełączanie i zapisujesz to w sesji lub w bazie. Obie metody troszkę się różnią, np. jeżeli przewidujesz, że ktoś inny może się logować na te konto warto zostać przy sesji. Oczywiście gdy sesja nie istnieje wtedy wyświetlasz domyślną grupę (jak nie ma czegoś takiego to po prostu ostatnią z bazy/listy).
Pilsener
8.11.2016, 08:34:32
1. Dane trzymać w bazie
2. Do uprawnień najlepiej użyć drzewa ról:
https://knpuniversity.com/screencast/symfon...ole-hierarchiesWtedy mamy już gotową implementację. Rolę można zmienić nawet w trakcie sesji bez żadnego problemu.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę
kliknij tutaj.