A legfontosabb, leghatékonyabb dolgokhoz szükséges egyfajta hozzáférés ellenőrzés. Az ACL-ek (Access Control Lists - Hozzáférést Vezérlő Listák) segítségével az alkalmazásunkhoz való hozzáférést apró lépésekben, mégis könnyen kezelhetően és módosíthatóan engedélyezhetjük vagy tilthatjuk. Az ACL-ek két dolgot kezelnek: olyan dolgokat, amik akarnak valamit, és olyan dolgokat amiket mi szeretnénk elérni. Az ACL szaknyelvben a dolgokat (többnyire felhasználók), amik/akik használni szeretnének valamit, ARO-nak (Access Request Object - Hozzáférést Kérő Objektum) hívjuk. A rendszer azon dolgait, amiket el szeretnénk érni (leginkább különféle események illetve adatok), ACO-nak (Access Control Object - Hozzáférést Kontrolláló Objektum) hívjuk.
Azért hívjuk ezeket "objektumnak", mert néha a kérést adó objektum nem egy személy; néha bizonyos Cake vezérlők hozzáférését a rendszer egyéb részeihez is korlátozni kell. Az ACO-k lehetnek egy vezérlő eseményei, egy webszolgáltatás, vagy akár nagymamád blogjának egy bejegyzése - egyszóval bármi, amit felügyelni akarsz.
Hogy az összes rövidítést egyszerre használjuk: az ACL az, amit arra használunk, hogy eldöntsük, mikor tud hozzáférni egy ARO egy ACO-hoz.
Na most, hogy segítsünk a megértésben, vegyünk egy példát a gyakorlatból. Képzelj el egy pillanatra egy számítógépes rendszert, amit kalandorok egy csoportja használ. A csoport vezetője gyorsan akar előrenyomulni a küldetéssel, miközben egy egészséges mértékű magánszférát és biztonságot is fenn akar tartani a többi kalandor számára. Az ARO-k tehát:
Gandalf Aragorn Bilbo Frodo Gollum Legolas Gimli Pippin Merry
A fentiek olyan elemek, amik ACO-kat fognak kérni a rendszertől. Itt fontos megjegyezni, hogy az ACL nem a felhasználók azonosítására szolgál. Erre a célra már lennie kell egy módszernek, ahogy a felhasználói információkat tárolod, és ahogy ellenőrzöd egy felhasználó személyazonosságát. Csak onnantól tudod az ACL nagyszerű képességeit használni, amikor mindez már megvan. De rendben, most térjünk vissza a kalandunkhoz.
A következő dolog, amit Gandalfnak meg kell tennie, egy lista készítése (ACO-k), amiket a rendszer kezelni fog. Ez a lista kinézhet pl. így:
Fegyverek A Gyűrű Füstölt hús Diplomácia Sör
Hagyományosan a rendszerek jogosultságai egyfajta mátrixban voltak leírva, ami a felhasználók és az objektumok halmazából állt. Ha mindezt egy táblában tárolnánk, hasonlóképpen nézne ki mint ez (X - hozzáférés megtagadva, O - engedélyezve):
Fegyverek A Gyűrű Füstölt hús Diplomácia Sör Gandalf X X O O O Aragorn O X O O O Bilbo X X X X O Frodo X O X X O Gollum X X O X X Legolas O X O O O Gimli O X O X X Pippin X X X O O Merry X X X X O
Első pillanatra ez a rendszer egész jól működhet. A biztonságos hozzáférést be tudjuk tartatni (csak Frodo érheti ek a Gyűrűt), és védelmet nyújt a balesetek ellen (a hobbitok nem nyúlhatnak a füstölt húshoz). Eléggé részletesnek és könnyen megérthetőnek tűnik, nem?
Nos, egy ilyen kis rendszerhez a mátrix alapú beállítás elég lehet. De egy növekvő rendszerben, vagy egy rengeteg erőforrással (ACO-k) és felhasználóval (ARO-k) rendelkezőben, egy tábla mint ez, egész gyorsan kezelhetetlenné válik. Képzeld csak el, hogy több száz háborús táborhelyhez próbálod a hozzáférést szabályozni, és mindezt egyesével teszed. A mátrixok egy másik hátulütője, hogy nem igazán lehet logikailag a felhasználókat csoportokba rendezni, illetve hierarchikus jogosultság változtatásokat végrehajtani ezeken a csoportokon. Például tök jó lenne a hobbitoknak automatikusan elérést adni a sörhöz és a húshoz, amint a csatának vége. Egyesével minden felhasználónál beállítani mindezt eléggé fárasztó és könnyen lehet hibázni - míg ezzel szemben egy hierarchikus változtatást az összes 'hobbit'-ra végrehajtani pillanatok műve.
Az ACL többnyire fa-struktúraként van megvalósítva. általában van egy ARO fa, és egy ACO fa. A különféle objektumainkat fa-struktúrába rendezve a jogosultságokat még mindig könnyedén, ugyanakkor a teljes rendszeren egy átfogó képet kapva tudjuk megoldani. Mivel Gandalf egy bölcs vezető, ezért ACL-ek segítségével rendezi a különféle objektumait az alábbi módon:
A Gyűrű Szövetsége: Harcosok Aragorn Legolas Gimli Varázslók Gandalf Hobbitok Frodo Bilbo Merry Pippin Vendégek Gollum
Kis csapatunkat ily módon struktúrálva most már megadhatjuk a hozzáféréseket a fához (annak ágaihoz), és ezek érvényesek lesznek a fa levelein is. Alapállapotban mindenhez megtagadjuk a hozzáférést. Ahogy haladsz a fán lefelé, felkapkodod az engedélyeket és alkalmazod őket. Az utolsó engedély (ami az ACO-ra vonatkozik) az, amit megtartasz végül. Egyszóval a következő jogosultságokat aggathatja Gandalf az ARO fánkra:
A Gyűrű Szövetsége: (hozzáférés mindenkinek mindenhez megtagadva) Harcosok (hozzáférés megengedve a Fegyverekhez, Sörhöz, Elf napiadaghoz, Füstölt húshoz ) Aragorn Legolas Gimli Varázslók (hozzáférés megengedve a Füstölt húshoz, Diplomáciához, és a Sörhöz) Gandalf Hobbitok (hozzáférés megengedve a Sörhöz) Frodo Bilbo Merry Pippin Vendégek (hozzáférés megengedve a Füstölt húshoz) Gollum
Ha az ACL segítségével meg szeretnénk nézni, hogy Pippin hozzáférhet-e a sörhöz, először is megnéznénk a fában a hozzá vezető utat, ami: Szövetség -> Hobbitok -> Pippin. Ezek után megnézzük a különféle jogosultságokat, amik ezekben a pontokban találhatóak, és a Pippinhez és a sörhöz leginkább meghatározott használjuk. Tehát:
A fa azonban lehetőseget ad nekünk arra is, hogy sokkal finomabb szinten állítsuk a jogosultságokat - miközben végig megtartjuk a lehetőséget, hogy masszív változtatásokat hajtsunk végre. Például:
A Gyűrű Szövetsége: (hozzáférés mindenkinek mindenhez megtagadva) Harcosok (hozzáférés megengedve a Fegyverekhez, Sörhöz, Elf napiadaghoz, Füstölt húshoz ) Aragorn (hozzáférés megengedve a Diplomáciához) Legolas Gimli Varázslók (hozzáférés megengedve a Füstölt húshoz, Diplomáciához, és a Sörhöz) Gandalf Hobbitok (hozzáférés megengedve a Sörhöz) Frodo (hozzáférés megengedve a Gyűrűhöz) Bilbo Merry (hozzáférés megtagadva a Sörhöz) Pippin (hozzáférés megengedve a Diplomáciához) Vendégek (hozzáférés megengedve a Füstölt húshoz) Gollum
Láthatod, hogy az Aragorn ARO megtartja az összes jogosultságát ami a többi Harcosnak is van, de ezen kívül még külön egyedi módosításokat hajthatsz végre, ha szükséges. A jogosultságok alapállapotban meg vannak tagadva, és csak a fán lefelé haladva változhatnak. Ahhoz, hogy lássuk, Merry elérheti-e a Sört, megnézzük, milyen úton lehet elérni őt: Szövetség -> Hobbitok -> Merry, és lefelé haladva minden sörrel kapcsolatos infót megtartunk útközben:
A Cake első ACL implementációja ini fájl alapú volt. Bár hasznos és megbízható, ennek ellenére azt javasoljuk, inkább az adatbázis alapú ACL-t használd. Leginkább azért, mert a program futása közben tudsz újabb ACO-kat és ARO-kat hozzáadni. Az ini fájlos megoldást egyszerű alkalmazásokhoz szántuk - illetve azoknak az emberkéknek, akik valami miatt nem használnak adatbázist. Az ARO/ACO jogosultságok az /app/config/acl.ini.php -ban vannak megadva. A definiálás módja is ennek a fájlnak az elején található:
; acl.ini.php - Cake ACL Configuration ; --------------------------------------------------------------------- ; Ebben a file-ban definiáld a jogosultságokat. ; aco = access control object (valami az alkalmazásban) ; aro = access request object (bármi, ami hozzáférést kér) ; ; Felhasználó rekordok hozzáadása: ; ; [uid] ; groups = group1, group2, group3 ; allow = aco1, aco2, aco3 ; deny = aco4, aco5, aco6 ; ; Csoport (group) rekordok hasonlóképp: ; ; [gid] ; allow = aco1, aco2, aco3 ; deny = aco4, aco5, aco6 ; ; Az allow, deny és a groups részek mind opcionálisak. ; MEGJEGYZéS: A csoportok nevei sosem egyezhetnek meg egy felhasználó nevével sem!
Az ini fájl segítségével megadhatsz felhasználókat (ARO-k), csoportokat, amikhez tartoznak, illetve a saját egyedi jogosultságaikat. Szintén megadhatsz csoportokat is a saját külön jogosultságaikkal. Ha szeretnéd megtudni, hogyan használhatod a Cake ACL komponensét a jogosultságok ellenőrzésére - ini fájllal - nézd meg a 11.4-es részt.
Alapállapotban a jogosultsági rendszer adatbázis alapú. Ez a modul (nevezzük dbACL-nek) néhány központi modellből és egy parancssori szkriptből áll. A modelleket a Cake az ACL csomópontok adatbázisba mentésére és olvasására használja. A parancssori szkript segít az elindulásban, illetve használhatod az ACL fa manipulálására is. Először is meg kell nézned, hogy az /app/config/database.php fájl létezik, és jól be van állítva. Egy új Cake telepítésnél a legegyszerűbben egy böngészőben az install könyvtárat kinyitva láthatod ezt. A lap tetejénél - ha mindent jól csináltál - az alábbi üzeneteket kell látnod: "Your database configuration file is present." és "Cake is able to connect to the database.". Nézd meg a 4.1-es részt az adatbázis beállításával kapcsolatos további részletekért. Ezután az ACL parancssori szkriptet használva felkészíted az adatbázist a jogosultsági információk tárolására. Ezt a /cake/scripts/acl.php file segítségével teheted meg, az alábbi módon:
$ php acl.php initdb Initializing Database... Creating access control objects table (acos)... Creating access request objects table (acos)... Creating relationships table (aros_acos)... Done.
Itt az adatbázisban már látnod kell az új táblákat. Ha igazán kíváncsi vagy, hogy tárolja a fastruktúra adatait a Cake, olvass utána a "módosított fabejárás adatbázisban címszó" alatt az irodalomban. Alapjában a csomópontokat, és azok helyét a fában tároljuk. Az acos és aros táblák tárolják a hozzájuk tartozó csomópontokat, az aros_acos tábla pedig összekapcsolja az ARO-kat azokkal az ACO-kkal, amiket elérhetnek.
Most már létre tudsz hozni ARO és ACO fákat.
Kétféle módon lehet ACO/ARO-kra hivatkozni. Egyrészt lehet egy numerikus értékkel, ami általában a tábla elsődleges kulcsa (primary key), amihez tartoznak. A másik egy tetszőleges sztring alias, amit hozzá lehet rendelni ehhez a számhoz. Ezt a két hivatkozási módot egyszerre is lehet használni.
Új ARO-t az Aro Cake modell megfelelő metódusait hívva hozahtunk létre. Az Aro osztály create() metódusa három paramétert vár: $link_id, $parent_id, és $alias. Ez létrehoz egy új ACL objektumot a parent_id által megadott szülő alatt, vagy ő maga lesz a kiinduló csomópont, ha a parent_id értéke null. A link_id-val összekapcsolhatsz egy tetszőleges felhasználói objektumot az ACL struktúrával. Az alias-al pedig elérheted ezt egy sztringgel.
Mielőtt neki tudnánk állni ACO-k és ARO-k gyártásának, be kell tölteni ezeket az osztályokat. Legkönnyebben a vezérlőben behívva (a $components tömbben) a Cake ACL komponensét tudjuk mindezt megtenni.
var $components = array('Acl');
Most, hogy ezzel is megvagyunk, lássunk egy példát, hogy néz ez ki a gyakorlatban. Az alábbi kódot a vezérlő egy eseményébe helyezhetjük:
$aro = new Aro();
// Először is gyártsunk pár ARO-t
// Ezeknek most még nincs szülője.
$aro->create( 1, null, 'Bob Marley' );
$aro->create( 2, null, 'Jimi Hendrix');
$aro->create( 3, null, 'George Washington');
$aro->create( 4, null, 'Abraham Lincoln');
// Most már csoportokba rendezhetjük a felhasználókat
// figyeld meg, hogy a csoportok ID-je 0, így ezek
// direkt sosem hivatkozhatnak egy felhasználóra
$aro->create(0, null, 'Presidents');
$aro->create(0, null, 'Artists');
// Most kapcsoljuk össze az ARO-kat a megfelelő csoporttal
$aro->setParent('Presidents', 'George Washington');
$aro->setParent('Presidents', 'Abraham Lincoln');
$aro->setParent('Artists', 'Jimi Hendrix');
$aro->setParent('Artists', 'Bob Marley');
// Röviden így készítünk egy ARO-t:
$aro = new Aro();
$aro->create($user_id, $parent_id, $alias);
ARO-kat a parancssorból is lehet készíteni:
$acl.php create aro <link_id> <szülő_id> <alias>.
Az ACO-k hasonlóképp készülnek:
$aco = new Aco(); // Készítsünk néhány ACO-t $aco->create(1, null, 'Electric Guitar'); $aco->create(2, null, 'United States Army'); $aco->create(3, null, 'Fans'); // csoportokat is lehet készíteni, mint az ARO-knál // a setParent()-el, de most ezt kihagyjuk // Szóval: $aco = new Aco(); $aco->create($id, $parent, $alias);Az ehhez tartozó parancssor:
$acl.php create aco <link_id> <szülő_id> <alias>.Jogosultságok hozzárendelése
Miután megvannak az ACO és ARO-ink, végre beállíthatjuk a jogosultságokat a két csoport között. Ezt a Cake Acl komponensével tesszük. A példa:
// Először is a vezérlőben hozzá kell // férnünk a Cake ACL komponenséhez: class SomethingsController extends AppController { // Ezt lehet hogy inkább az AppController-be kellene rakni, // de itt is jól működik. var $components = array('Acl'); // Emlékezz: az ACL mindig mindent megtagad, // amiről nincs infója. Ha bármiféle ellenőrzés // lenne most, a hozzáférés meg lenne tagadva. // Engedjük most meg egy ARO-nak a hozzáférést egy ACO-hoz. function someAction() { //ENGEDéLYEZéS // így adunk egy ARO-nak teljes hozzáférést egy ACO-hoz: $this->Acl->allow('Jimi Hendrix', 'Electric Guitar'); $this->Acl->allow('Bob Marley', 'Electric Guitar'); // Ugyanezt megtehetjük csoportokkal is... $this->Acl->Allow('Presidents', 'United States Army'); // Az allow() függvénynek van egy harmadik, $esemeny paramétere. // Ennek segítségével részbeni hozzáférést is megadhatsz. // $esemeny értéke lehet: create, read, update, delete. // Ha $esemeny nincs megadva, teljes hozzáférése lesz. $this->Acl->allow('George Washington', 'Electric Guitar', 'read'); $this->Acl->allow('Abraham Lincoln', 'Electric Guitar', 'read'); //TILTáS // Hasonló módon... : // Miután lejárt a mandátuma... $this->Acl->deny('Abraham Lincoln', 'United States Army'); } }Ennek a vezérlőnek nem sok haszna van, talán csak annyi, hogy megértsd, hogyan működik a folyamat. Az Acl-t a saját felhasználó-kezelő komponenseddel együtt kezelve lehet a legjobb eredményeket elérni. Mihelyst egy felhasználó létrejött, az ARO-ját a fa megfelelő ágára lehet helyezni, a további jogosultságokat pedig (ha szükséges) hozzárendelni a megfelelő ACO-khoz.
A jogosultságokat a Cake parancssori szkriptjeivel is be lehet állítani. A szintaktika hasonló a modell függvényeihez, és meg lehet nézni a $php acl.php help -et futtatva.
4. rész
Jogosultságok ellenőrzése: Az ACL komponens
A jogosultságok ellenőrzése a lekgönnyebb része a Cake féle ACL-nek. Az Acl komponensnek csak egyetlen metódusát kell meghívni, a check()-et. Jó módja az ACL programunkba való beépítésének, ha az AppController-ünkbe rakunk egy eseményt, ami végrehajtja az ellenőrzést. Ha iderakjuk, a programunk bármely részéből elérhetjük ezt a részt. Egy példa:
class AppController extends Controller { // Beszerezzük a komponensünket var $components = array('Acl'); function checkAccess($aco) { // Ellenőrizzük a hozzáférést $access = $this->Acl->check($this->Session->read('user_alias'), $aco, $action = "*"); // megtagadva if ($access === false) { echo "na húzzá!"; exit; } // engedélyezve else { echo "csá tesó!"; exit; } } }Az Acl komponenst az AppController-ben elérhetővé téve az Acl használható lesz alkalmazásunk bármelyik vezérlőjében. íme az alap forma:
$this->Acl->Check($aro, $aco, $action = '*');{} - 15 Access Control Lists
Understanding How ACL Works
Most important, powerful things require some sort of access control. Access control lists are a way to manage application permissions in a fine-grained, yet easily maintainable and manageable way. Access control lists, or ACL, handle two main things: things that want stuff, and things that are wanted. In ACL lingo, things (most often users) that want to use stuff are called access request objects, or AROs. Things in the system that are wanted (most often actions or data) are called access control objects, or ACOs. The entities are called 'objects' because sometimes the requesting object isn't a person - sometimes you might want to limit the access certain Cake controllers have to initiate logic in other parts of your application. ACOs could be anything you want to control, from a controller action, to a web service, to a line on your grandma's online diary.
To use all the acronyms at once: ACL is what is used to decide when an ARO can have access to an ACO.
Now, in order to help you understand this, let's use a practial example. Imagine, for a moment, a computer system used by a group of adventurers. The leader of the group wants to forge ahead on their quest while maintaining a healthy amount of privacy and security for the other members of the party. The AROs involved are as following:
- Gandalf
- Aragorn
- Bilbo
- Frodo
- Gollum
- Legolas
- Gimli
- Pippin
- Merry
These are the entities in the system that will be requesting things (the ACOs) from the system. It should be noted that ACL is *not* a system that is meant to authenticate users. You should already have a way to store user information and be able to verify that user's identity when they enter the system. Once you know who a user is, that's where ACL really shines. Okay - back to our adventure.
The next thing Gandalf needs to do is make an initial list of things, or ACOs, the system will handle. His list might look something like:
- Weapons
- The One Ring
- Salted Pork
- Diplomacy
- Ale
Traditionally, systems were managed using a sort of matrix, that showed a basic set of users and permissions relating to objects. If this information were stored in a table, it might look like the following, with X's indicating denied access, and O's indicating allowed access.
Weapons The One Ring Salted Pork Diplomacy Ale Gandalf No No Yes Yes Yes Aragorn Yes No Yes Yes Yes Bilbo No No No No Yes Frodo No Yes No No Yes Gollum No No Yes No No Legolas Yes No Yes Yes Yes Gimli Yes No Yes No No Pippin No No No Yes Yes Merry No No No No Yes At first glance, it seems that this sort of system could work rather well. Assignments can be made to protect security (only Frodo can access the ring) and protect against accidents (keeping the hobbits out of the salted pork). It seems fine grained enough, and easy enough to read, right?
For a small system like this, maybe a matrix setup would work. But for a growing system, or a system with a large amount of resources (ACOs) and users (AROs), a table can become unwieldy rather quickly. Imagine trying to control access to the hundreds of war encampments and trying to manage them by unit, for example. Another drawback to matrices is that you can't really logically group sections of users, or make cascading permissions changes to groups of users based on those logical groupings. For example, it would sure be nice to automatically allow the hobbits access to the ale and pork once the battle is over: Doing it on an indivudual user basis would be tedious and error prone, while making a cascading permissions change to all 'hobbits' would be easy.
ACL is most usually implemented in a tree structure. There is usually a tree of AROs and a tree of ACOs. By organizing your objects in trees, permissions can still be dealt out in a granular fashion, while still maintaining a good grip on the big picture. Being the wise leader he is, Gandalf elects to use ACL in his new system, and organizes his objects along the following lines:
Fellowship of the Ring:
- Warriors
- Aragorn
- Legolas
- Gimli
- Wizards
- Gandalf
- Hobbits
- Frodo
- Bilbo
- Merry
- Pippin
- Vistors
- Gollum
By structuring our party this way, we can define access controls to the tree, and apply those permissions to any children. The default permission is to deny access to everything. As you work your way down the tree, you pick up permissions and apply them. The last permission applied (that applies to the ACO you're wondering about) is the one you keep. So, using our ARO tree, Gandalf can hang on a few permissions:
Fellowship of the Ring: [Deny: ALL]
- Warriors [Allow: Weapons, Ale, Elven Rations, Salted Pork]
- Aragorn
- Legolas
- Gimli
- Wizards [Allow: Salted Pork, Diplomacy, Ale]
- Gandalf
- Hobbits [Allow: Ale]
- Frodo
- Bilbo
- Merry
- Pippin
- Vistors [Allow: Salted Pork]
- Gollum
If we wanted to use ACL to see if the Pippin was allowed to access the ale, we'd first get his path in the tree, which is Fellowship->Hobbits->Pippin. Then we see the different permissions that reside at each of those points, and use the most specific permission relating to Pippin and the Ale.
Fellowship = DENY Ale, so deny (because it is set to deny all ACOs)
Hobbits = ALLOW Ale, so allow
Pippin = ?; There really isn't any ale-specific information so we stick with ALLOW.
Final Result: allow the ale.
The tree also allows us to make finer adjustments for more granular control - while still keeping the ability to make sweeping changes to groups of AROs:
- Warriors [Allow: Weapons, Ale, Elven Rations, Salted Pork]
- Aragorn [Allow: Diplomacy]
- Legolas
- Gimli
- Wizards [Allow: Salted Pork, Diplomacy, Ale]
- Gandalf
- Hobbits [Allow: Ale]
- Frodo [Allow: Ring]
- Bilbo
- Merry [Deny: Ale]
- Pippin [Allow: Diplomacy]
- Vistors [Allow: Salted Pork]
- Gollum
You can see this because the Aragorn ARO maintains is permissions just like others in the Warriors ARO group, but you can still make fine-tuned adjustments and special cases when you see fit. Again, permissions default to DENY, and only change as the traversal down the tree forces an ALLOW. To see if Merry can access the Ale, we'd find his path in the tree: Fellowship->Hobbits->Merry and work our way down, keeping track of ale-related permissions:
Fellowship = DENY (because it is set to deny all), so deny the ale.
Hobbits = ALLOW: ale, so allow the ale
Merry = DENY ale, so deny the ale
Final Result: deny the ale.
Defining Permissions: Cake's INI-based ACL
Cake's first ACL implementation was based off of INI files stored in the Cake installation. While its useful and stable, we recommend that you use the database backed ACL solution, mostly because of its ability to create new ACOs and AROs on the fly. We meant it for usage in simple applications - and especially for those folks who might not be using a database for some reason.
By default, CakePHP's ACL is database-driven. To enable INI-based ACL, set ACL_CLASSNAME to INI_ACL, and ACL_FILENAME to ini_acl in core.php.
ARO/ACO permissions are specified in /app/config/acl.ini.php. Instructions on specifying access can be found at the beginning of acl.ini.php:
; acl.ini.php - Cake ACL Configuration ; --------------------------------------------------------------------- ; Use this file to specify user permissions. ; aco = access control object (something in your application) ; aro = access request object (something requesting access) ; ; User records are added as follows: ; ; [uid] ; groups = group1, group2, group3 ; allow = aco1, aco2, aco3 ; deny = aco4, aco5, aco6 ; ; Group records are added in a similar manner: ; ; [gid] ; allow = aco1, aco2, aco3 ; deny = aco4, aco5, aco6 ; ; The allow, deny, and groups sections are all optional. ; NOTE: groups names *cannot* ever be the same as usernames!Using the INI file, you can specify users (AROs), the group(s) they belong to, and their own personal permissions. You can also specify groups along with their permissions. To learn how to use Cake's ACL component to check permissions using this INI file, see section 11.4.
Defining Permissions: Cake's Database ACL
Getting Started
The default ACL permissions implementation is database stored. Database ACL, or dbACL consists of a set of core models, and a command-line script that comes with your Cake installation. The models are used by Cake to interact with your database in order to store and retrieve nodes the ACL trees. The command-line script is used to help you get started and be able to interact with your trees.
To get started, first you'll need to make sure your /app/config/database.php is present and correctly configured. For a new Cake installation, the easiest way to tell that this is so is to bring up the installation directory using a web browser. Near the top of the page, you should see the messages "Your database configuration file is present." and "Cake is able to connect to the database." if you've done it correctly. See section 4.1 for more information on database configuration.
Next, use the the ACL command-line script to initialize your database to store ACL information. The script found at /cake/scripts/acl.php will help you accomplish this. Initialize the your database for ACL by executing the following command (from your /cake/scripts/ directory):
Initializing your database using acl.php
$ php acl.php initdb Initializing Database... Creating access control objects table (acos)... Creating access request objects table (aros)... Creating relationships table (aros_acos)... Done.At this point, you should be able to check your project's database to see the new tables. If you're curious about how Cake stores tree information in these tables, read up on modified database tree traversal. Basically, it stores nodes, and their place in the tree. The acos and aros tables store the nodes for their respective trees, and the aros_acos table is used to link your AROs to the ACOs they can access.
Now, you should be able to start creating your ARO and ACO trees.
Creating Access Request Objects (AROs) and Access Control Objects (ACOs)
There are two ways of referring to AROs/ACOs. One is by giving them an numeric id, which is usually just the primary key of the table they belong to. The other way is by giving them a string alias. The two are not mutually exclusive.
The way to create a new ARO is by using the methods defined the the Aro Cake model. The create() method of the Aro class takes three parameters: $link_id, $parent_id, and $alias. This method creates a new ACL object under the parent specified by a parent_id - or as a root object if the $parent_id passed is null. The $link_id allows you to link a current user object to Cake's ACL structures. The alias parameter allows you address your object using a non-integer ID.
Before we can create our ACOs and AROs, we'll need to load up those classes. The easiest way to do this is to include Cake's ACL Component in your controller using the $components array:
var $components = array('Acl');Once we've got that done, let's see what some examples of creating these objects might look like. The following code could be placed in a controller action somewhere:
$aro = new Aro();First, set up a few AROs. These objects will have no parent initially.
$aro->create( 1, null, 'Bob Marley' );
$aro->create( 2, null, 'Jimi Hendrix');
$aro->create( 3, null, 'George Washington');
$aro->create( 4, null, 'Abraham Lincoln');Now, we can make groups to organize these users. Notice that the IDs for these objects are 0, because they will never tie to users in our system.
$aro->create(0, null, 'Presidents');
$aro->create(0, null, 'Artists');Now, hook AROs to their respective groups:
$aro->setParent('Presidents', 'George Washington');
$aro->setParent('Presidents', 'Abraham Lincoln');
$aro->setParent('Artists', 'Jimi Hendrix');
$aro->setParent('Artists', 'Bob Marley');In short, here is how to create an ARO:
$aro = new Aro(); $aro->create($user_id, $parent_id, $alias);You can also create AROs using the command line script using
$acl.php create aro <link_id> <parent_id> <alias>Creating an ACO is done in a similar manner:
$aco = new Aco(); //Create some access control objects: $aco->create(1, null, 'Electric Guitar'); $aco->create(2, null, 'United States Army'); $aco->create(3, null, 'Fans');We could create groups for these objects using setParent(), but we'll skip that
for this particular example. To create an ACO:$aco = new Aco(); $aco->create($id, $parent, $alias);The corresponding command line script command would be:
$acl.php create aco <link_id> <parent_id> <alias>Assigning Permissions
After creating our ACOs and AROs, we can finally assign permission between the two groups. This is done using Cake's core Acl component. Let's continue on with our example:
// First, in a controller, we'll need access // to Cake's ACL component: class SomethingsController extends AppController { // You might want to place this in the AppController // instead, but here works great too. var $components = array('Acl'); // Remember: ACL will always deny something // it doesn't have information on. If any // checks were made on anything, it would // be denied. Let's allow an ARO access to an ACO. function someAction() { //ALLOW // Here is how you grant an ARO full access to an ACO $this->Acl->allow('Jimi Hendrix', 'Electric Guitar'); $this->Acl->allow('Bob Marley', 'Electric Guitar'); // We can also assign permissions to groups, remember? $this->Acl->Allow('Presidents', 'United States Army'); // The allow() method has a third parameter, $action. // You can specify partial access using this parameter. // $action can be set to create, read, update or delete. // If no action is specified, full access is assumed. // Look, don't touch, gentlemen: $this->Acl->allow('George Washington', 'Electric Guitar', 'read'); $this->Acl->allow('Abraham Lincoln', 'Electric Guitar', 'read'); //DENY //Denies work in the same manner: //When his term is up... $this->Acl->deny('Abraham Lincoln', 'United States Army'); } }This particular controller isn't especially useful, but it is mostly meant to show you how the process works. Using the Acl component in connection with your user management controller would be the best usage. Once a user has been created on the system, her ARO could be created and placed at the right point of the tree, and permissions could be assigned to specific ACO or ACO groups based on her identity.
Permissions can also be assigned using the command line script packaged with Cake. The syntax is similar to the model functions, and can be viewed by executing $php acl.php help.
Checking Permissions: The ACL Component
Checking permissions is the easiest part of using Cake's ACL: it consists of using a single method in the Acl component: check(). A good way to implement ACL in your application might be to place an action in your AppController that performs ACL checks. Once placed there, you can access the Acl component and perform permissions checks application-wide. Here's an example implementation:
class AppController extends Controller { // Get our component var $components = array('Acl'); function checkAccess($aco) { // Check access using the component: $access = $this->Acl->check($this->Session->read('user_alias'), $aco, $action = "*"); //access denied if ($access === false) { echo "access denied"; exit; } //access allowed else { echo "access allowed"; exit; } } }Basically, by making the Acl component available in the AppController, it will be visible for use in any controller in your application. Here's the basic format:
$this->Acl->Check($aro, $aco, $action = '*');Differences
| Lines: 1-392 | Lines: 1-431 |