Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Zalążek frameworka + autoryzacja
Forum PHP.pl > Forum > PHP > Object-oriented programming
Vengeance
Cześć.

Dam może po prostu kod:
http://vengeance.strefaphp.net/tmp/interfe...ion=Source:Show

i zapytam:

Jak efektywnie napisać autoryzacje, tak by można było ją elastycznie zmieniać (txt/sql/ldap) a także włączac/wyłączać i ogólnie z niej korzystać :]

Jak to "fajnie" wpleść w cały kod?

Sorry, jest 3 nad ranem, jak coś to potem uzupełnie pytanie :]
Pa
Nievinny
To robisz tak: Jeżeli w configu auth = true to wykonujesz czynności. W klasie auth powinna być tetoda controlAccess(). Ona sprawdza poziom (dzięsiątkowo 1-99 or więciej), potem zezwolenia: bitowo 2, 4, 8, 16 itd. Można je łączyć i sprawdać wymagane. Klasa powinna też pobierać info o grupach i zezwolaniach prywatnych. To sprawdzić i ok.
crash
A ja tak z innej beczki. Czy przypadkiem nie powinno się dołączać interfejsu do klasy za pomocą implements, a nie tak ja Ty to robisz przez extends?
hawk
Hmm, jakby to ująć... sam nad tym pracuję. W wolnych chwilach. Takie hobby. Jak skończę, to dam znać.

Poza tym:
Cytat
ak efektywnie napisać autoryzacje, tak by można było ją elastycznie zmieniać (txt/sql/ldap)

Autoryzacja to access control. Do tego nie wykorzystuje się LDAP. Nie myl autoryzacji z uwierzytelnianiem. Dlatego z założenia nie lubię systemów, które zawierają klasę "Auth" - to znak, że nie wiadomo, co ta klasa naprawdę ma robić. Proszę mi tylko nie przypominać, jak nazywała się ww. klasa w phiend1 - każdy się uczy na błędach winksmiley.jpg.

@Nievinny: nie tak szybko. Jaki model uwierzytelniania proponujesz? RBAC? W stylu Unixa? Grupy jak w W2k? A w zasadzie pytanie powinno brzmieć: jaki model chce zaimplementować Vengeance?
Vengeance
@crashu: powinno... tak też robie, ale ten kod pisałem coś po północy i coś mi się pomyliło :] Dzięki

@hawk:
Chodzi właśnie oto, czy model autoryzacji powinien być "wymienialny" czy też wpisany na sztywno w framework. Ja osobiście najbardziej lubie pracować wykorzystując system ról + dopisuje do tego grupy które są po prostu zbiorem danych ról.

Mnie nie chodziło w tym wątku o sposoby zorganizowania autoryzacji, ale o wkomponowanie tego w całość.

A co do rozróżneinia Autoryzacji i Autentykacji (Uwierzytelniania) to masz racje... ale właśnie w tym rzecz, jak to "fajnie" wpleść w framework tak bym na przyszłość mógł równie dobrze podpiąć phpGACL czy inne pierdolki.

Czy robić tak jak dotychczas z klasą Request, czyli spójny interfejs a do Core przekazuje instancje klas Autoryzacji i Autentykacji który potem sobie na tym operuje, a gdy nic nie przekaże to po prostu procesy te się nie odbywają?
hawk
No dobrze... uchylę rąbka tajemnicy i napiszę, jak JA to wplatam we framework. W dużym skrócie - nie wplatam i już biggrin.gif.

To zależy, co rozumiemy przez "framework", ale patrząc na twój kod, jest to zgodne z moim rozumieniem - kontroler, MVC, itd. Kontroler nie musi wykonywać sam uwierzytelniania i access control. Powiem więcej - kontroler w ogóle nie musi wiedzieć, że takie coś ma miejsce. I mamy spokój. Im mniej zależności, tym lepiej.

Swoją drogą, kluczem do zrobienia elastycznego systemu auth nie jest wplatanie we framework (bo to jest naprawdę bardzo mały kawałek kodu), ale łączenie się ze źródłem danych. Jak robiłem sobie listę, to wyszło mi dosyć dużo potencjalnych źródeł, które wymagają osobnych driverów: baza danych, LDAP, IMAP, FTP, pliki ini, plik passwd, plik htpasswd, plik haseł Samby, SOAP, ... auć. Kod zarządzający tym wszystkim jest prosty i jak będę miał więcej czasu, mogę wrzucić. Do twojego frameworka też będzie można go podpiąć - żadna różnica.
Vengeance
Postanowiłem, iż autoryzacje i uwierzytelnianie (oraz inne rzeczy) rozwiąże poprzez Intercepting Filter. Musze jeszcze tylko troche lepiej go poznać :] Czy to dobre rozwiązanie?

Na mój mał rozumek, klasy pełniące role Intercepting Filter powinny być na sztywno wpisane w CORE i umożliwiać właśnie zastosowanie filtrów. Czyż nie? Mamy wtedy bardzo elastyczne rozwiązanie.

A tak BTW. jak potem zoragnizować np. pobranie UserName aktualnie zalogowanego użytkownika w celu wyświetlenia tego na stronie (założywszy, iż uwierzytelnianie spełnia odpowiedni filtr)?
chmolu
Tak w ogóle to już sam nie wiem, które jest które? Autoryzacja to sprawdzanie uprawnień? Czy to jest uwierzytelnianie? :/

Cytat
Postanowiłem, iż autoryzacje i uwierzytelnianie (oraz inne rzeczy) rozwiąże poprzez Intercepting Filter. Musze jeszcze tylko troche lepiej go poznać :] Czy to dobre rozwiązanie?


Uprawnienia nie pasują do IF. Dostęp do tej klasy powinieneś mieć w każdym miejscu aplikacji, a Intercepting Filter jest odpalany tylko przed i po wykonaniu akcji. Najpierw będziesz potrzebował uprawnień do akcji, ale później możesz potrzebować sprawdzić, czy użytkownik ma prawo oglądać daną część strony. IMHO najlepiej taką klasę wrzucić do kontekstu, albo zrobić z niej singleton.

Cytat
Na mój mał rozumek, klasy pełniące role Intercepting Filter powinny być na sztywno wpisane w CORE i umożliwiać właśnie zastosowanie filtrów. Czyż nie? Mamy wtedy bardzo elastyczne rozwiązanie.

Nie za bardzo rozumiem, zwłaszcza tego fragmentu: "klasy pełniące role Intercepting Filter powinny być na sztywno wpisane w CORE i umożliwiać właśnie zastosowanie filtrów". Te klasy to nie Intercepting Filter, one same są filtrami.

Wg mnie filtry powinny być jak najbardziej odłączone od jądra. Tylko klasa zajmująca się wczytywaniem łańcuszka filtrów z konfiguracji i wykonywaniem go powinna być częścią core. Resztę ustalasz sam - w pliku konfiguracyjnym.
Vengeance
@chmolu: Już wyjaśniam... najlepiej kodem. Obecnie rozpisałem to tak:
http://vengeance.strefaphp.net/tmp/interfe...ion=Source:Show

Lecz jestem dziś świeżo po zakupie http://helion.pl/ksiazki/php5ob.htm
Dość ciekawie rozpisali tam wzorce itd. i możliwe iż po lekturze dużo zmienie w tym kodzie. Choć mimo to prosze o uwagi, ocene, krytyke.

@chmolu:

Uwierzytelnianie / Autentykacja - Na podstawie danych (najczesciej Login/Hasło czasem np. IP) dokonuje sprawdzenia czy użytkownik jest tym za kogo sie podaje ;P

Autoryzacja - sprawdza czy juz uwierzytelniony użytkownik ma prawo do wykonania danej operacji.

@chmolu:
Autoryzacja / Uwierzytelnianie to będą klasy zwykłe (możliwe że wykorzystam Singleton) a filtry będą tylko odpowiednio z nich korzystać, wywoływać odpowiednie metody celem dokonania tego co ważne :] Czyż źle rozumuje?
chmolu
Cytat
Uwierzytelnianie / Autentykacja - Na podstawie danych (najczesciej Login/Hasło czasem np. IP) dokonuje sprawdzenia czy użytkownik jest tym za kogo sie podaje ;P

Autoryzacja - sprawdza czy juz uwierzytelniony użytkownik ma prawo do wykonania danej operacji.

dzięki, bo już mi się kompletnie pomieszało smile.gif

Cytat
... filtry będą tylko odpowiednio z nich korzystać, wywoływać odpowiednie metody celem dokonania tego co ważne :] Czyż źle rozumuje?

IMO źle, bo to już nie będzie Intercepting Filter.

Intercepting Filter odpowiada tylko i wyłącznie za pre-processing input/request i post-processing output/response.
Vengeance
Dobrze, że o tym mówisz... tak jak mówiłem niewiele wiem jeszcze o dokładnej idei Intercepting Filter. Jakoś nie ma wielu fajnych źródeł o tym.

Więc jak najlepiej (oczywiście twoim zdaniem, bo co osoba to inne myślenie) zorganizować autoryzacje i uwierzytelnianie?
Ttak by twórca aplikacji wykorzystującej framework mógł szybko zdecydować i wprowadzić jedynie uwierzytelnianie - bo np. autoryzacja mu niepotrzebna.

-edit-
Wg. moich ksiazkowych pozycji, moje rozumowanie nie jest w cale błędne.
Co prawda, książka poruszyła temat Intercepting Filter przy temacie Dekoratora,
ale wystepują tam właśnie filtry do autoryzacji, buforowania itd. A to, że taki filtr korzysta z zew. klasy przecież niczemu nie przeszkadza.


ps. Zaktualizowałem także swój kodzik o pewne komentarze, linki itd.
Do obejrzenia tu:
http://vengeance.strefaphp.net/tmp/interfe...ion=Source:Show
chmolu
Cytat
Więc jak najlepiej (oczywiście twoim zdaniem, bo co osoba to inne myślenie) zorganizować autoryzacje i uwierzytelnianie?
Ttak by twórca aplikacji wykorzystującej framework mógł szybko zdecydować i wprowadzić jedynie uwierzytelnianie - bo np. autoryzacja mu niepotrzebna.

Uwierzytelnianie zrobiłbym jako IF (byłoby jak plugin), a autoryzację wywalił do klasy, która nie łączyłaby się z frameworkiem. Najlepiej, żeby wrzucić ją do kontekstu, albo zrobić z niej singleton.

Cytat
Wg. moich ksiazkowych pozycji, moje rozumowanie nie jest w cale błędne.
Co prawda, książka poruszyła temat Intercepting Filter przy temacie Dekoratora,
ale wystepują tam właśnie filtry do autoryzacji, buforowania itd. A to, że taki filtr korzysta z zew. klasy przecież niczemu nie przeszkadza.

Implementacja wzorców jest różna, ale jakoś nie widzi mi się Autoryzacja jako IF. To po prostu nie pasuje, bo do autoryzacji musisz mieć dostę cały czas, a nie tylko przy pre- lub post-processingu.

Kod przejrzę później, bo jestem teraz naprawdę zajęty.

//obiecana recenzja winksmiley.jpg

Przyczepię się tylko do filtrów. Kombinujesz z tym odkładaniem danych do rejestru. Spróbuj zrobić coś takiego:

Kod
class FooFilter implements Filter
{
      public function execute($chain)
      {
            echo 'app starting...';
            $chain->next();
            echo 'app finishing...';
      }
}


I teraz są 2 wyjścia:
- zrobić, żeby kontroler implementował InterceptingFilter
- zrobić wspólnego przodka dla akcji i filtrów, żeby mogły istnieć razem w łańcuszku

Ale myślę, że pierwsze rozwiązanie jest lepsze.
Vengeance
Przyznam się, że nie dokońca rozumiem o co ci chodziło :]

Cytat
- zrobić, żeby kontroler implementował InterceptingFilter

Obecnie tak jest.

Cytat
Kombinujesz z tym odkładaniem danych do rejestru.

Chodziło zapewne o klase Registry. Tak więc istnieje ona tylko po to, by filtry mierzące czas wykonywania aplikacji miały możliwość przekazania sobie czasu (pomijam, iż tego typu filtr odbiega chyba troche od podstawowego zastosowania Intercepting Filter)

A podany przez ciebie kod, różni się dla mnie tylko tym, iż procedura wykonywania kolejnych filtrów przekazana została filtrowi, a "zabrana" z klasy FilterManager.

Chodziło ci w tym oto, aby Filtr miał możliwość w każdym momencie dokonania jakiś zmian w łańcuszku? (to przekazywanie $chain jako argumentu)

Dzięki za zainteresowanie
chmolu
Sorry za moje majaczenia smile.gif

Chodziło mi o to, że sposób, który masz obecnie zmusza cię do pisania dwóch filtrów: startTime i EndTime. A to co pisałem wyżej eliminuje to.

  1. <?php
  2.  
  3.  class Benchmark implements Filter
  4. {
  5.  public function execute($chain)
  6.  {
  7. $start = this->getMicrotime()
  8. $chain->next();
  9.  
  10. echo '<br/>Time: ' . ($this->getMicrotime() - $start) . &#092;"<br/>n\";
  11.  }
  12. }
  13.  
  14. ?>


To samo możesz zastosować do output bufferingu.

  1. <?php
  2.  
  3.  class Bufferer implements Filter
  4. {
  5.  public function execute($chain)
  6.  {
  7. ob_start('ob_gzhandler');
  8.  
  9. $chain->next();
  10.  
  11.  }
  12. }
  13.  
  14. ?>


Mam nadzieję, że teraz już wiesz co mam na myśli smile.gif
Vengeance
Ah, już zrozumiałem smile.gif
$chain->next(); wykonuje następny filtr, lub w końcowym etapie akcje.
Chyba nawet można to będzie ładnie zaimplementować poprzez wzorzec Decorator.

Dzięki.
hawk
Słusznie uważacie, że autoryzacja wymaga czegoś więcej niż filtra - jakiejś np. klasy dostępnej z innych miejsc aplikacji. Ale tak naprawdę nie ma o czym tutaj długo rozmawiać. Bo co jest potrzebne?

Po uwierzytelnianiu mamy nazwę zalogowanego użytkownika. W zależności od użytego modelu możemy mieć np. grupy, do których należy. Jedno i drugie musimy wrzucić do sesji. Teraz pytanie: co powinna mieć "klasa do autoryzacji" poza tymi dwiema informacjami? Plus kilka metod do sprawdzania przynależności do grup. Jeżeli nic, to problem nie istnieje. Pakujemy te dane w maksymalnie prosty obiekt, wrzucamy do sesji i mamy już załatwioną praktycznie autoryzację. Teraz możemy sobie zrobić filtr, który przed wykonaniem akcji sprawdzi potrzebne uprawnienia. Możemy też odwołać się do naszego obiektu bezpośrednio z kodu akcji. I tyle.
Vengeance
Słusznie. A jeśli ktoś wymaga by uwierzytelnianie było wykonywane każdorazowo można w klasie stworzyć statyczne argumenty ($username, $groups etc.) wypełnianie przy pomyślnym zalogowaniu.

Skorzystać z tego może filtr autoryzacji jak i aplikacja z kazdego miejsca (np. system szablonów celem wyświetlenia zalogowanego usera).

----
A wracając do samego FilterManager co sądzicie to takiej koncepcji:
Na początek dodajemy filtry w odpowiedniej kolejności, tak jak jest to w moim kodzie. Stworzony łańcuch przekazujemy do Managera. On, w pętli wykonuje kolejne filtry (pobiera kolejny filtr z wierzchu tablicy po czym go usuwa - array_shift()) do póki tablica filtrów będzie pusta.

Sam filtr zaś może (ale nie musi) wykonać kolejny filtr z łańcucha. Łańcuch jest przekazywany tak jak w kodzie @chmol-a
W takim wypadku filtr jest wykonywany wg. tej samej zasady jak poprzez Managera.

Co to da? Nie każdy filtr robi coś "przed i po". W takim filtrze możemy usunąć wywołanie kolejnego filtra (po co utrudniać prace?). Jeśli zaś potrzebne nam jest wykonanie jakieś operacji przed i po uruchomieniu akcji (innych filtrów) możemy wywołać metode next().


! Najnowsza wersja kodu:
http://vengeance.strefaphp.net/tmp/interfe...ion=Source:Show

Teraz zajme się lepszym opracowaniem Request i Response. Jeśli ktoś ma jakieś sugestie (a na pewno ma) to możemy tu o tym pogadać :]
squid
Moja osobista oponia na ten temnat to taka ze potwierdzeniem tozsamosci usytkownia zajumuje sie controler i do tego mam wbudowana metode auth(). Jesli uzytkownik nie jest zalogowany to przypisuje go do grupy uzytkownikow anonimowych. Nie ma mozliwosci wylaczenia tego poniewaz nie widze takiej potrzeby a widze potrzebe sledzenia uzytkownika nawej zupelnie obcego stad kady nalezy go jakies grupy. Oprocz grup sa takze pojedynczy uzytkownicy ktorzy moga nalezec do dowolnej liczby grup z przedzialu <0,max) i dziedziocza po nich uprawnienia. I tu sprawdzanie uprawnien uzytkownika powierzam zupelnie niezaleznej klasie najlepiej zeby implementowala pewien interfejs wtedy mozna ja wymieniac i testowac rozne rozwiazania, kontroler nic nie wie o tej klacie poniewaz to model z niej kozysta zeby stwierdzic czy uzytkownik moze wykonac jakas operacje. W skrocie system uprawnien opiera sie na czym takim: czy obiekt X ma prawo do wykonania operacji Y na obiekcie Z. X - to uzytkownik wykonujacy akcje na modelu Z. Takze widok w razie potrzeby moze sprawdzic czy np. usytkownik ma prawo do otrzymania pliku pdf czy tylko (x)html.
Wg mnie duzym bledem jest uzaleznianie obieku sprawdzajacego dostep od jakis baz danych i itd. w moim dziwnym frameworku (mam nadzieje ze przejde na phiend 2 winksmiley.jpg ) tylko jeden obiekt zajmuje sie danymi a cala reszta czy to modele czy systemy uprawnien zleca mu wydobycie informacji w sposob niezalezy od zrodla, to dopiero DataAccesObjest rozpoznaje zrodlo z jakiego musi skorzystac i wykonuje operacje dostepowe zwracajac rzadane wartosci. Choc szczerze mowiac kozystam tylko z BD to czy to bedzie ftp czy cos innego wystarczy napisac klase pochodna od DAO i wklepac konfiguracje (nad ktora pracuje smile.gif )
Imperior
@hawk: widze jedną lukę... może tylko dla mnie to luka... ale oprócz sprawdzenia uprawnień w filtrze, potrzebne jest sprawdzanie uprawnień na rządanie. Dajmy na przykład tę stronę forum... trzeba sprawdzić, czy użytkownik może mieć przycisk edytuj/usuń posta.

---

A tu już musi mieć jakiś interfejs.
squid
Cytat(Imperior @ 2005-07-12 12:59:35)
@hawk: widze jedną lukę... może tylko dla mnie to luka... ale oprócz sprawdzenia uprawnień w filtrze, potrzebne jest sprawdzanie uprawnień na rządanie. Dajmy na przykład tą stronę forum... trzeba sprawdzić, czy użytkownik może mieć przycisk edytuj/usuń posta.

u mnie tym i wszystkimi innymi rzeczami zwiazanymi z uprawnieniami zajmuje sie jedna osobna klasa ktora wlasnie moze byc wywolana w dowolnym momecie ale nie jest na sztywno zwiazana z systemem
hawk
@Imperior: IMHO wcale nie ma luki. Zgadzam się, że jest taka potrzeba. Ale nie zgadzam się, że potrzeba do tego nowego interfejsu.

A konkretnie: skoro musimy wrzucić do sesji nazwę użytkownika i jego grupy (załóżmy, że system działa na grupach), to zróbmy do tego małą klasę:
  1. <?php
  2.  
  3. class Credentials {
  4. private $sUser;
  5. private $aGroups;
  6.  
  7. public function __construct($sUser, $aGroups) {
  8. $this->sUser = $sUser;
  9. $this->aGroups = $aGroups;
  10. }
  11.  
  12. public function getUser() {
  13. return $this->sUser;
  14. }
  15.  
  16. public function getGroups() {
  17. return $this->aGroups;
  18. }
  19.  
  20. public function belongsTo($sGroup) {
  21. return in_array($sGroup, $this->aGroups);
  22. }
  23.  
  24. public function belongsToAll($aGroups) {
  25. return (count(array_diff($aGroups, $this->aGroups) == 0);
  26. }
  27.  
  28. public function belongsToAny($aGroups) {
  29. return (count(array_intersect($aGroups, $this->aGroups) > 0);
  30. }
  31. }
  32.  
  33. ?>

I to już praktycznie wszystko. Jak zrobię klasę do sprawdzania uprawnień, to przecież ona nie będzie nic robiła poza przekazaniem wywołania metody.

Chyba że robimy uprawnienia do konkretnego obiektu (np. posta, artykułu), ale to już jest część systemu przechowywania tych obiektów (trzeba zapisać właściciela i uprawnienia dla poszczególnych grup).
Vengeance
Ok, filtry już są odpalane przez $chain->next() czyli tak jak zaproponował @chmolu. Teraz pytanie. Czy tworzyć oddzielny filtr do wywołania Core no i akcji podanej przez usera zarazem, czy też zrobić tak (obecnie tak zrobilem) iż:

class Application implements Core, FilterManager, Filter

tak więc Core jest jednocześnie managerem filtrów jak i filtrem :]
Jak lepiej? Wiecie oco chodzi, prawda? snitch.gif
squid
Cytat(Vengeance @ 2005-07-12 22:00:21)
Ok, filtry już są odpalane przez $chain->next() czyli tak jak zaproponował @chmolu. Teraz pytanie. Czy tworzyć oddzielny filtr do wywołania Core no i akcji podanej przez usera zarazem, czy też zrobić tak (obecnie tak zrobilem) iż:

class Application implements Core, FilterManager, Filter

tak więc Core jest jednocześnie managerem filtrów jak i filtrem :]
Jak lepiej? Wiecie oco chodzi, prawda? snitch.gif

tak wogole to co to sa te filtry (tutaj) ?
serafin
Veng: pomysl moze i niezly. Dzieki niemu mozesz "cala" aplikacje objac filtrem... ale.. sam pomysl czy jest to zgodne z idea IF.

Pozdrawiam
aleksander
jeżeli we frameworku nie ma czegoś takiego jak łańcuchy akcji to sprawdzanie uprawnień może odbywac się w filtrze.
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.