Felhasználói jogosultságok kezelése – CakePHP 2. rész

cakephpAz 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.

3 thoughts on “Felhasználói jogosultságok kezelése – CakePHP 2. rész

  1. 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.

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöljük.