# Introductie

Zend_Acl levert een lichte en flexibele toegangscontrolelijst (ACL) functionaliteit en rechten beheer. In het algemeen, een applicatie mag deze functionaliteit benutten om de toegang tot bepaalde beschermde objecten door andere vragende objecten te controleren.

Binnen deze documentatie spreken we af,

- Een Bron is een object waarvan de toegang wordt gecontroleerd.

- Een Rol is een object dat toegang vraagt tot een bron.

Simpel gezegd, Rollen vragen toegang tot bronnen. Een voorbeeld, als een persoon toegang vraagt tot een auto, dan is de vragende persoon een rol en de auto is de bron, want de toegang tot de auto wordt gecontroleerd.

Door de specificatie en het gebruiken van een toegangscontrolelijst (ACL), kan een applicatie controleren of vragende objecten (Rollen) zijn toegestaan om beschermde objecten (Bronnen) te gebruiken.

## Over Bronnen

In Zend_Acl is het maken van een bron heel simpel. Zend_Acl heeft een `Zend_Acl_Resource_Interface` om het ontwikkelaars makkelijk te maken bij het maken van Bronnen. Een klasse hoeft deze interface alleen maar te implementeren, en bestaat uit een enkele methode, `getResourceId()`, om Zend_Acl het object als een Bron te laten beschouwen. Verder wordt `Zend_Acl_Resource` gebruikt binnen Zend_Acl als een standaard Bron implementatie voor ontwikkelaars die uitgebreid kan worden waar wenselijk.

Zend_Acl levert een boom structuur waaraan meerdere Bronnen ( of "gebieden onder toegangscontrole" ) aan toegevoegd kunnen worden. Omdat Bronnen opgeslagen worden in zo'n boom structuur, kunnen ze algemeen ( tot aan de top van de boom ) tot specifiek ( tot de blaadjes van de boom ) geregeld worden. Vragen aan een specifieke Bron zullen automatisch de Bronnen hiërarchie doorzoeken naar regels verbonden met ouderlijke Bronnen, wat een simpele overerving van regels mogelijk maakt. Als voorbeeld, als een standaard regel moet worden toegepast op ieder gebouw binnen een stad, dan verbind je die regel met de stad, in plaats van aan ieder gebouw. Sommige gebouwen hebben wellicht uitzonderingen op die regel en dit is vrij makkelijk te bereiken binnen Zend_Acl door die uitzonderingsregels te verbinden met ieder gebouw die een uitzondering heeft. Een Bron mag maar van een ouder Bron erven, maar deze ouder Bron kan zijn eigen ouder Bron hebben, etc etc.

Zend_Acl ondersteunt ook privileges op Bronnen (zoals, "maak", "lees", "update", "verwijder"), en de ontwikkelaar kan regels toekennen die effect hebben op alle privileges of specifieke privileges op een Bron.

## Over Rollen

Net als bij Bronnen, is het aanmaken van een Rol ook heel simpel. Zend_Acl levert `Zend_Acl_Role_Interface` om het ontwikkelaars makkelijk te maken bij het maken van een Rol. Een klasse hoeft deze interface alleen maar te implementeren, en bestaat uit een enkele methode, `getRoleId()`, om Zend_Acl het object als een Rol te laten beschouwen. Verder wordt `Zend_Acl_Role` gebruikt binnen Zend_Acl als een standaard Rol implementatie voor ontwikkelaars die uitgebreid kan worden waar wenselijk.

In Zend_Acl, mag een Rol erven van één of meer Rollen. Dit is om overerving van regels tussen Rollen mogelijk te maken. Als voorbeeld, een gebruiker Rol, zoals "sally", kan behoren tot één of meer ouder Rollen, zoals "redacteur" en "administrator". De ontwikkelaar kan apart regels toekennen aan "redacteur" en "administrator" en "sally" erft deze regels van beide, zonder dat deze regels direct aan "sally" zijn toegekend.

Hoewel de mogelijkheid om te erven van meerdere Rollen heel makkelijk is, brengt meedere overervingen een zekere mate van complexiteit met zich mee. Het volgende voorbeeld illustreert een tegenstrijdige bepaling en hoe Zend_Acl dit oplost.

### Meerdere overervingen tussen rollen

De volgende code defineerd 3 basis Rollen - "`gast`", "`lid`", en "`admin`" - waarvan andere Rollen kunnen erven. Vervolgens, wordt er een Rol, met de identiteit "`eenGebruiker`" aangemaakt die van alle drie de Rollen erft. De volgorde waarin deze rollen staan in de `$ouders` array is van belang. Als het nodig is, zoekt Zend_Acl niet alleen naar toegangsregels voor de geraadpleegde Rol ( in dit voorbeeld "`eenGebruiker`"), maar ook in de Rollen waar de geraadpleegde Rol van erft (in dit voorbeeld "`gast`", "`lid`", en "`admin`"):

    <?php
    require_once 'Zend/Acl.php';
    $acl = new Zend_Acl();

    require_once 'Zend/Acl/Role.php';
    $acl->addRole(new Zend_Acl_Role('gast'))
        ->addRole(new Zend_Acl_Role('lid'))
        ->addRole(new Zend_Acl_Role('admin'));

    $ouders = array('gast', 'lid', 'admin');
    $acl->addRole(new Zend_Acl_Role('eenGebruiker'), $ouders);

    require_once 'Zend/Acl/Resource.php';
    $acl->add(new Zend_Acl_Resource('eenBron'));

    $acl->deny('gast', 'eenBron');
    $acl->allow('lid', 'eenBron');

    echo $acl->isAllowed('eenGebruiker', 'eenBron') ? 'toegestaan' : 'weigeren';

Omdat er geen regel is gespecificeerd voor de "`eenGebruiker`" Rol en "`eenBron`", gaat Zend_Acl opzoek naar regels die mogelijk gedefineerd zijn voor Rollen waar "`eenGebruiker`" van erft. Als eerste wordt de "`admin`" Rol geraadpleegd, hiervoor is geen toegang regel gedefineerd. Daarna wordt de "`lid`" Rol geraadpleegd, en Zend_Acl vindt hier een regel dat "`lid`" toegestaan is om "`eenBron`" te gebruiken.

Als Zend_Acl door zou gaan met raadplegen van regels gedefineerd voor andere ouder Rollen, dan zou hij vinden dat "`gast`" geen toegang heeft om "`eenBron`" te gebruiken. Dit feit introduceert een tegenstrijdigheid want nu is "`eenGebruiker`" zowel toegestaan als geweigerd om "`eenBron`" te gebruiken, veroorzaakt door het erven van conflicterende regels van verschillende ouder Rollen.

Zend_Acl lost deze tegenstrijdigheid op door de raadpleging te beëindigen zodra de eerste regel gevonden wordt die direct toepasbaar is op de vraag. In dit geval, omdat de "`lid`" Rol eerder geraadpleegd wordt dan "`gast`", zal de voorbeeld code "toegestaan" weergeven.

Wanneer je meerdere ouders specificeerd voor een Rol, hou dan in gedachten dat de laatste ouder in de lijst als eerste doorzocht wordt op regels die toepasbaar zijn op de autorisatie vraag.

## Maken van de toegangscontrolelijst (ACL)

Een ACL kan iedere groep van fysieke en virtuele objecten bevatten die je wenst. Als demonstratie creëren we een basis Content Management Systeem ACL die verschillende niveaus van groepen bevat. Voor het maken van een ACL object, moeten we de ACL instantiëren zonder parameters:

    <?php
    require_once 'Zend/Acl.php';

    $acl = new Zend_Acl();

Totdat een ontwikkelaar een toestaan regel specificeerd, zal Zend_Acl toegang tot iedere privilege van iedere Bron verbieden voor elke Rol.

## Registeren van Rollen

Content Management Systemen zullen bijna altijd een hiërarchie van rechten nodig hebben om de rechten van zijn gebruikers te bepalen. Er is bijvoorbeeld een 'gast' groep om gelimiteerde toegang voor demonstraties toe te staan, een 'medewerker' groep voor het meerendeel van de CMS gebruikers die de dagelijkse acties uitvoeren, een 'redacteur' groep voor diegene die verantwoordelijke zijn voor herzien, acrhieveren en verwijderen van content en een 'administrator' groep die alles van de andere groepen mag en onderhoud mag plegen aan gevoelige informatie, gebruikersbeheer, configuraties aanpassen en gegevens backuppen/ exporteren. Deze rechten worden verzameld in een Rol lijst, waarin elke groep privileges mag erven van 'ouder' groepen en enkele privileges voor hun unieke groep kunnen hebben. De rechten kunnen als volgt worden weergegeven:

### Toegang controle voor een voorbeeld CMS

Naam | Unieke rechten | Erft rechten van
--- | --- | ---
Gast | Bekijk | N/A
Medewerker | Wijzig, Verzenden, Herzien | Gast
Redacteur | Publiceren, Archiveren, Verwijderen | Medewerker
Administrator | Heeft alle rechten | N/A

Als voorbeeld wordt `Zend_Acl_Role` gebruikt, maar ieder object dat `Zend_Acl_Role_Interface` implementeert kan gebruikt worden. De groepen kunnen toegevoegd worden aan de Rol lijst op de volgende manier:

    <?php
    require_once 'Zend/Acl.php';

    $acl = new Zend_Acl();

    // Voeg groepen toe aan de Rol lijst van Zend_Acl_Role
    require_once 'Zend/Acl/Role.php';

    // Gast erft geen oudelijke Rollen
    $rolGast = new Zend_Acl_Role('gast');
    $acl->addRole($rolGast);

    // Medewerker erft van gast
    $acl->addRole(new Zend_Acl_Role('medewerker'), $rolGast);

    /* Bovenstaande kan ook geschreven worden als:
    $acl->addRole(new Zend_Acl_Role('medewerker'), 'gast');
    */

    // Redacteur erft van medewerker
    $acl->addRole(new Zend_Acl_Role('redacteur'), 'medewerker');

    // Administrator erft geen ouder Rollen
    $acl->addRole(new Zend_Acl_Role('administrator'));

## Defineren van de toegangscontrole

Nu de ACL de relevante Rollen bevat, kunnen de regels worden opgesteld die defineren hoe Bronnen kunnen worden gebruikt door Rollen. Het is je misschien opgevallen dat we geen Bronnen hebben gespecificeerd in dit voorbeeld, wat erop neer komt dat de regels gelden voor alle Bronnen. Zend_Acl levert een inplementatie waarbij regels enkel te worden toegekend van algemeen tot specifiek, dit verkleint het aantal regels wat nodig is, want Bronnen en Rollen erven regels die zijn gedefineerd voor hun ouders.

In het algemeen, staat Zend_Acl een regel toe als een meer specifiekere regel niet bestaat.

We kunnen dus een redelijke complexe groep van regels defineren met een kleine hoeveelheid code. Om de basisregels toe te passen zoals hierboven staan beschreven:

    <?php
    require_once 'Zend/Acl.php';

    $acl = new Zend_Acl();

    require_once 'Zend/Acl/Role.php';

    $rolGast = new Zend_Acl_Role('gast');
    $acl->addRole($rolGast);
    $acl->addRole(new Zend_Acl_Role('medewerker'), $rolGast);
    $acl->addRole(new Zend_Acl_Role('redacteur'), 'medewerker');
    $acl->addRole(new Zend_Acl_Role('administrator'));

    // Gast mag alleen content bekijken
    $acl->allow($rolGast, null, 'bekijk');

    /* Bovenstaande kan ook geschreven worden als:
    $acl->allow('gast', null, 'bekijk');
    */

    // Medewerker erft het bekijk privilege van gast, maar heeft extra privileges
    $acl->allow('medewerker', null, array('wijzig', 'verzend', 'herzien'));

    // Redacteur erft bekijk, wijzig, verzend en herzien privileges van medewerker
    // maar heeft extra prvileges
    $acl->allow('redacteur', null, array('publiceer', 'archiveer', 'verwijder'));

    // Administrator erft niets, maar is alle privileges toegestaan
    $acl->allow('administrator');

De `null` waarde in bovenstaande `allow()` aanroepen worden gebruikt om aan te geven dat de toestaan regels op alle Bronnen van toepassing zijn.

## Raadplegen van de ACL

We hebben nu een flexibele ACL die gebruikt kan worden om te bepalen of de aanvrager toestemming heeft om de actie uit te voeren binnen de web applicatie. Raadplegen is vrij simpel met het gebruik van de `isAllowed()` methode:

    <?php
    echo $acl->isAllowed('gast', null, 'bekijk') ?
         "toegestaan" : "geweigerd"; // toegestaan

    echo $acl->isAllowed('medewerker', null, 'publiseer') ?
         "toegestaan" : "geweigerd"; // geweigerd

    echo $acl->isAllowed('medewerker', null, 'herzien') ?
         "toegestaan" : "geweigerd"; // toegestaan

    echo $acl->isAllowed('redacteur', null, 'bekijk') ?
         "toegestaan" : "geweigerd"; // toegestaan vanwege de overerving van gast

    echo $acl->isAllowed('redacteur', null, 'update') ?
         "toegestaan" : "geweigerd"; // geweigerd want er is geen toestaan regel voor 'update'

    echo $acl->isAllowed('administrator', null, 'bekijk') ?
         "toegestaan" : "geweigerd"; // toegestaan want administrator is alles toegestaan

    echo $acl->isAllowed('administrator') ?
         "toegestaan" : "geweigerd"; // toegestaan want administrator is alles toegestaan

    echo $acl->isAllowed('administrator', null, 'update') ?
         "toegestaan" : "geweigerd"; // toegestaan want administrator is alles toegestaan