Temat: Gdzie acl->check()

Hej, mam pytanko:

Pytanie: z waszego doswiadczenia gdzie uzywacie sprawdzania czy klient ma prawo dostepu?

Opis: Postanowilem srobowac swoich sil z ACL i chyba zalapalem oco biega. Do testow stworzylem mala testowa stronke z mozliwoscia logowania i powstal problem.
Czy efektywnie jest
(1) podczas logowania zapisywanie do zmiennej session calej tabeli praw dostepu czy tez
(2) podczas wywolywania kazdej funkcji w dowolnym kontrolerze sprawdzac prawa a moze
(3) w modelu przed uzyciem funkcji save albo gdzies zrobic warunek sprawdzajacy, czy tez
(4) polaczyc dwie metody i zapisac prawa i sprawdzac w zmiennej czy ktos ma prawa w kontrolerze lub
(5) inaczej ??:P

2

Odp: Gdzie acl->check()

Cześć,

Można np. zapisać dane logowania do zmiennej przechowywanej sesji po zalogowaniu, a potem w app_controller.php, w akcji beforeFilter() /* metoda wywoływana dla każdej akcji w każdym kontrolerze*/ sprawdzać istnienie tej zmiennej przez if($this->Session->check('logged_user')){...}. Dla niektórych akcji sprawdzanie tej zmiennej może spowodować zapętlenie się apache'a, więc trzeba zadbać o to, żeby część z metod mogła być wywoływana przez niezalogowanego user'a (m. in. metoda logowania , i wylogowania oraz index dla niezalogowanego user'a). Wyjaśnię to może na przykładzie (niestety nie będzie to przykład stricte ACL, bo nie jestem przy swoim komputerze i muszę pisać z głowy hmm ).

Załóżmy, że masz 3 kontrolery, users_controller, app_controller oraz pages_controller.

w app_controller masz tylko funkcję wyglądającą mniej więcej tak:

function beforeFilter(){
        if($this->Session->check('user') == false)
            {
                //co zrobic z niezaqlogowanym  userem
               //np, przekierować go na index
                 $this->redirect('/pages/index')
            }else{
                   $user=$this->Session->read('user');
                        //co zrobić z zalogowanym userem
            }
    }

Wszystko ok, tylko jeśli komuś wygaśnie sesja, to cake będzie go próbował przekierować na stronę główną, na której sprawdzane jest jeszcze raz czy jest zalogowany (metoda beforeFilter w app_controller nadal działa) i mamy pętlę gotową. Jak temu zapobiec? Bardzo prosto smile

Trzeba w kontrolerze pages_controller.php przedeklarować metodę beforeFilter (Cake najpierw wykonuje metodę w kontrolerze niższego rzędu, po czym, jeśli jej tam nie znajdzie przechodzi wyżej. A więc, w kontrolerze pages_controller dodajemy metodę:

function beforeFilter(){
                if(in_array($this->action,$allowed_actions)){
                       //nie jest sprawdzane czy user jest zalogowany
                }else{
                      //wywołujemy akcję beforeFilter z kontrolera nadrzędnego (sprawdzamy czy user jest zalogowany)
              parent::beforeFilter();
                }
    }

No dobrze, ale skąd wziąć zmienną $allowed_actions? Trzeba ją zdefiniować jako tablicę stringów oznaczających akcje dla których nie trzeba być zalogowanym.
W wypadku pages controller będzie to:

var $allowed_actions = array('index');

W users controller pewnie coś w stylu:

var $allowed_actions = array('login','logout','register');

To chyba wystarczy aby sprawdzanie credentials działało szybko i przejrzyscie, bez konieczności zbędnego mieszania w kodzie w wypadku ewentualnych poprawek.

Mam nadzieje że napisałem w miarę jasno. Kod może zawierać błędy, bo piszę z głowy.

Pzdr,

Ostatnio edytowany przez darek_dobron (2008-12-12 23:36:25)

3

Odp: Gdzie acl->check()

Uuuu spora odpowiedz.. dzieki ale potrzebuje sie z nia blizej zapoznac aby cos odpowiedziec ;] Nie omieszkam tego zrobic jak przetestuje Twoj sposob ;]

4

Odp: Gdzie acl->check()

Da się jakos sprawdzic prawa w modelu? Cos na styl:

Model:
function saveData() {
if($this->acl->check(%$^$%^%^%^))
   $this->save();
}

5

Odp: Gdzie acl->check()

ACL to component -> wykorzystuje się go w controllerze i tam powinno odbywać się sprawdzanie praw;

6

Odp: Gdzie acl->check()

A szkoda bo jest cos takiego jak beforeSave ;]

7

Odp: Gdzie acl->check()

Chciałbyś wykorzystywać ACL'a do ustawiania dostępu do każdej wywoływanej metody w modelu ?? smile Listy kontroli dostępu wykorzystuje się na wyższym poziomie niż dostęp do bazy BD. Świetnie spisuje się przy określaniu dostępu do kontrolerów i ich akcji.

8

Odp: Gdzie acl->check()

w sumie to malem pomysl tylko z uzyciem tego w modelu w wypadku save() i delete() zeby przed kazdym wywolaniem sprawdzac czy osoba ktora to robi ma do tego prawo ;]

PS: a tak na marginesie jak to robicie w praktyce bo ja to chodze po omacku niestety i mam cos takiego:

przykladowy kontroler:

    function beforeFilter() {
        $this->checkSession();
        $this->aroAlias = 'User::'.$this->Session->read('User.id');
        $this->acoAlias = $this->Project->name;   
    }

    function show($id = false) {
        if($id && is_numeric($id)) {
            $tempAro = $this->aroAlias;
            $tempAco = $this->acoAlias.'::'.$id;
            if($this->Acl->check($tempAro, $tempAco, 'read')) {
                $this->data = $this->Project->findById($id);
            } else {
                $this->redirect('user/login');
                exit();
            }
            $this->data = $this->Project->findById($id);           
        }
    }
   
:koniec

9

Odp: Gdzie acl->check()

duke_piotr napisał/a:

(1) podczas logowania zapisywanie do zmiennej session calej tabeli praw dostepu czy tez

Nie. Dlatego ze raz zapisanych do sesji uprawnien nie dasz rady zmienic w czasie rzeczywistym. Zalozmy ze blednie nadasz uzytkowniki uprawnienia super hiper admina, ten sie zaloguje ... i po ptakach wink

maciek napisał/a:

Chciałbyś wykorzystywać ACL'a do ustawiania dostępu do każdej wywoływanej metody w modelu ?? smile Listy kontroli dostępu wykorzystuje się na wyższym poziomie niż dostęp do bazy BD. Świetnie spisuje się przy określaniu dostępu do kontrolerów i ich akcji.

Niekoniecznie, ACL w kłejku jest troche kulawy. Załóżmy że masz tabele gdzie rekordy są dzielone pomiędzy użytkownikami np :

tabela datas :
id    field_1, field_2, ........, field_n
1     ........., .........., ........, .........
2     ........., .........., ........, .........
3     ........., .........., ........, .........
4     ........., .........., ........, .........
5     ........., .........., ........, .........

mamy 3 userow : user1 , user2, user3

przypadek 1.
this->Data->find("all") dla usera 1  powinien zrocic rekordy o id 1,2,3 (user1 posiada uprawnienia R dla rekordow 1,2,3)
this->Data->find("all") dla usera 2  powinien zrocic rekordy o id 2,4,5 (user2 posiada uprawnienia R dla rekordow 2,4,5)
this->Data->find("all") dla usera 3  powinien zrocic rekordy o id 1,5 (user3 posiada uprawnienia R dla rekordow 1,5)

przypadek 2.
przy probie aktualizacji , odczytu, usuniecia  przez user 1 rekordu o id 4 lub 5 - model powinien zwrocic blad informujacy o niedostacznyc uprawnieniach. Tak samo sprawa wyglada przy aktualizacji wile rekordow naraz.

itd ...

Moim zdaniem to wlasnie zadanie dla ACL'a - ktorego brak w kłekowej implementacji ww, oczywiscie da sie to osiagnac i w tej chwili wprowadzajac dodatkowe tabele  lub filtrujac z wykorzystaniem ACL'a wyniki dowolnego zapytania (SELECT) , lub sprawdzajac uprawnienia (DELTE,UPDATE, REPLACE), ale powinno to byc zrobione automagicznie przez model / behavior.

Ewentualnie taka częśc logiki powinna być osadzona w bazie danych ( nie wiem czy to możliwe np w przypadku mysql).

Ostatnio edytowany przez robal77 (2009-03-23 19:59:02)

10

Odp: Gdzie acl->check()

robal77 napisał/a:

Nie. Dlatego ze raz zapisanych do sesji uprawnien nie dasz rady zmienic w czasie rzeczywistym. Zalozmy ze blednie nadasz uzytkowniki uprawnienia super hiper admina, ten sie zaloguje ... i po ptakach wink

Troche sie pozmienialo i juz nie aktualne (w tym watku jest bardziej aktualne pytanie o kontroler w ACL smile ) wiec sie tylko uczepie odpowiedzi tongue

Jezeli blednie nadam komus prawa to i tak dupa czyz nie? Bo jezeli blednie nadalem tutaj to i na 99% blednie jest wszedzie indziej wiec jak dupa to dupa. W twoim przypadku to raczej chodzi o dodatkowe zabezpieczenie hiper admina zeby jezeli juz sie cos takiego wydarzy to zeby bylo jakies dodatkowe zabezpieczenie -> tutaj wchodzi ACL i dodatkowe sposoby uwiezytelniania (PHP_AUTH_USER czy cos).

PS: co sadzisz o przykladowym kontrolerze z nowszego pytania z gory ??:D

11

Odp: Gdzie acl->check()

@duke_piotr co by bylo jasniej, jezeli dane o uprawnieniach beda zapisywane do sesji, po zalogowaniu sie i dasz komus tego super hiper admina, a ten sie zaloguje ... nie zmienisz tego, puki delikwent sie nie wyloguje - o ile bedziesz swiadom tego faktu to mozesz zabic sesje delikwenta. W przypadku zmian w czasie rzeczywistym mozesz odebrac delikwentowi uprawnienia, wprost z aplikacji, zanim ten zdazy kliknac na cokolwiek.

Tak jak pisalem wczesniej, kontrola dostepu do rekordow powinna spoczywac na behaviorze lub modelu a nie na kontrolerze, wieczorem wrzuce pierwsza wersje alpha takiego beaviora ....

12

Odp: Gdzie acl->check()

Wracajac do pytania:  to jak sprawdzic uprawnienia w modelu (np w beforeSave) ??:D

Nie chce sie klocic tak tylko teoretyzuje ;]
Twoje rozwiazanie (nie trzymania w sesji uprawnien) ma faktycznie zalety - pytanie czy warto obciazac aplikację jezeli przyczny (uprawnienia hiper usera) i tak sie nie da usunac, a w przypadku odkrycia bledu (czy tak czy siak odkryjemy to w tym samym czasie) zabijamy mu sesje i zmieniamy prawa (to moze wydajniej bylo by zrobic funkcje zabijajaca sesje konkretnemu userowi niz wpychac wszedzie na sile sprawdzanie praw ?? ).

Ostatnio edytowany przez duke_piotr (2009-03-24 16:36:48)

13

Odp: Gdzie acl->check()

duke_piotr napisał/a:

Wracajac do pytania:  to jak sprawdzic uprawnienia w modelu (np w beforeSave) ??:D.

Napisalem ze takiego behaviora w fazie alpha wrzuce wieczorem.


duke_piotr napisał/a:

pytanie czy warto obciazac aplikację jezeli przyczny (uprawnienia hiper usera) i tak sie nie da usunac, a w przypadku odkrycia bledu (czy tak czy siak odkryjemy to w tym samym czasie) zabijamy mu sesje i zmieniamy prawa (to moze wydajniej bylo by zrobic funkcje zabijajaca sesje konkretnemu userowi niz wpychac wszedzie na sile sprawdzanie praw ?? ).

Nic nie obciazasz sprawdzajac w ten sposb, obojetnie czy masz 10 czy 1000 uzytkownikow. Po to zostaly wymyslone systemu cachowania zeby odciazyc aplikacjie , wsytraczy uzyc memcached + apc i nie bedziesz widziec roznicy i przy 100 000 uzytkownikow online naraz.

Poza tym kurde w kłejku nieumiejetnie uzyc asocjacji  lub uzywac w widokach i kontrolerach  requestAction  zeby zamulic aplikacje.

Ostatnio edytowany przez robal77 (2009-03-24 17:06:22)