Aus den Zend Framework Blogs

Donnerstag, 04.03.2010

Irgendwie ist es ja total sinnlos, laufend aktuelle Links zu Blogbeiträgen zum Zend Framework zu sammeln und diese dann nicht zu verbloggen, und diesem sinnlosen Treiben werde ich nun Einhalt gebieten und einfach diese gesammelten Links hier in diesem Blog veröffentlichen, und zwar jetzt und zwar auch in der Reihenfolge des Eingangs:

So, das war es erst einmal. Den nächsten Schwung Zend Framework Beiträge gibt es dann beim nächsten Mal.

http://www.littlehart.net/atthekeyboard/2010/01/27/creating-usable-forms-with-zend-framework/

Tweet this via redir.ec

Zend Framework FAQ: Wie setze ich eine ACL für eine Modul basierte Applikation um?

Montag, 26.10.2009

Bei der ersten Abstimmung für die Zend Framework Fragestunde, wurde diese Frage mit 37% der Stimmen auf Platz 1 gewählt: Wie setze ich eine ACL für eine Modul basierte Applikation um?

Hierfür müssen wir als erstes die Grundlage schaffen und festlegen, was eigentlich mit einer Modul basierten Applikation gemeint ist. Das Zend Framework bietet schon seit einen frühen Anfängen die Möglichkeit, eine Applikation in Module aufzuteilen. In einem Modul können somit Action-Controller, View-Skripte, Models, Formulare und mehr gekapselt werden. Die Klassen dieser Module bekommen einen eigenen vorangestellten Namensraum, damit es nicht zu Namenskonflikten kommen kann. Eine Zend Framework Applikation könnte somit aus den Modulen Gästebuch, Forum und CMS (für Ausgabe von Textbeiträgen) bestehen. Zusätzlich zu diesen Modulen gibt es in der Regel immer ein Default-Modul, dass sich unter anderem um die Auslieferung der Homepage kümmert. Zusammenfassend werden wir also mit den folgenden Module arbeiten:

  • default
  • guestbook
  • forum
  • cms

Um mit Zend_Acl eine ACL (Access Control List) umsetzen zu können, benötigen wir noch die Benutzerrollen. Wir verwenden an dieser Stelle die drei Benutzerrollen admin, editor und guest und gehen davon aus, dass in allen Modulen die selben Benutzerrollen verwendet werden sollen. Den Aspekt der Wiederverwendbarkeit der Module lasse ich an dieser Stelle bewusst unberücksichtigt. Denn dies würde das Ganze nur noch komplizierter machen.

Als nächstes müssen wir noch überlegen, wie wir die Ressourcen, Privilegien und Rechte in unserer ACL definieren. Hierbei gibt es verschiedene Ansätze. Wir könnten als Ressourcen unsere Models betrachten und deren Methoden als Privilegien einsetzen. Ein anderer Ansatz basiert auf dem Dreigespann Modul, Controller und Action. Diesen Ansatz möchte ich hier vorstellen. Als Privilegien verwenden wir die Namen der Aktionsmethoden und als Ressourcen die Namen der Action-Controller Klassen. Und wo bleibt das Modul? Ganz einfach, für jedes Modul erstellen wir eine eigene ACL. Dies hat auch den Vorteil, dass die ACL insgesamt nicht zu groß wird. Zudem können wir durch geschicktes Cachen der Zend_Acl Objekte zusätzlich die Performance steigern.

Hier folgt als Beispiel die ACL für unser CMS Modul. Die ACLs für die anderen Module sehen ähnlich aus und tragen die Klassennamen Default_Acl, Guestbook_Acl und Forum_Acl.

PHP:
  1. class Cms_Acl extends Zend_Acl
  2. {
  3.     public function __construct()
  4.     {
  5.         // Rollen anlegen
  6.         $this->addRole(new Zend_Acl_Role('guest'));
  7.         $this->addRole(new Zend_Acl_Role('editor'), 'guest');
  8.         $this->addRole(new Zend_Acl_Role('admin'), 'editor');
  9.        
  10.         // Ressourcen anlegen, jede Ressource entspricht einem Action-Controller
  11.         $this->addResource(new Zend_Acl_Resource('index'));
  12.         $this->addResource(new Zend_Acl_Resource('article'));
  13.         $this->addResource(new Zend_Acl_Resource('tag'));
  14.         $this->addResource(new Zend_Acl_Resource('comment'));
  15.        
  16.         // Privilegien und Rechte für Gäste anlegen
  17.         $this->allow('guest', 'index');
  18.         $this->allow('guest', 'article', array('index', 'show'));
  19.         $this->allow('guest', 'tag', array('index', 'show'));
  20.         $this->allow('guest', 'comment', array('index', 'show', 'create'));
  21.  
  22.         // Privilegien und Rechte für Redakteure anlegen
  23.         $this->allow('editor', 'article', array('create', 'update', 'delete'));
  24.         $this->allow('editor', 'tag', array('create', 'update'));
  25.         $this->allow('editor', 'comment', array('update', 'delete'));
  26.        
  27.         // Privilegien und Rechte für Admins anlegen
  28.         $this->allow('admin', 'article', array('approve', 'block'));
  29.         $this->allow('admin', 'tag', array('delete'));
  30.         $this->allow('admin', 'comment', array('mark-as-spam', 'hide'));
  31.     }
  32. }

Das ist keine große Sache und sollte jedem klar sein, der sich mit der Zend_Acl Komponente schon ein wenig befasst hat. Jetzt bleibt die Frage, wann wird die entsprechende ACL denn geladen. Dies kann erst passieren, nachdem das Routing statt gefunden hat und klar ist, welches Modul gerade aufgerufen wird. Dafür verwenden wir ein Plugin.

Das Plugin kümmert sich nur um die Benutzerrechte und nicht um die Authentifizierung. Es geht davon aus, dass diese bereits erfolgt ist. Das Plugin in an sich ist relativ selbsterklärend, hervorheben möchte ich nur, dass auf Basis des aktuellen Moduls der Klassenname der entsprechenden ACL erstellt wird. Der Rest sollte Routine sein. Wenn eine Benutzer nicht über entsprechende Rechte verfügt, wird er als Gast gebeten sich einzuloggen und als angemeldeter User bekommt einen entsprechenden Hinweis.

PHP:
  1. class Default_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract
  2. {
  3.     public function routeShutdown(Zend_Controller_Request_Abstract $request)
  4.     {
  5.         // hole Module, Controller und Action
  6.         $module     = $request->getModuleName();
  7.         $controller = $request->getControllerName();
  8.         $action     = $request->getActionName();
  9.        
  10.         // hole Auth
  11.         $auth = Zend_Auth::getInstance();
  12.        
  13.         // hole Rolle
  14.         $role = $auth->hasIdentity()
  15.               ? Zend_Auth::getInstance()->getIdentity()->role
  16.               : 'guest';
  17.        
  18.         // erstelle Klassenname für ACL
  19.         $aclClass = ucfirst($module) . '_Acl';
  20.        
  21.         // Erstelle ACL Objekt
  22.         $acl = new $aclClass(); /* @var $acl Zend_Acl */
  23.        
  24.         // Prüfe Rechte
  25.         if (!$acl->isAllowed($role, $controller, $action))
  26.         {
  27.             // lege neue Action fest
  28.             $newAction = ('guest' == $role) ? 'login' : 'forbidden';
  29.            
  30.             // Ändere Request Objekt für neue Action
  31.             $request->setModuleName('default')
  32.                     ->setControllerName('user')
  33.                     ->setActionName($newAction);
  34.         }
  35.     }
  36. }

Das war es schon im Wesentlichen. Das Ganze ließe sich nun noch verfeinern, indem man sich z.B. eine Factory Methode schreibt, welche das Ermitteln des Klassennamens übernimmt. Dadurch kann die ACL auch außerhalb des Plugins anhand eines Moduls ermittelt werden. Diese Methode könnte My_Acl::factory() heißen, als Parameter $module entgegen nehmen und ein von Zend_Acl abgeleitetes Objekt zurückgeben. Diese Factory-Methode könnte sich dabei auch gleich um das Caching kümmern, so dass die ACLs nicht bei jedem Aufruf neu erstellt werden müssen.

Ich hoffe, die Ausgangsfrage ist somit im Wesentlichen beantwortet. Falls nicht, bitte in den Kommentaren melden. Natürlich auch bei Fragen zu diesem Beitrag.

Tweet this via redir.ec


Better Tag Cloud