Az első részben megnéztük a két hasonló módszer, a vezérlő engedélyekre és a modell engedélyekre alapuló hozzáférés kezelést. A következőkben megnézzük a jogosultságok kezelésére is használható ACL-ek kétféle hasznosítási elvét. Aki eddig esetleg nem tette volna, az olvassa el először a CakePHP szakácskönyv ACL-lel foglalkozó részét.
Harmadik módszer: Hozzáférések a tevékenység engedélyek alapján
Ez az egyetlen módszer ami megköveteli az ACL használatát. Ez a módszer abból indul ki, hogy a userek vagy a userek bizonyos csoportja használhat egy tevékenységet vagy nem. Tehát ebben az esetben nincs lehetőségünk olyan jogosultságok beállítására amelyek az url paramétereitől, vagy valamilyen adatrekordtól függenek.
Használatához az app_controller.php fájlunk így fog kinézni:
<?php class AppController extends Controller { var $components = array('Acl', 'Auth'); //az ACL és Auth komponensek betöltése var $helpers = array('Html', 'Form'); function beforeFilter(){ $this->Auth->authorize = 'actions'; //itt gondoskodunk az authorize beállításáról $this->Auth->allow('display'); //pages controller-hez nem kell hitelesítettnek lennie } } ?>
Ennél a módszernél sem a vezérlőkben sem a modellekben nem használunk isAuthorized függvényt. A komponens a meghívott tevékenységet fogja keresni a bejelentkezett felhasználó jogosultságai között. Mivel az ACL is fehér listás, azaz mindenhez tiltja a hozzáférést amire kifejezetten nincs engedély először létre kell hoznunk a megfelelő ARO-kat és ACO-kat és ezek jogosultságait.
Az ACL console használatával valami ilyesmit kell megtennünk minden tevékenységre és felhasználóra:
./cake acl create aro / Adminok ./cake acl create aro / Szerkesztok ./cake acl create aro Adminok User.1 ./cake acl create aro Szerkesztok User.2 ./cake acl create aco / Users ./cake acl create aco Users editmydata ./cake acl create aco Users viewmydata ./cake acl create aco Users listall ./cake acl grant Adminok Users '*' ./cake acl grant User.1 Users '*' ./cake acl deny User.1 Users/listall
Létrehoztuk a felhasználó csoportokat képviselő ARO-kat, elhelyeztük az egyes felhasználókat a csoportokban. Ezután létrehoztuk a vezérlőket és a tevékenységeiket képviselő ACO ágakat, majd létrehoztuk a közöttük fennálló hozzáférési szabályokat. Talán a két utolsó sor szoul magyarázatra. Az utolsó előtti sorban azt mondjuk, hogy a User.1 hozzáfér minden egyes UsersController beli tevékenységhez, majd az utolsó sorban tiltjuk a hozzáférését a listall metódushoz. Így a User.1 felhasználó a UsersController listall metódusát kivéve mindenhez hozzá fog férni a vezérlőben.
Ellenőrzési metódusokat nem kell létrehoznunk, mivel az ellenőrzés a fenti ACL alapján fog megtörténni. Mivel ennek a módszernek az elgondolása jelentősen más mint az előzőeké valószínű, hogy a vezérlőink metódusai is jelentősen el fognak térni. Azaz például a felhasználó adatok módosítására nem a UsersController::edit() metódusát fogjuk használni, ami egy paraméterben kapja meg a szerkeszteni kívánt user id-jét, hanem ehelyett egy UsersController:editmydata() metódust használunk ami nem vár paramétert és maga gondoskodik arról, hogy a felhasználó csak a saját adatihoz férjen hozzá.
Ez a módszer teljesen automatizálttá teszi a jogosultságok kezelését, viszont igényli, hogy a jogosultságok tevékenységekre kioszthatók legyenek. A webalkalmazás tervezésénél érdemes megfontolni, hogy ez a tulajdonsága előnyünkre vagy hátrányunkra válik.
Az ACL-ek és a tevékenység engedélyek használatával egy a növekedést jól kezelő rugalmas rendszert kapunk. Arra is lehetőségünk van, hogy a felhasználók létrehozásánál automatizáljuk az ARO fában való megjelenítésüket a user model $actsAs tulajdonságának beállításával, de ez a terület már tényleg túlmutat a jelen cikk mondandóján. A szakácskönyvben olvashatsz bővebben róla.
Új tevékenységek beépülése is automatizálható az ACO fába, de ez már egy bonyolultabb kérdés. Mindenesetre a fehér listát megközelítés miatt túl nagy hibát nem követhetünk el, mivel ha elfelejtjük az új tevékenységet felvenni az ACO-k közé, akkor úgy is tiltva marad a hozzáférés mindenki számára.
Negyedik módszer: Hozzáférések vezérlő engedélyek és ACL alapján
A negyedik itt bemutatott módszer az első módszer használatát bővíti ki az ACL-lel. Amennyiben az első módszer megközelítése megfelelő de bizonyos esetekben szűkösnek bizonyul, akkor könnyedén bővíthetjük az ACL segítségével.
Ehhez az app_controller.php a következőket fogja tartalmazni:
<?php class AppController extends Controller { var $components = array('Acl', 'Auth'); function beforeFilter(){ $this->Auth->authorize = 'controller'; $this->Auth->allow('display'); //pages controller-hez nem kell hitelesítettnek lennie $this->Auth->authError = "Bocsi, de ehhez jogilag kevés vagy."; } function isAuthorized(){ return false; } } ?>
Eddig semmi különös, betöltjük az Acl és Auth komponenseket, valamint létrehozzuk az isAuthorized metódust ami alapértelmezés szerint mindenkinek minden hozzáférést tilt.
Létre kell hoznunk az ACL ágainkat is.
./cake schema run create DbAcl ./cake acl create aro / Adminok ./cake acl create aro / Szerkesztok ./cake acl create aro Adminok User.1 ./cake acl create aro Szerkesztok User.2 ./cake acl create aco / Szerkesztes ./cake acl grant User.1 Szerkesztes '*'
Tegyük fel, hogy az alkalmazásban jelenleg egy postunk van amit User.1 írt és egy másik amit User.3. Azt szeretnék, ha a következő jogosultságok érvényesülnének:
- mindenki mindent megcsinálhat a saját cikkével
- a szerkesztő nem hozhat létre más nevében és nem törölheti más cikkét
- az admin bárki nevében hozhat létre cikket
Ebben az esetben a posts_controller.php fájlunk valahogy így fog kinézni:
<?php class PostsController extends AppController { var $name = 'Posts'; var $helpers = array('Html', 'Form'); var $opciok = null; function beforeFilter(){ parent::beforeFilter(); } function isAuthorized(){ //na kérem szépen a jogokat ACL-ből jól leellenőrizzük if($this->action == 'index'){ //akinek az ACL szerint van read joga a szerkesztes-re az láthat minden cikket if($this->Acl->check(array('model' => 'User', 'foreign_key' => $this->Auth->user('id')), 'Szerkesztes', 'read')) return true; //akinek nincs read joga az csak a saját cikkeit láthatja $this->opciok = array('Post.user_id' => $this->Auth->User('id')); return true; } if($this->action == 'add'){ //akinek az ACL szerint van create joga a szerkesztes-re az létrehozhat cikket bárki nevében if($this->Acl->check(array('model' => 'User', 'foreign_key' => $this->Auth->user('id')), 'Szerkesztes', 'create')) return true; //akinek nincs create joga az csak a saját nevében hozhat létre cikket $this->opciok = array('User.id' => $this->Auth->User('id')); return true; } return false; } function index() { $this->Post->recursive = 0; $this->set('posts', $this->paginate('Post', $this->opciok)); } //sok más metódus }
Azt hiszem a kód itt is elég egyértelmű és jól bemutatja, hogy hogyan kombináljuk a két módszert.
Nem létező ACL ágak ellenőrzése
Meg kell még jegyezni egy dolgot ami egyesek szerint egy bug, szerintem azonban így helyes. Ha egy nem létező ágra hívjuk meg a $this->Acl->check() metódust akkor az rendben lefut (warning-gal) és false-ot ad vissza. Azaz ha a User ág teljes joggal rendelkezik a valamiACO felett, és az ágban van egy User.1 és egy User.2 akkor a $this->Acl->check(‘User.3’, ‘valamiACO’, ‘read’); false-ot fog visszaadni, azaz tiltja a hozzáférést. Nem beszélhetünk öröklésről, mivel az ág nem létezik, nincs kitől örökölnie.
A $this->Acl->allow() metódus csak létező ágakra hívható meg, nem létező esetében nem fog működni.
A CRUD és object módszerek
A CRUD és object módszerről nem igazán találtam leírást és a kód turkálása után sem tudtam olyan helyzetet elképzelni amikor jól jöttek volna. Ha valakinek van velük tapasztalata akkor kérem ossza meg velünk!
Amint látható maga a téma meglehetősen vaskos, hiszen a fentiekben a különböző módszerekkel csak az egyes megoldások felszínét érintettük.
Keresek embereket, CakePHP honlapfejlesztésre. Aki ért hozzá, írjon. Mail: [email protected]
Köszi,
Tiadar
Szia!
Nem tudom figyeled-e még ezeket a hozzászólásokat, de itt teszem fel a kérdésem, és nem a CakePHP fórumon, mert ide kapcsolódik.
Akár melyik autentikációt használod, engedélyezed a pages controllert. Miért? A Pages_controller mit csinál?
Na most a routs-ba én beállítottam, hogy a kezdőoldal a products controller index metódusa legyen, akkor gondolom nincs értelme a display engedélyezésének.
@Pepe a pages controller jeleníti meg a pageket. Ide szoktam pakolni olyan page-eket amik leírják, hogy hogyan lehet regisztrálni, miről szól a szolgáltatás stb. Akkor jó így ha reg nélkül nem akarsz semmiféle kontrollert kiadni a usernek, de azért a login pagen kívűl szeretnél elérhetővé tenni statikus tartalmakat.