Es existieren 2 Module:
- bibo (Bücherverwaltung)
- login (Loginmodul)
Folgendes Rechtemanagement soll umgesetzt werden:
admin, user, guest
- Admin bekommt vollen Zugriff auf auf Modul bibo und Modul login
- User bekommt Zugriff
- auf die Bibo-Actions: Index, Ausleihen, Zurückgeben, Suchen
- vollen Zugriff auf Login
- gast bekommt Zugriff
- auf die Bibo-Action: Index
- auf die Login-Actions:index, login (logout braucht der gast nicht, sonst wäre er ein user)
Das Rechtemanagement soll über ein .ini-Datei konfigurierbar sein.
Die eigentlichen Nutzer werden aus einer simplen sqlite Datenbank ausgelesen. Die Tabelle heißt simplerweise ‚users‘
und besitzt die Spalten ‚u_id‘, ‚u_username‘, ‚u_passwort‘, ‚u_role‘.
In meinem Fall hat die Tabelle zwei Einträge:
- 1, admin, admin, admin (Loginname:admin, Passwort:admin, Rolle:admin)
- 2, test, test, user (Loginname:test, Passwort:test, Rolle:user)
Analog zu den Zend ACL Tutorials (Kommentare beachten) werden als Plugin im Ordner application/Plugin/Auth die folgenden 3 Dateien angelegt:
- AccessControl.php
- Acl.php
- AuthAdapter.php
Neu hinzu kommt nun die acl.ini im Ordner application/configs/acl.ini
Die Datei AuthAdapter.php bildet die Schnittstelle zu der SQLite-Datenbank:
class Plugin_Auth_AuthAdapter extends Zend_Auth_Adapter_DbTable { public function __construct() { parent::__construct(); $this->setTableName('users'); $this->setIdentityColumn('u_username'); $this->setCredentialColumn('u_passwort'); } }
Der Tabellenname wird wie oben bereits festgelegt auf ‚user‘ gesetzt. Die Spalte mit dem Loginnamen heißt ‚u_username‘, das dazu gehörige Passwort steht in der Spalte ‚u_passwort‘.
Die Datei AccessControl.php ist für das Login-Handling zuständig. Sie führt die Datenbankabfrage bzgl. der Nutzerdaten durch und prüft, ob das Login korrekt ist. Für den Fall, dass der Login nicht korrekt ist, oder der Nutzer keine Rechte besitzt wird die Weiterleitung auf eine Fehlerseite oder das Loginpanel vorgenommen.
class Plugin_Auth_AccessControl extends Zend_Controller_Plugin_Abstract { protected $_auth; protected $_acl; public function __construct(Zend_Auth $auth, Zend_Acl $acl) { $this->_auth = $auth; $this->_acl = $acl; } public function routeStartup(Zend_Controller_Request_Abstract $request) { if (!$this->_auth->hasIdentity() && null !== $request->getPost('login_user') && null !== $request->getPost('login_password')) { // POST-Daten bereinigen $filter = new Zend_Filter_StripTags(); $username = $filter->filter($request->getPost('login_user')); $password = $filter->filter($request->getPost('login_password')); if(!empty($username)) { //Datenbankabfrage $authAdapter = new Plugin_Auth_AuthAdapter(); $authAdapter->setIdentity($username); $authAdapter->setCredential($password); $result = $this->_auth->authenticate($authAdapter); //Fehlermeldung setzen, wenn Login falsch if($result->getCode() != 1) { $view = Zend_Layout::getMvcInstance()->getView(); $view->assign(array('fehler'=>'Login inkorrekt! Bitte korrekten Login eingeben!')); } if($result->getCode() == 1) { $view = Zend_Layout::getMvcInstance()->getView(); $view->assign(array('weiterleitung'=>'true')); } if ($result->isValid()) { $storage = $this->_auth->getStorage(); // die gesamte Tabellenzeile in der Session speichern, // wobei das Passwort unterdrückt wird $storage->write($authAdapter->getResultRowObject(null, 'password')); } } } } public function preDispatch(Zend_Controller_Request_Abstract $request) { if ($this->_auth->hasIdentity() && is_object($this->_auth->getIdentity())) { $role = $this->_auth->getIdentity()->u_role; } else { $role = 'guest'; } $module = $request->getModuleName(); // Ressourcen = Modul -> kann hier geändert werden! $resource = $module; if (!$this->_acl->has($resource)) { $resource = null; } if (!$this->_acl->isAllowed($role, $resource, $request->getActionName())) { if ($this->_auth->hasIdentity()) { // angemeldet, aber keine Rechte -> Fehler! $request->setModuleName('login'); $request->setControllerName('error'); $request->setActionName('noaccess'); } else { // nicht angemeldet -> Login $request->setModuleName('login'); $request->setControllerName('index'); $request->setActionName('index'); } } } }
Bevor wir uns der Acl.php zuwenden, sollten wir nun im application/configs Ordner die Datei acl.ini gemäß unseren Rechtevorstellungen befüllen. Für unser Beispiel sollte das wie folgt aussehen:
;##################################### ;# Bsp.: Module.Role.x = Action # ;##################################### bibo.guest.0 = index bibo.user.0 = index bibo.user.1 = ausleihen bibo.user.2 = leihen bibo.user.3 = suchen bibo.user.4 = zurueck bibo.admin.0 = all login.guest.0 = index login.guest.1 = login login.user.0 = all login.admin.0 = all
Wir setzen unsere Zugriffsrechte nach dem Schema Module.Role.FortlaufendeZahl
Möchtest Du alle Controller einer Resource für eine Rolle freischalten, so kannst Du das wie im Beispiel analog der Zeile
bibo.admin.0 = all
realisieren.
Die Datei Acl.php liest nun die Config-Datei acl.ini ein und setzt die entsprechend der Konfiguration festgelegten Rechte im
Anwendungskontext.
class Plugin_Auth_Acl extends Zend_Acl { protected $_config; public function __construct($aclConfig = null) { //Pfad zur acl.ini setzen if($aclConfig) { //Wenn $aclConfig gesetzt ist dann wird diese Datei als Config-Datei verwendet $this->_config = (string) APPLICATION_PATH."/configs/".$aclConfig; } else { $this->_config = (string) APPLICATION_PATH."/configs/acl.ini"; } //Prüft ob die Config-Datei vorhanden ist if(file_exists($this->_config)) { //Config einlesen und in ein Array packen $config = new Zend_config_Ini($this->_config); $config = $config->toArray(); foreach ($config as $res=>$value) { //Hinzufügen der verfügbaren Resourcen $this->addResource(new Zend_Acl_Resource($res)); foreach ($value as $role=>$access) { if(!$this->_getRoleRegistry()->has($role)) { //Hinzufügen der verfügbaren Rollen $this->addRole(new Zend_Acl_Role($role)); } foreach ($access as $rules) { /* Setzen der Zugriffsrechte: Falls access auf all gesetzt wird, erlaube alles für die Resource, ansonsten definierte Rollen aus acl.ini */ if($rules == 'all') { $this->allow($role, $res, null); } else { $this->allow($role, $res, $rules); } } } } } else { throw new Zend_Acl_Exception('Keine Config-Datei /../application/configs gefunden'); } } }
Damit ist die Grundfunktionalität des ZendAcl-Plugins um eine Konfigurationsdatei erweitert wurden. Man kann nun besser den Überblick zwischen PHP-Code und Konfiguration der Anwendung behalten.