Files
yii/docs/guide/de/topics.auth.txt
2011-01-16 14:55:27 +00:00

685 lines
28 KiB
Plaintext

Authentifizierung und Autorisierung
===================================
Diese beiden Themen spielen dann eine Rolle, wenn einige Webseiten nur für
bestimmte Benutzer zugänglich sein sollen. Bei der *Authentifizierung* wird
geprüft, ob jemand auch tatsächlich der ist, der er vorgibt zu sein. Meist
geschieht das per Benutzernamen und Passwort. Man könnte aber auch eine andere
zur Identifizierung geeignete Methode verwenden, z.B. eine Chipkarte,
den Fingerabdruck, etc. Über die *Autorisierung* wird festgestellt, ob die
identifizierte (also authentifizierte) Person auch tatsächlich berechtigt
ist, bestimmte Ressourcen zu manipulieren. Normalerweise wird dazu geprüft, ob die
Person einer bestimmten Rolle zugeordnet ist, die Zugriff auf die Ressource
hat.
Yii hat ein einfach anzuwendendes Authentifizierungs-/Autorisierungs-Framework
(Auth-Framework) eingebaut, das leicht an spezielle Bedürfnisse angepasst werden kann.
Zentraler Bestandteil dieses Frameworks ist eine in der Anwendung
vordefinierte *Userkomponente* (Benutzerkomponente), die
das [IWebUser]-Interface implementiert. Diese Userkomponente stellt die
beständigen Identitätsdaten des aktuellen Benutzers dar.
Über `Yii::app()->user` kann von jeder Stelle aus darauf zugegriffen werden.
Mittels der Userkomponente kann man über [CWebUser::isGuest] prüfen,
ob ein Benutzer angemeldet ist oder nicht. Man kann einen Benutzer mit
[login|CWebUser::login] und [logout|CWebUser::logout] an- bzw. abmelden oder
mit [CWebUser::checkAccess] prüfen, ob der Benutzer bestimmte
Operationen ausführen kann. Außerdem kann man den [eindeutigen
Namen|CWebUser::name] bzw. auch andere beständige Identitätsdaten des
Benutzers abfragen.
Definieren der Identitätsklasse
-------------------------------
Wie bereits erwähnt, geht es bei der Authentifizierung darum, die Identität
eines Benutzers zu prüfen. Bei einer typischen Webanwendung werden dazu meist
ein Benutzername und ein Passwort herangezogen. Es kann aber auch andere
Methoden geben, die entsprechend eine andere Implementierung erfordern. Damit
die Art der Authentifizierung geändert werden kann, führt das
Yii Auth-Framework eine Identitätsklasse (engl.: identity class) ein.
Eine Identitätsklasse enthält die eigentliche Logik zur Authentifizierung und
sollte das [IUserIdentity]-Interface implementieren. So können Klassen für
verschiedene Identifizierungsmethoden (z.B. OpenID, LDAP, Twitter
OAuth oder Facebook Connect) angelegt werden. Um eine eigene Identitätsklasse
zu erstellen, empfiehlt es sich für den Anfang, [CUserIdentity] zu erweitern.
Das ist die Basisklasse für alle Methoden, die auf Benutzername und Passwort
basieren.
Im wesentlichen muss eine neue Identitätsklasse nur die Methode
[IUserIdentity::authenticate] implementieren. Sie kapselt die Kernlogik
zur Authentifizierung. Daneben können noch weitere identitätsbezogene Daten
deklariert werden, die während einer Benutzersitzung beständig bereitgehalten
werden sollen.
#### Ein Beispiel
Im folgenden Beispiel zeigen wir, wie man eine Identitätsklasse zur
datenbankgestützten Authentifizierung verwendet. Ein Besucher wird dazu
Benutzernamen und Passwort in ein Anmeldeformular eingeben. Diese Daten werden
dann mittels [ActiveRecord](/doc/guide/database.ar) gegen eine Benutzertabelle
in der Datenbank geprüft. Das Beispiel demonstriert dabei gleich mehreres:
1. Wie man `authenticate()` für eine DB-gestützte Prüfung der Anmeldedaten implementiert.
2. Dass man die `CUserIdentity::getId()`-Methode überschreiben kann, um die Eigenschaft `_id` statt des Benutzernamens zurückzuliefern, wie das in der Basisimplementierung der Fall ist.
3. Wie man die Methode `setState()` ([CBaseUserIdentity::setState]) verwendet, um weitere Daten dauerhaft für spätere Requests zu speichern
~~~
[php]
class UserIdentity extends CUserIdentity
{
private $_id;
public function authenticate()
{
$record=User::model()->findByAttributes(array('username'=>$this->username));
if($record===null)
$this->errorCode=self::ERROR_USERNAME_INVALID;
else if($record->password!==md5($this->password))
$this->errorCode=self::ERROR_PASSWORD_INVALID;
else
{
$this->_id=$record->id;
$this->setState('title', $record->title);
$this->errorCode=self::ERROR_NONE;
}
return !$this->errorCode;
}
public function getId()
{
return $this->_id;
}
}
~~~
Im nächsten Abschnitt zu An- und Abmeldung werden wir sehen, dass diese
Identitätsklasse an die login-Methode des Benutzerobjekts übergeben wird.
Sämtliche Informationen, die (per Aufruf von [CBaseUserIdentity::setState]) in
einem Status gespeichert wurden, werden dort in einem beständigen
Speicher, wie etwa der Session, abgelegt. Diese Daten stehen dann direkt als
Eigenschaften von [CWebUser] zur Verfügung. In unserem Beispiel haben wir den
Titel über `$this->setState('title', $record->title);` gespeichert. Wurde der
Anmeldeprozess durchlaufen, kann man daher die `title`-Information des aktuellen
Benutzers über `Yii::app()->user->title` abrufen. (Dies ist seit Version 1.0.3
möglich. In früheren Versionen musste man stattdessen
`Yii::app()->user->getState('title')` verwenden.)
> Info|Info: Standardmäßig verwendet [CWebUser] die Session als beständigen
Speicher für solche Identitätsdaten. Wenn die cookie-basierte Anmeldung aktiviert
wird (indem [CWebUser::allowAutoLogin] auf true gesetzt wurde), können
Identitätsdaten auch in einem Cookie gespeichert werden. Stellen Sie sicher,
dass Sie hier keine vertraulichen Informationen (z.B. Passwörter) speichern.
An- und Abmelden
----------------
Nachdem wir an einem Beispiel demonstriert haben, wie eine Identitätsklasse
erstellt wird, kann man diese nun zum einfachen An- und Abmelden verwenden.
Das folgende Beispiel zeigt, wie dies erreicht wird:
~~~
[php]
// Benutzer mit übergebenem Benutzernamen/Passwort anmelden
$identity=new UserIdentity($username,$password);
if($identity->authenticate())
Yii::app()->user->login($identity);
else
echo $identity->errorMessage;
......
// Aktuellen Benutzer abmelden
Yii::app()->user->logout();
~~~
Wir erzeugen hier eine neues UserIdentity-Objekt und übergeben die
Anmeldedaten (also die `$username`- und `$password`-Werte aus dem
Anmeldeformular) an den Konstruktor. Danach rufen wir einfach die
`authenticate()`-Methode auf. Falls erfolgreich, übergeben wir die
Identitätsinformationen an die Methode [CWebUser::login], die diese dann in
einem Permanentspeicher (standardmäßig der Sesssion) ablegt, um sie für
späteren Requests verfügbar zu machen. Schlägt die Authentifizierung fehl,
können wir über die `errorMessage`-Eigenschaft weitere Informationen dazu
abfragen.
Ob ein Benutzer erfolgreich authentifiziert wurde, kann in der gesamten
Anwendung einfach über `Yii::app()->user->isGuest` geprüft werden. Verwendet
man einen Permanentspeicher, wie die Session (Standard) und/oder ein Cookie
(wie im folgenden Beschrieben), um die Identitätsinformationen zu speichern,
kann der Anwender über mehrere aufeinanderfolgende Requests angemeldet
bleiben. In diesem Fall wird die Identitätsklasse bzw. der gesamte
Anmeldeprozess nicht bei jedem Request benötigt bzw. durchlaufen. Stattdessen
lädt CWebUser die Identitätsinformationen automatisch aus dem entsprechenden
Permanentspeicher und verwendet sie um den Rückgabewert von
`Yii::app()->user->isGuest` zu bestimmen.
Cookie-basierte Anmdeldung
--------------------------
Ein Benutzer wird automatisch wieder abgemeldet, wenn er für einen bestimmten
Zeitraum nicht aktiv war. Die Dauer hängt von der
[Session-Konfiguration](http://de2.php.net/manual/de/session.configuration.php)
ab. Möchte man das ändern, kann man die Eigenschaft
[allowAutoLogin|CWebUser::allowAutoLogin] der Userkomponente auf true setzen
und eine Dauer als zweiten Parameter an die [CWebUser::login]-Methode übergeben. Der
Benutzer bleibt dann für die angegebene Zeit angemeldet, auch wenn das
Browserfenster geschlossen wird. Beachten Sie, dass der Benutzer dazu in
seinem Browser Cookies akzeptieren muss.
~~~
[php]
// Benutzer für 7 Tage angemeldet lassen. Stellen Sie sicher,
// dass allowAutoLogin in der Userkomponente auf true gesetzt ist
Yii::app()->user->login($identity,3600*24*7);
~~~
Wie bereits erwähnt, werden Daten, die man über [CBaseUserIdentity::setState]
speichert, ebenfalls im Cookie abgelegt, falls man die cookie-basierte
Anmeldung verwendet. Wenn der Besucher das nächste mal angemeldet wird, werden
diese Daten aus dem Cookie ausgelesen und im Status über `Yii::app()->user`
bereitgestellt.
Auch wenn Yii Maßnahmen bereitstellt, um eine Veränderung dieser Cookiedaten
auf der Clientseite zu verhindern, empfehlen wir unbedingt, keine sensiblen
Daten als Status zu speichern. Stattdessen sollte man solche Daten auf der
Serverseite in einem Permanentspeicher (z.B. einer Datenbank) ablegen und bei
Bedarf wiederherstellen.
Für jede seriöse Webanwendung empfehlen wir außerdem folgende Strategie, um
die Sicherheit bei cookie-basierter Anmeldung zu verbessern:
* Zum Zeitpunkt, wenn ein Benutzer sich erfolgreich anmeldet, erzeugt man
einen zufälligen Schlüssel, der sowohl im Statuscookie als auch im
Permanentspeicher (z.B. Datenbank) auf dem Server gespeichert wird.
* Wenn der Benutzer bei einem späteren Request per Cookie angemeldet wird, überprüft man, ob die
beiden Schlüsselwerte übereinstimmen, bevor die Anmeldung durchgeführt wird.
* Wenn der Benutzer sich neu über das Anmeldeformular einloggt, muss ein neuer
Schlüssel erzeugt werden
Damit schließt man aus, dass der Besucher ein altes Statuscookie wiederverwendet,
dessen Statusinformationen aber schon nicht mehr gültig sind.
Zur Umsetzung dieser Strategie müssen folgende beiden Methoden überschrieben
werden:
* [CUserIdentity::authenticate()]: Hier wird die eigentliche Authentifizierung
durchgeführt. Wurde der Benutzer authentifiziert, sollte man hier einen neuen
Zufallsschlüssel erzeugen und diesen sowohl in der Datenbank als auch im
Identitätstatus (mit [CBaseUserIdentity::setState]) speichern.
* [CWebUser::beforeLogin()]: Diese Methode wird beim Anmelden eines
Benutzers aufgerufen. Hier sollte man den Schlüssel aus dem Statuscookie mit
dem in der Datenbank vergleichen.
Zugangskontrollfilter
---------------------
Mit dem Zugangskontrollfilter (engl.: access control filter) lässt sich prüfen,
ob der aktuelle Benutzer die gewünschte Controlleraction ausführen darf. Die
Prüfung erfolgt anhand des Benutzernamens, der IP-Adresse des Clients und dem
Requesttyp. Dieser einfache Filter steht als Anwendungskomponente
["accessControl"|CController::filterAccessControl] bereit.
> Tip|Tipp: Der Zugangskontrollfilter ist für einfache Fälle gedacht.
Kompliziertere Berechtigungsregeln kann man mit der rollenbasierten
Zugriffskontrolle (RBAC) umsetzen, die wir im nächsten Abschnitt
behandeln werden.
Um diesen Filter in einem Controller zu verwenden, überschreibt man die
[CController::filters]-Methode wie folgt (siehe auch
[Filter](/doc/guide/basics.controller#filter) zu näheren Details über
die Anwendung von Filtern):
~~~
[php]
class PostController extends CController
{
......
public function filters()
{
return array(
'accessControl',
);
}
}
~~~
Mit dieser Funktion legt man fest, dass der
[Zugangskontrollfilter|CController::filterAccessControl] auf alle Actions des
`PostController`s angewendet werden soll. Die spezifischen Berechtigungen
werden in der Methode [CController::accessRules] angegeben, die man z.B. so
überschreiben kann:
~~~
[php]
class PostController extends CController
{
......
public function accessRules()
{
return array(
array('deny',
'actions'=>array('create', 'edit'),
'users'=>array('?'),
),
array('allow',
'actions'=>array('delete'),
'roles'=>array('admin'),
),
array('deny',
'actions'=>array('delete'),
'users'=>array('*'),
),
);
}
}
~~~
Hier werden drei Regeln in jeweils einem Array definiert. Das erste Element
eines solchen Arrays ist entweder `'allow'` (erlaube) oder `'deny'` (verbiete). Die
weiteren Name-Wert-Paare bestimmen, wann diese Regel gilt. Die Regeln
oben bedeuten der Reihe nach, dass die `create`- und `edit`-Actions nicht von
anonymen Benutzern aufgerufen werden können. Die `delete`-Action darf von Benutzern
mit der Rolle `admin` ausgeführt werden. Und die `delete`-Action darf von
keinem Benutzer ausgeführt werden.
Die Zugriffsregeln werden eine nach der anderen in der Reihenfolge ihrer
Definition geprüft. Die erste Regel, die vollständig auf den aktuellen
Kontext (z.B. Benutzername, Rolle, IP-Adresse) zutrifft, bestimmt das
Ergebnis. Falls es sich um eine `allow`-Regel handelt, darf die
Action ausgeführt werden, liegt eine `deny`-Regel vor, darf sie nicht
ausgeführt werden. Passt keine der definierten Regeln auf den aktuellen
Kontext, darf die Action ausgeführt werden.
> Tip|Tipp: Um sicherzustellen, dass eine Action nicht doch unter einem bestimmten
> Kontext ausgeführt werden kann, ist es hilfreich, eine immergültige
> `deny`-Regel ans Ende seiner Regeln zu setzen:
> ~~~
> [php]
> return array(
> // ... Andere Regeln ...
> // Die folgende Regel verbietet die 'delete'-Action in jedem Kontext
> array('deny',
> 'actions'=>array('delete'),
> ),
> );
> ~~~
> Diese Regel ist nötig, da eine Action ausgeführt werden darf, falls keine
> anderslautende passende Regel gefunden wurde.
Eine Regel kann folgende Kontextparameter enthalten:
- [actions|CAccessRule::actions]: Definiert, welche Actions diese Regel
betrifft. Dies sollte ein Array aus Action-IDs sein, Groß-/Kleinschreibung
spielt hierbei keine Rolle.
- [controllers|CAccessRule::controllers]: Definiert, welche Controller
diese Regel betrifft. Dies sollte ein Array aus Controller-IDs sein,
Groß-/Kleinschreibung spielt hierbei keine Rolle. Diese Option ist seit
Version 1.0.4 verfügbar.
- [users|CAccessRule::users]: Definiert, welche Benutzer diese Regel
betrifft. Zur Prüfung wird der [Name|CWebUser::name] des aktuellen Benutzers
herangezogen, Groß-/Kleinschreibung spielt hierbei keine Rolle.
Hier können drei spezielle Zeichen verwendet werden:
- `*`: Jeder Benutzer, inkl. anonyme und authentifizierte Benutzer.
- `?`: Anonyme (nicht angemeldete) Benutzer.
- `@`: Authentifizierte (angemeldete) Benutzer.
- [roles|CAccessRule::roles]: Definiert, welche Rollen diese Regel
betrifft. Dazu wird die [rollenbasierte
Zugriffskontrolle](/doc/guide/topics.auth#role-based-access-control) verwendet, die wir im nächsten
Abschnitt beschreiben werden. Konkret wird diese Regel angewendet, wenn
[CWebUser::checkAccess] für eine der Rollen true zurückliefert. Beachten Sie,
dass Sie Rollen vor allem in `allow`-Regeln einsetzen sollten, da eine Rolle
per Definition eine Erlaubnis darstellt, etwas bestimmtes zu tun. Und obwohl
wir hier den Begriff `roles` (Rollen) verwenden, kann der Wert tatsächlich
jedem beliebigen Autorisierungselement entsprechen, inklusive Rollen, Tätigkeiten und
Operationen.
- [ips|CAccessRule::ips]: Definiert, welche Client-IP-Adressen diese
Regel betrifft.
- [verbs|CAccessRule::verbs]: Definiert, welche Requesttypen (z.B. 'GET',
'POST') diese Regel betrifft. Groß-/Kleinschreibung spielt hierbei keine
Rolle.
- [expression|CAccessRule::expression]: Definiert einen PHP-Ausdruck,
dessen Wert darüber entscheidet, ob die Regel zutrifft oder nicht. Im Ausdruck
können Sie `$user` für `Yii::app()->user` verwenden. Diese Option ist seit
Version 1.0.3 verfügbar.
Verhalten nach der Autorisierung
--------------------------------
Wurde eine Autorisierung verweigert, so ist der Benutzer nicht berechtigt,
die gewünschte Action auszuführen und es passiert folgendes:
- War der Benutzer nicht angemeldet und zeigt die Eigenschaft
[loginUrl|CWebUser::loginUrl] der Userkomponente auf die URL der Anmeldeseite,
so wird der Browser auf diese Seite umgeleitet. Beachten Sie, dass
[loginUrl|CWebUser::loginUrl] standardmäßig auf die Seite `site/login` zeigt.
- In allen anderen Fällen wird eine HTTP-Exception mit dem Fehlercode 403 angezeigt.
[loginUrl|CWebUser::loginUrl] kann als relative oder absolute URL angegeben werden.
Man kann auch ein Array konfigurieren, das dann an [CWebApplication::createUrl]
übergeben wird, um damit eine URL zu erzeugen.
Das erste Element dieses Arrays sollte die [Route](/doc/guide/basics.controller#route)
zur Anmeldeaction angeben. Der Rest kann aus Name-Wert-Paaren für GET-Parameter bestehen.
Hier ein Beispiel:
~~~
[php]
array(
......
'components'=>array(
'user'=>array(
// Dies entspricht dem Vorgabewert
'loginUrl'=>array('site/login'),
),
),
)
~~~
Wurde der Browser auf die Anmeldeseite umgeleitet und verläuft die Anmeldung
erfolgreich, kann man den Browser zurück zu der Seite schicken, bei der
die Autorisierung verweigert wurde. Die URL dieser Seite kann über die Eigenschaft
[returnUrl|CWebUser::returnUrl] der Userkomponente abgerufen werden:
~~~
[php]
Yii::app()->request->redirect(Yii::app()->user->returnUrl);
~~~
Rollenbasierte Zugriffskontrolle
--------------------------------
Die rollenbasierte Zugriffskontrolle (RBAC, engl.: role-based access control)
bietet eine einfache und trotzdem leistungsfähige zentralisierte
Zugriffssteuerung. Für weitere Ausführungen zum Vergleich von RBAC mit anderen
traditionellen Verfahren der Berechtigungsprüfung beachten Sie bitte auch den
entsprechenden [Wiki-Artikel](http://de.wikipedia.org/wiki/RBAC) (evtl. auch
in der ausührlicheren [englischen
Version](http://en.wikipedia.org/wiki/Role-based_access_control)).
Yii implementiert über seine
[authManager|CWebApplication::authManager]-Komponente ein hierarchisches
RBAC-Schema. Im folgenden behandeln wir zunächst die Grundkonzepte dieses
Schemas. Danach beschreiben wir, wie man Autorisierungsdaten definiert und
schließlich wie man diese für die Berechtigungsprüfung verwendet.
### Übersicht
Einer der grundlegenden Begriffe bei RBAC mit Yii ist das
*Autorisierungselement* (engl.: authorization item). Ein Autorisierungselement
steht für die Erlaubnis, etwas bestimmtes zu tun (z.B. einen Blogeintrag anzulegen
oder Benutzer zu verwalten). Gemäß ihrer Beschaffenheit und dem anvisierten
Zielpublikum können Autorisierungselemente in *Operationen* (engl.:
operations), *Tätigkeiten* (engl.: tasks) und *Rollen* (engl.: roles) eingeteilt
werden. Eine Rolle besteht aus Tätigkeiten, eine Tätigkeit aus Operationen. Eine
Operation steht für eine atomare Berechtigung.
In einem System kann es zum Beispiel eine Rolle `administrator` geben. Sie
besteht aus den Tätigkeiten `Beiträge verwalten` und `Benutzer verwalten`.
Die Tätigkeit `Benutzer verwalten` könnte aus den Operationen
`Benutzer anlegen`, `Benutzer aktualisieren` und `Benutzer löschen` bestehen.
Um das System noch flexibler zu machen, erlaubt es Yii
sogar, dass eine Rolle aus weiteren Rollen oder Operationen, eine
Tätigkeit aus anderen Tätigkeiten und eine Operation aus anderen Operationen
besteht.
Ein Autorisierungselement wird eindeutig über seinen Namen identifiziert und
kann mit einer *Geschäftsregel* (engl.: business
rule) verbunden sein. Eine Geschäftsregel ist ein PHP-Schnippsel, das
ausgeführt wird, wenn die Berechtigung für das Element geprüft wird.
Liefert dieser Code true zurück, so ist der Benutzer zu diesem Element
berechtigt. Definiert man zum Beispiel eine Operation `aktualisiereBeitrag`,
kann man eine Geschäftsregel hinzufügen, die prüft, ob die ID des Benutzers
mit derjenigen des Beitragsautors übereinstimmt, so dass nur der Autor selbst
berechtigt ist, seine Beiträge zu aktualisieren.
Durch den Einsatz von Autorisierungselementen kann man eine
*Autorisierungshierarchie* aufbauen. Ein Element `A` ist das Elternelement
eines anderen Elements `B` in der Hierarchie, wenn `A` aus `B` besteht (oder
anders ausgedrückt `A` die von `B` dargestellten Berechtigung(en) erbt).
Ein Element kann sowohl mehrere Kind- als auch mehrere Elternelemente
haben. Eine Autorisierungshierarchie ist daher eher ein Graph partieller
Ordnung als eine Baumstruktur. In dieser Hierarchie stehen Rollen auf der
obersten Ebene, Operationen auf der untersten und Tätigkeiten zwischen diesen
beiden.
Wurde die Autorisierungshierarchie einmal erstellt, kann man Benutzer zu den
Rollen in dieser Hierarchie hinzufügen. Ein Benutzer, dem eine Rolle
zugewiesen wurde, hat alle von dieser Rolle dargestellten Berechtigungen. Weist man
einem Benutzer z.B. die Rolle `administrator` zu, hat er Administratorrechte,
was die Tätigkeiten `Beiträge verwalten` und `Benutzer verwalten` beinhaltet
(sowie die zugehörigen Operationen wie `Benutzer anlegen`).
Am einfachsten stellt sich die Anwendung dar: Möchte man in einer
Controlleraction prüfen, ob der aktuelle Benutzer den Beitrag
löschen kann, geht das so:
~~~
[php]
if(Yii::app()->user->checkAccess('löscheBeitrag'))
{
// Beitrag löschen
}
~~~
Konfigurieren des Autorisierungsmanagers
----------------------------------------
Bevor man eine Autorisierungshierarchie anlegen und den Zugriffsschutz
einsetzen kann, muss die [authManager|CWebApplication::authManager]-Komponente
konfiguriert werden. Yii bietet hier zwei Typen an: [CPhpAuthManager] und [CDbAuthManager].
Der erste speichert die Autorisierungsdaten in einer PHP-Datei, der andere
in der Datenbank. Über die Klasse kann man einen dieser Typen, sowie dessen
Starteigenschaften konfigurieren:
~~~
[php]
return array(
'components'=>array(
'db'=>array(
'class'=>'CDbConnection',
'connectionString'=>'sqlite:pfad/zu/datei.db',
),
'authManager'=>array(
'class'=>'CDbAuthManager',
'connectionID'=>'db',
),
),
);
~~~
Jetzt kann man über `Yii::app()->authManager` auf den
[authManager|CWebApplication::authManager] zugreifen.
> Note|Hinweis: Wenn Sie Umlaute für die Bezeichnung Ihrer
Autorisierungselemente verwenden möchten, achten Sie bitte darauf, dass sie
die entsprechenden Tabellen mit UTF-8-Codierung anlegen und sie bei der
Konfiguration der Datenbankverbindung die Eigenschaft
[CDbConnection::charset] ebenfalls auf `utf8` setzen.
Anlegen einer Autorisierungshierarchie
--------------------------------------
Das Anlegen einer Autorisierungshierarchie beinhaltet drei Schritte:
Autorisierungselemente anlegen, zwischen diesen Elementen Beziehungen
definieren und Benutzern Rollen zuweisen. Die
[authManager|CWebApplication::authManager]-Komponente bietet hierfür
eine ganze Reihe von APIs.
Rufen Sie je nach Art des Elements eine der folgenden Methoden auf, um ein
Autorisierungselement zu erstellen:
- [CAuthManager::createRole] (erzeugt Rolle)
- [CAuthManager::createTask] (erzeugt Tätigkeit)
- [CAuthManager::createOperation] (erzeugt Operation)
Hat man eine Reihe von Autorisierungselementen angelegt, kann man mit
den folgenden Methoden Beziehungen zwischen diesen Elementen definieren:
- [CAuthManager::addItemChild] (definiert Eltern-Kind-Beziehung)
- [CAuthManager::removeItemChild] (entfernt Eltern-Kind-Beziehung)
- [CAuthItem::addChild] (definiert Kind-Beziehung von Elternelement aus)
- [CAuthItem::removeChild] (entfernt Kind-Beziehung von Elternelement aus)
Um schließlich einzelnen Benutzern Rollen zuzuweisen, ruft man folgende Methoden
auf:
- [CAuthManager::assign] (weist Rolle zu)
- [CAuthManager::revoke] (entfernt zugewiesene Rolle)
Unten sehen Sie ein Beispiel, wie man mit dieser API eine
Autorisierungshierarchie aufbaut:
~~~
[php]
$auth=Yii::app()->authManager;
$auth->createOperation('erstelleBeitrag','Einen Beitrag erstellen');
$auth->createOperation('leseBeitrag','Einen Beitrag lesen');
$auth->createOperation('aktualisiereBeitrag','Einen Beitrag aktualisieren');
$auth->createOperation('löscheBeitrag','Einen Beitrag löschen');
$bizRule='return Yii::app()->user->id==$params["post"]->authID;';
$task=$auth->createTask('aktualisiereEigenenBeitrag','Einen eigenen Beitrag aktualisieren',$bizRule);
$task->addChild('aktualisiereBeitrag');
$role=$auth->createRole('leser');
$role->addChild('leseBeitrag');
$role=$auth->createRole('autor');
$role->addChild('leser');
$role->addChild('erstelleBeitrag');
$role->addChild('aktualisiereEigenenBeitrag');
$role=$auth->createRole('redakteur');
$role->addChild('leser');
$role->addChild('aktualisiereBeitrag');
$role=$auth->createRole('admin');
$role->addChild('redakteur');
$role->addChild('autor');
$role->addChild('löscheBeitrag');
$auth->assign('leser','leserA');
$auth->assign('autor','autorB');
$auth->assign('redakteur','redakteurC');
$auth->assign('admin','adminD');
~~~
Wurden diese Hierarchie einmalig erstellt, wird sie automatisch von der
[authManager|CWebApplication::authManager]-Komponente (also
z.B. [CPhpAuthManager] oder [CDbAuthManager]) geladen. Man muss obigen
Code also nur einmal ausführen, NICHT bei jeden Request.
> Info|Info: Das Verfahren oben mutet etwas umständlich an. Es soll
> aber lediglich das Prinzip demonstrieren. In der Regel wird der
> Entwickler eine geeignete Verwaltungsschnittstelle entwerfen, mit
> der man Autorisierungshierarchien intuitiver erstellen kann.
Anwendung von Geschäftsregeln
-----------------------------
Erstellt man eine Autorisierungshierarchie, kann man eine Rolle, eine
Tätigkeit oder eine Operation mit einer sogenannten *Geschäftsregel* versehen.
Auch beim Zuweisen einer Rolle an einen Benutzer kann man eine solche
Geschäftsregel angeben. Eine Geschäftsregel ist ein PHP-Schnippsel,
der während der Berechtigungsprüfung ausgeführt wird. In obigem Beispiel
wurde bei der Tätigkeit `aktualisiereEigenenBeitrag`
eine solche Geschäftsregel definiert. Darin wird einfach geprüft,
ob die ID des aktuellen Benutzers mit der des Autors übereinstimmt.
Bei der Zugriffsprüfung wird der Beitrag (post) vom
Entwickler im Array `$params` übergeben.
### Berechtigungsprüfung
Um die Berechtigungsprüfung durchzuführen, braucht man zunächst den Namen des
Autorisierungselements. Will man zum Beispiel zu testen, ob der aktuelle
Benutzer einen Beitrag erstellen kann, muss die Berechtigung zur Operation
`erstelleBeitrag` ermittelt werden. Dazu ruft man [CWebUser::checkAccess]
wie folgt auf:
~~~
[php]
if(Yii::app()->user->checkAccess('erstelleBeitrag'))
{
// Beitrag erstellen
}
~~~
Ist eine Geschäftsregel mit weiteren Parametern mit dem Element verbunden,
können diese ebenfalls mit übergeben werden. Um zum Beispiel zu prüfen, ob
ein Benutzer einen bestimmten Beitrag aktualisieren darf, würde man die
Beitragsdaten in `$params` übergeben:
~~~
[php]
$params=array('post'=>$post);
if(Yii::app()->user->checkAccess('aktualisiereEigenenBeitrag',$params))
{
// Beitrag aktualisieren
}
~~~
### Verwenden von Standardrollen
> Note|Hinweis: Standardrollen können seit Version 1.0.3 verwendet werden.
In vielen Webanwendungen gibt es einige Rollen, denen praktisch alle Benutzer
zugewiesen werden sollen, um z.B. alle authentifizierten Benutzer mit
bestimmten Basisberechtigungen zu versehen. Man könnte also diesen Rollen
jeden einzelnen Benutzer zuwiesen, was allerdings relativ hohen Verwaltungsaufwand
bedeutet. Stattdessen kann man aber auch *Standardrollen* (engl.: default roles) verwenden.
Eine Standardrolle ist eine Rolle, die implizit allen Benutzern zugewiesen
wird und zwar authentifizierten Benutzern genauso, wie Gästen. Man muss ihnen
nicht explizit Benutzer zuweisen. Beim Aufruf von
[CWebUser::checkAccess] werden zunächst die Standardrollen überprüft, als ob
sie dem Benutzer zugewiesen worden wären.
Standardrollen müssen in der Eigenschaft [CAuthManager::defaultRoles]
deklariert werden. Die folgende Konfiguration legt zum Beispiel zwei
Standardrollen fest: `authentifiziert` und `gast`.
~~~
[php]
return array(
'components'=>array(
'authManager'=>array(
'class'=>'CDbAuthManager',
'defaultRoles'=>array('authentifiziert', 'gast'),
),
),
);
~~~
Da eine Standardrolle jedem Benutzer zugewiesen wird, wird sie normalerweise
mit einer Geschäftsregel verbunden, um festzustellen, ob die Rolle
wirklich auf den Benutzer zutrifft. Der folgende Code definiert zum Beispiel
zwei Rollen, "authentifiziert" und "gast", die letzendlich authentifizierten
Benutzern und Gästen entsprechend zugeordnet werden.
~~~
[php]
$bizRule='return !Yii::app()->user->isGuest;';
$auth->createRole('authentifiziert','Autentifizierte Benutzer', $bizRule);
$bizRule='return Yii::app()->user->isGuest;';
$auth->createRole('gast','Gast-Benutzer', $bizRule);
~~~
<div class="revision">$Id: topics.auth.txt 2739 2010-12-14 01:50:04Z weizhuo $</div>