Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: ACL - własny
Forum PHP.pl > Forum > PHP
cojack
Witam,
Potrzebuje do swojego cms'a napisać własny ACL i teraz się bije z myślami jak to zrobić, nie podoba mi się w zendowskim acl serializacja danych, nigdy jej nie używałem i używać nie będę (chyba że będę jakoś zmuszony w co wątpię) ale nie teraz o tym mowa.

Więc wymyśliłem sobie że będę jechał na bitach, np:
  1. $a = 2;
  2. $b = 4;
  3. $c = 8;
  4. $d = $a + $b;
  5. if ( $d & $c )
  6. echo 'Go go go masterczułki';
  7. else
  8. echo 'No nie 4hp';


I teraz czy robić to na grupy + osobno dla usera, czy tylko na grupy? Wiadomo tylko na grupy prościej, a na jedno i drugie, większe możliwości.

Macie jakieś inne pomysły?
phpion
Ja w swoim ACL mam swego rodzaju hierarchię uprawnień:
- uprawnienie przypisane bezpośrednio do zasobu (priorytet = 0),
- uprawnienie przypisane do grupy, do której należy użytkownik (priorytet = 1),
- uprawnienie przypisane bezpośrednio do użytkownika (priorytet = 2).
Dzięki temu możesz łatwo stworzyć taką sytuację, gdy grupa G ma dostęp do zasobu Z, ale równocześnie w grupie tej użytkownik U, który nie może mieć dostępu. Wówczas wystarczy jawnie odebrać jemu uprawnienia i po sprawie.

Co do serializacji: nie mów "hop". Serializacja okazuje się całkiem szybkim mechanizmem i często jest bardzo przydatna (np. gdy chcesz przechować jakiś obiekt w sesji czy w pliku).
cojack
Co do hierarchii to też o tym myślałem, bo mimo wszystko to może być czasem potrzebne, sprawdzanie na 2-3 poziomach dostęp do aplikacji przez użytkownika. A co do samych uprawnień? :]
erix
http://artykuly.zyxist.com/czytaj.php/system_uprawnien_w_php

Choć moim zdaniem, nie ma sensu robić relacyjnego modelu dla danych, które są raczej sztywno ustawione. Uprawnienie<->kolumna byłoby IMHO rozsądnym rozwiązaniem.
cojack
Ale gościu nakombinował, strasznie... nie podoba mi się ten sposób dostępu do modułów. Wystarczy że sobie zmienisz nazwy controlerow a router jest na tyle ubogi że nie możesz w nim definiować dla controlera innej nazwy i dupa, leżysz i kwiczysz, mało flexible.

A poza tym, struktura drzewiasta, mam złe wspomnienia z tym, lepiej to rozbić na np:

Module
- id ++
- name string

Action
- id ++
- module_id int
- name string // nie unique!

Oraz

User
- id ++

Group
- id ++
- name string
- value int

UserToGroup
- user_id int
- group_id int

Rule
- id ++
- module_id
- action_id
- value

I np jeżeli mamy np 3 grupy:

User, Editors, Admin, każda z nich ma inne value w Group, value jest sumą kolejnych 2^n poziomów, więc jeżeli mamy np moduł articles a w nim akcje index, list, edit, delete, show, to te akcje mają wartości: 2, 4, 8, 16, 32, jeżeli chcemy by nasz User mógł przeglądać artykuły nasza grupa będzie miała wartość: 2+4+32 czyli 38, i aby sprawdzić czy User z danej grupy może patrzeć tam gdzie chce sprawdzamy value grupy z value rule, nie ma możliwości by np do jednej grupy dopisać dwa razy index, index. Bo wtedy miałby dostęp do list. A że na raz sprawdzamy tylko jedną akcję i tylko jeden moduł, nie będzie potrzeby stosowania podwójnego && winksmiley.jpg
phpion
Znowu przytoczę swój przykład smile.gif Mam zasoby tworzone na zasadzie ścieżek czyli np.:
user/edit
user/delete
Dodatkowo zasoby mają "przestrzenie nazw" czyli po prostu typy. Powyższe mają typ "action", ale mogą być również inne typy np. "form_field". Sprawdzenie dostępu odbywa się na zasadzie wywołania rekurencyjnego "od tyłu" aż do momentu znalezienia definicji dostępu do zasobu czyli pytając o dostęp do:
moj/super/mega/zasob
sprawdzane są po kolei:
moj/super/mega/zasob
moj/super/mega
moj/super
moj
Dzięki temu mogę jedną definicją odebrać uprawnienia do całego kontrolera. Jeżeli mi się zamarzy to mogę potem nadać dostęp do danej akcji w kontrolerze. Jak na razie rozwiązanie sprawdza się nieźle smile.gif
cojack
No tak, masz rację, w moim przykładzie jedynym minusem jest to iż gdy będzie dużo modułów, to rozmiar 2^n będzie kolosalny, już 2^20 sięga daleko poza int. Będę musiał to przemyśleć, cały czas próbuję znaleźć mega optymalne rozwiązanie, które miało by od razu zaimplementowane dziedziczenie po grupach użytkowników. Ciężko będzie.
Zyx
Cytat(cojack)
Ale gościu nakombinował, strasznie... nie podoba mi się ten sposób dostępu do modułów. Wystarczy że sobie zmienisz nazwy controlerow a router jest na tyle ubogi że nie możesz w nim definiować dla controlera innej nazwy i dupa, leżysz i kwiczysz, mało flexible.


Przy projektowaniu czegokolwiek polecam rezygnację z podejścia "system jest do bani, bo przycisk w prawym górnym rogu jest zielony, a nie czerwony". Jeśli chcesz stworzyć system ACL, który w pewnym momencie nie rozjedzie Ci się z powodu błędów logicznych w rozumowaniu, musisz umieć pomijać takie szczegóły, jak sposób nazwania zasobów. To jest tylko kwestia implementacyjna - chyba nie sądzisz, że będę przez 90% artykułu wyprowadzał cały framework jedynie po to, by móc szybciej nazwę kontrolera sobie zmienić, a meritum będzie w ostatnich 10% tekstu. To, że implementacja czegoś nie ma, nie znaczy, że cała idea jest do kitu lub mało elastyczna. Zwróć uwagę, że to Ty napisałeś, że elementy w acl_resource to moduły - ja nie robiłem nigdzie tak daleko idących założeń. Więcej - nie zakładałem też, że acl_role musi być grupą użytkowników - jeśli wstawisz w to miejsce zwykłego użytkownika, siła wyrazu mechanizmu rozpoznawania uprawnień nie zmieni się. Możesz tam dać i jedno, i drugie, możesz wreszcie wymyślić jakiś zupełnie odjechany system i nie wpłynie to na sam algorytm.

Przykładowy problem, z którym Twój ACL sobie nie poradzi, a mój tak. Najpierw szkic sytuacji:
- Mamy artykuły podzielone na kategorie.
- Do artykułów można dodawać komentarze.

Problemy:
- Pewna kategoria jest widoczna tylko dla konkretnej roli.
- Pewna rola może moderować komentarze w wybranej kategorii artykułów.
- Pewna rola może moderować komentarze we wszystkich kategoriach artykułów.
- Pewien artykuł może być modyfikowany przez wybraną rolę.

Ty sztywno związałeś akcje z modułami, nie możesz więc przydzielać uprawnień do pojedynczych elementów zbioru. U mnie jest to jedynie kwestia wymyślenia odpowiedniej reprezentacji drzewka, np. /frontend/articles/(id kategorii)/article/(id artykułu)/comments/edit. Pełne uprawnienia do edycji komentarzy to 1 dla ścieżki /frontend/articles/*/article/*/comments/edit, pełne uprawnienia do edycji komentarzy w kategorii to 1 dla ścieżki /frontend/articles/17/article/*/comments/edit. Co więcej, nawet jeśli przydzieliliśmy komuś prawo do edycji zasobu, a nagle musimy zablokować mu dostęp do całego działu, wszystko sprowadza się do zmiany stanu na 0 dla ścieżki /frontend/articles... co sprowadza nas do tego, że artykuł prezentuje niemal w 100% identyczne rozwiązanie, jak to, które przedstawił phpion i które tak Ci się podobało.

Podsumowując, najpierw przemyśl sobie cały problem w oderwaniu od wszystkiego, a później myśl, jak go zaimplementować. Nie na odwrót.
cojack
Zyx jedyne co mi się nie podoba w Twoim rozwiązaniu to to że implementuje router (w pewnym sensie) again, a mi na tym nie zależy. Jeżeli mam już gotowy router, to należy wykorzystać jego moc nie "pisać go od nowa". Nie chce zapisywać względnych ścieżek do bazy, ani używać pętli ala rekurencji. Muszę to przemyśleć.


@edit
Rzucę okiem jak to jest w linuxie zrobione, może jak nie będzie trudne w implementacji, to zastosuję.
Zyx
A MS Word implementuje funkcjonalność programu graficznego (w pewnym sensie). W tym kodzie nie ma żadnego routera! Jeśli dla Ciebie sam fakt użycia ciągów tekstowych do prostszej identyfikacji zasobów jest dowodem, że tam jest router, to gratuluję bujnej wyobraźni. I kto Ci broni do ścieżki wpisać ID modułu: /frontend/7/edit? Fakt, relacja to nie będzie, ale idźmy dalej - kto Ci broni dodać pole module_id do acl_resource? Wydawało mi się, że dostatecznie klarownie wyjaśniłem, że artykuł prezentuje PRZYKŁADOWĄ implementację i to są drugorzędne szczegóły? Względnych ścieżek też tu nawiasem mówiąc nie ma.

Jeśli oczekujesz konkretnych pomysłów na ACL, sprecyzuj swoje wymagania - na razie zarzuciłeś kawałkiem kodu wykorzystującym flagi, bąknąłeś coś serializacji, o grupach użytkowników i zadałeś zasadnicze pytanie: "macie jakieś pomysły?" Pewnie, że mamy, i to sporo, tylko jak coś tu komuś doradzić, kto nie napisał nawet, jakiej funkcjonalności właściwie oczekuje? Byłoby z tym dużo prościej i otrzymałbyś dużo konkretniejszą poradę, niż tylko zarzucanie dziesiątkami linków i pomysłów w nadziei, że któryś Ci się spodoba. Przykładowo, byłbym wtedy w stanie powiedzieć Ci, czy w ogóle taki system da się napisać bez użycia pętli i rekurencji...

PS. Rozwiązanie przedstawione w artykule było wzorowane na jednej z koncepcji linuksowego systemu ACL... smile.gif
cojack
No mam trochę nie uporządkowane myśli, ale to chyba jak każdy programista, coś chce powiedzieć, o czymś myśli a mówi o czymś innym tongue.gif Ale chyba rozwiązałem swoje bolączki, tackle 6 lat temu jakiś ziom napisał acl'a, teraz go tylko przepiszę do php 5 + adaptacja dla doctrine, i udostępnie na tej samej licencji, czyli gpl.

Więcej info: http://sourceforge.net/projects/tackle/
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.
Invision Power Board © 2001-2025 Invision Power Services, Inc.