Zend_Acl è una delle tante classi di Zend molto utili.
Consiste in una serie di funzionalità che permettono un controllo molto facile di CHI può fare COSA aumentando il livello di protezione del sistema e diminuendo le possibilità di errore da parte dello sviluppatore.
Un esempio:
L’amministratore del sistema potrà fare tutto.
Un utente normale potrà accedere solo ad alcune pagine(o risorse).
Risorse e ruoli.
Queste sono le due entità fondamentali quando si parla di controllo degli accessi.
Le risorse
Una serie di oggetti che si possono controllare, nel caso di pattern MVC, possono essere controller, action, percorsi, ecc.
I ruoli
Sono gli attori attivi del sistema che devono accedere alle risorse, ad esempio amministratori, utenti normali, moderatori, ecc.
Quindi andremo a crea un plugin di Zend che effettuerà i controlli.
I metodi da inserire nel plugin sono 2 :
- __construct() : in cui andremo a specificare risorse, ruoli e permessi
- preDispatch() : l’operazione preliminare alla chiamata di una action in cui effettuare il controllo
Operazioni da implementare nel __construct()
- Creazione dell’ istanza di Zend_Acl
- Creazione della risorsa
- Creazione del ruolo
- Aggiunta della risorsa all’ Access Control List
- Aggiunta del ruolo all’ Access Control List
- Definizione dei permessi su una risorsa da parte di un ruolo
Quindi di seguito il codice:
public function __construct() {
// Creiamo l'istanza
$acl = new Zend_Acl();
// Creiamo la risorsa
$resource1 = new Zend_Acl_Resource('nomeController1');
$resource2 = new Zend_Acl_Resource('nomeController2');
// Creiamo il ruolo
$role = new new Zend_Acl_Role('nomeRuolo');
// Associamo la risorsa all' ACL
$acl->add($resource1);
$acl->add($resource2);
// Associamo il ruolo all' ACL
$acl->addRole($role);
// Andiamo a specificare i vari permessi
// ad es: permettiamo al ruolo di accedere alla risorsa 1 e gli neghiamo la 2
$acl->allow('nomeRuolo', 'nomeController1');
$acl->deny('nomeRuolo', 'nomeController2');
}
Operazioni da implementare del preDispatch():
- Controllo dell’autenticazione dell’utente
- Controllo sui permessi della richiesta effettuata dall’utente
Quindi di seguito il codice:
// nel preDispatch() ho la richiesta fatta
public function preDispatch(Zend_Controller_Request_Abstract $request) {
// controllo se l'utente è autenticato altrimenti lo credo un qualsiasi ospite
if ($this->auth->hasIdentity()) {
$role = $this->auth->getIdentity()->tipo_utente;
} else {
$role = 'ospite';
}
// controllo se il ruolo è contemplato nell'ACL
if (!$this->acl->hasRole($role)) {
$role = 'ospite';
}
// prendo il nome del controller come risorsa alla quale l'utente vuole accedere
$resource = $request->controller;
// prendo il nome dell'azione come privilegio alla quale l'utente vuole accedere
$privilege = $request->action;
// controllo se la risorsa è contemplata dall'ACL
if (!$this->acl->has($resource)) {
$resource = null;
}
// controllo se il ruolo non ha accesso alla risorsa e lo reindirizzo alla pagina per gli ospiti
if (!$this->acl->isAllowed($role, $resource, $privilege)) {
$request->setControllerName($this->_authController['controller']);
$request->setActionName($this->_authController['action']);
}
}
Questo è il plugin da andare ad aggiungere all’applicazione.
Per aggiungerlo andate nel file di bootstrap dell’applicazione (index.php o bootstrap.php) e aggiungete il plugin così:
// istanzio la Zend_Auth $auth = Zend_Auth::getInstance(); $auth->setStorage(new Zend_Auth_Storage_Session()); // istanzio il Zend_Controller_Front $controller = Zend_Controller_Front::getInstance(); $controller->registerPlugin(new CustomControllerAclManager($auth));
Abbiamo quasi finito, bisogna aggiungere la fase di checking dell’identità nel preDispatch() dei vari controller:
class CustomControllerAction extends Zend_Controller_Action {
public function preDispatch() {
$auth = Zend_Auth::getInstance();
if ($auth->hasIdentity()) {
$this->view->authenticated = true;
$this->view->identity = $auth->getIdentity();
} else {
$this->view->authenticated = false;
}
}
}
Bene, con questo il sistema di accessi è terminato.
Possiamo far ereditare il controller ad altri controller figli così che non dobbiamo specificare il checking nel preDispatch() di tutti.
Per dubbi o chiarimenti commentate qui sotto!
Alla prossima!











Iscriviti al feed di Good2know
Ciao.
Bella guida. Solo che io che sono alle prime armi non ho ben capito dove mettere alcune parti di codice. Se inserisco le funzioni di __construct() e preDispatch() in tutti i controllers e mettiamo il caso di averne tanti, ogni volta che modifico un qualcosa nella procedura, devo modificare le funzioni su tutti i controllers. Esiste un modo per definire queste funzioni una sola volta e farle richiamare da ogni controller?
Inoltre. Spesso avviene che i Ruoli e le Risorse siano dimamici in un sito. Es. nel mio i Ruoli li prendo da una tabella dove per ogni Controller definisco, in modo gerarchico, le autorizzazioni. Questa opportunità com’è gestita in Zend_Acl?
Grazie e complimenti ancora per la guida
Ciao Francesco, grazie per i complimenti, rispondo subito alla tua domanda.
Essendo nell’ambito della programmazione ad oggetti (OOP) il problema relativo alla replicazione del codice non esiste.
Se tu hai parti di codice identico su più controller puoi estrarlo e farne una superclasse che poi verrà ereditata dai vari controller.
Nell’esempio fatto tu vedi che il codice è implementato all’interno del CustomControllerAction, se tu avrai un controller per la gestione delle news, quindi NewsController, in cui hai necessità di avere il controllo dell’autorizzazione, NewsController erediterà da CustomController e non più da Zend_Controller_Action:
ad es: class NewsController extends CustomControllerAction.
Per avere più chiari i concetti di programmazione orientata agli oggetti ti consiglio questa guida: http://programmazione.html.it/guide/leggi/38/guida-programmazione-orientata-agli-oggetti/
Ciao e grazie ancora di leggere Good2know!
Oh cavolo… ero incentrato alla semplice funzione e non c’ho proprio pensato all’eritarietà delle classi. Grazie!
Scusa… domanda forse stupida. Mi viene generato un errore sulla riga “$controller->registerPlugin(new CustomControllerAclManager($auth));” perchè non trova il CustomControllerAclManager. Siccome ho fatto delle modifiche. Con che nome lo dovrei sostituire?
Il nome del plugin deriva dal nome della classe del plugin stesso. Avrai la classe “class CustomControllerAclManager extends Zend_Controller_Plugin_Abstract” come plugin per le autorizzazioni.
Se cambi il nome al plugin anche il nome usato nella creazione di istanza dovrà cambiare.