| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 24249 -->
- <!-- Reviewed: no -->
- <sect1 id="learning.multiuser.authorization">
- <title>Erstellung eines Authorisations Systems in Zend Framework</title>
- <sect2 id="learning.multiuser.authorization.intro">
- <title>Einführung in Authorisation</title>
- <para>
- Nachdem ein Benutzer als authentisch identifiziert wurde, kann eine Anwendung mit Ihrem
- Geschäft weitermachen und einige nützliche und gewünschte Ressourcen an den Konsumenten
- liefern. In vielen Fällen können Anwendungen andere Ressource Typen enthalten, wobei
- einige Ressourcen auch striktere Regeln betreffend Zugriff haben können. Dieser Prozess
- der Erkennung, wer Zugriff zu welchen Ressourcen hat, ist der Prozess der
- "Authorisierung". Authorisierung in seiner einfachsten Form ist die Komposition der
- folgenden Elemente:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- die Identität von dem der Zugriff wünscht
- </para>
- </listitem>
- <listitem>
- <para>
- die Ressource für welche die Identität den Zugriff anfragt um Sie zu konsumieren
- </para>
- </listitem>
- <listitem>
- <para>
- und optional, was der Identität erlaubt ist mit der Ressource zu tun
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Im Zend Framework behandelt die Komponente <classname>Zend_Acl</classname> die Arbeit
- der Erstellung eines Baums von Rollen, Ressourcen und Privilegien um
- Authorisationsanfragen zu managen und abzufragen.
- </para>
- </sect2>
- <sect2 id="learning.multiuser.authorization.basic-usage">
- <title>Grundsätzliche Verwendung von Zend_Acl</title>
- <!-- explain the interaction with a User object, how -->
- <para>
- Wenn <classname>Zend_Acl</classname> verwendet wird können beliebige Modelle als Rollen
- oder Ressourcen fungieren indem einfach das richtige Interface implementiert wird. Um
- als Rolle verwendet zu werden muss die Klasse
- <classname>Zend_Acl_Role_Interface</classname> implementieren, welche nur
- <methodname>getRoleId()</methodname> benötigt. Um als Ressource zu verwenden muss eine
- Klasse <classname>Zend_Acl_Resource_Interface</classname> implementieren wofür die
- Klasse so ähnlich die <methodname>getResourceId()</methodname> Methode implementieren
- muss.
- </para>
- <para>
- Anbei wird ein einfaches Benutzermodell demonstriert. Dieses Modell kann einen Teil in
- unserem <acronym>ACL</acronym> System übernehmen indem einfach
- <classname>Zend_Acl_Role_Interface</classname> implementiert wird. Die Methode
- <methodname>getRoleId()</methodname> gibt die Id "guest" zurück wenn die Id nicht
- bekannt ist, oder die Id der Rolle welche mit dem aktuellen Benutzerobjekt verknüpft
- ist. Dieser Wert kann effektiv von überall kommen, eine statische Definition oder
- vielleicht dynamisch von der Datenbankrolle des Benutzers selbst.
- </para>
- <programlisting language="php"><![CDATA[
- class Default_Model_User implements Zend_Acl_Role_Interface
- {
- protected $_aclRoleId = null;
- public function getRoleId()
- {
- if ($this->_aclRoleId == null) {
- return 'guest';
- }
- return $this->_aclRoleId;
- }
- }
- ]]></programlisting>
- <para>
- Wärend das Konzept eines Benutzers als Rolle recht gerade heraus ist, könnte die
- Anwendung ein anderes Modell wählen welches im eigenen System als potentielle
- "Ressource" im <acronym>ACL</acronym> System verwendet wird. Der Einfachheit halber
- verwenden wir das Beispiel eines Blog Posts. Da der Typ der Ressource mit dem Typ des
- Objekts verknüpft ist, gibt diese Klasse nur 'blogPost' als Ressource ID im System
- zurück. Natürlich kann dieser Wert dynamisch sein wenn das System dies benötigt.
- </para>
- <programlisting language="php"><![CDATA[
- class Default_Model_BlogPost implements Zend_Acl_Resource_Interface
- {
- public function getResourceId()
- {
- return 'blogPost';
- }
- }
- ]]></programlisting>
- <para>
- Jetzt da wir zumindest eine Rolle und eine Ressource haben können wir mit der Definition
- der Regeln des <acronym>ACL</acronym> Systems weitermachen. Diese Regeln werden
- konsultiert wenn das System eine Abfrage darüber erhält was möglicherweise eine
- bestimmte Rolle, eine Ressource und optional ein Privileg ist.
- </para>
- <para>
- Nehmen wir die folgenden Regeln an:
- </para>
- <programlisting language="php"><![CDATA[
- $acl = new Zend_Acl();
- // Die verschiedenen Rollen im System einstellen
- $acl->addRole('guest');
- // Der Eigentümer erbt alle Regeln vom Gast
- $acl->addRole('owner', 'guest');
- // Die Ressource hinzufügen
- $acl->addResource('blogPost');
- // Die Privilegien den Rollen- und Ressourcekombinationen hinzufügen
- $acl->allow('guest', 'blogPost', 'view');
- $acl->allow('owner', 'blogPost', 'post');
- $acl->allow('owner', 'blogPost', 'publish');
- ]]></programlisting>
- <para>
- Die oben stehenden Regeln sund recht einfach: eine Gastrolle und eine Eigentümerrolle
- existieren; sowie ein blogPost Ressourcetyp. Gästen ist es erlaubt Blogposts anzusehen,
- und Eigentümern ist es erlaubt zu posten und Blogposts zu veröffentlichen. Um dieses
- System abzufragen könnte man das folgende machen:
- </para>
- <programlisting language="php"><![CDATA[
- // Wir nehmen an dass das Benutzermodell vom Ressourcetyp Gast ist
- $guestUser = new Default_Model_User();
- $ownerUser = new Default_Model_Owner('OwnersUsername');
- $post = new Default_Model_BlogPost();
- $acl->isAllowed($guestUser, $post, 'view'); // true
- $acl->isAllowed($ownerUser, $post, 'view'); // true
- $acl->isAllowed($guestUser, $post, 'post'); // false
- $acl->isAllowed($ownerUser, $post, 'post'); // true
- ]]></programlisting>
- <para>
- Wie man sieht können bei Ausführung der obigen Regeln entweder Eigentümer und Gäste
- Posts ansehen, oder neue Posts erstellen, was Eigentümer können und Gäste nicht. Aber
- wie man erwarten kann ist diese Art von System nicht so dynamisch wie man es wünschen
- könnte. Was, wenn wir sicherstellen wollen das einem spezifischen Benutzer ein sehr
- spezifischer Blogpost gehört bevor Ihm erlaubt wird Ihn zu veröffentlichen? In anderen
- Worten wollen wir sicherstellen das nur Blogpost Eigentümer nur die Möglichkeit haben
- Ihre eigenen Posts zu veröffentlichen.
- </para>
- <para>
- Hier kommen Annahmen zum Einsatz. Annahmen sind Methoden welche aufgerufen werden wenn
- das prüfen einer statischen Regel einfach nicht genug ist. Wenn ein Annahmeobjekt
- registriert wird, dann wird dieses Objekt konsultiert um, typischerweise dynamisch, zu
- ermitteln ob einige Rollen Zugriff auf einige Ressourcen, mit einigen optionalen
- Privilegien haben was nur durch die Logik in der Annahme beantwortet werden kann.
- Für dieses Beispiel verwenden wir die folgende Annahme:
- </para>
- <programlisting language="php"><![CDATA[
- class OwnerCanPublishBlogPostAssertion implements Zend_Acl_Assert_Interface
- {
- /**
- * Diese Annahme sollte die aktuellen Benutzer und BlogPost Objekte
- * empfangen
- *
- * @param Zend_Acl $acl
- * @param Zend_Acl_Role_Interface $user
- * @param Zend_Acl_Resource_Interface $blogPost
- * @param $privilege
- * @return bool
- */
- public function assert(Zend_Acl $acl,
- Zend_Acl_Role_Interface $user = null,
- Zend_Acl_Resource_Interface $blogPost = null,
- $privilege = null)
- {
- if (!$user instanceof Default_Model_User) {
- throw new Exception(__CLASS__
- . '::'
- . __METHOD__
- . ' erwartet das die Rolle eine'
- . ' Instanz von user ist');
- }
- if (!$blogPost instanceof Default_Model_BlogPost) {
- throw new Exception(__CLASS__
- . '::'
- . __METHOD__
- . ' erwartet das die Ressource eine'
- . ' Instanz von BlogPost ist');
- }
- // Wenn die Rolle ein publisher ist kann Sie einen Post immer verändern
- if ($user->getRoleId() == 'publisher') {
- return true;
- }
- // Prüfen um sicherzustellen das alle anderen nur deren eigene Posts
- // verändern
- if ($user->id != null && $blogPost->ownerUserId == $user->id) {
- return true;
- } else {
- return false;
- }
- }
- }
- ]]></programlisting>
- <para>
- Um dies mit unserem <acronym>ACL</acronym> System zu verknüpfen würden wir das folgende
- tun:
- </para>
- <programlisting language="php"><![CDATA[
- // Dies ersetzen:
- // $acl->allow('owner', 'blogPost', 'publish');
- // Mit diesem:
- $acl->allow('owner',
- 'blogPost',
- 'publish',
- new OwnerCanPublishBlogPostAssertion());
- // Auch die Rolle"publisher" hinzufügen der auf alles Zugriff hat
- $acl->allow('publisher', 'blogPost', 'publish');
- ]]></programlisting>
- <para>
- Jetzt wird jedesmal wenn <acronym>ACL</acronym> darüber konsultiert wird ob ein
- Benutzer einen spezifischen Blogpost veröffentlichen kann diese Annahme ausgeführt.
- Diese Annahme stellt sicher dass, solange der Rollentyp nicht 'publisher' ist, die
- Benutzerrolle der Anfrage logisch mit dem Blogpost verbunden sein muss. In diesem
- Beispiel haben wir geprüft das die Eigenschaft <property>ownerUserId</property> des
- Blogposts mit der übergebenen Id des Benutzers übereinstimmt.
- </para>
- </sect2>
- </sect1>
|