Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. PHP
Code

Wie man CakePHPs Zugriffskontrolllisten benutzt

by
Difficulty:IntermediateLength:LongLanguages:

German (Deutsch) translation by Władysław Łucyszyn (you can also view the original English article)

Wenn Sie ein CMS erstellen, benötigen Sie wahrscheinlich verschiedene Benutzerrollen - Superuser, Administratoren, Benutzer - mit unterschiedlichen Berechtigungsstufen. Zu kompliziert zu programmieren? Geben Sie CakePHPs ACL (Access Control Lists) ein. Mit dem richtigen Setup überprüfen Sie die Benutzerberechtigungen mit nur einer Zeile.

Einführung: Was sind Zugriffskontrolllisten?

Mit der ACL können Sie eine Hierarchie von Benutzern mit ihren jeweiligen Rollen erstellen. Hier ist ein kurzes Beispiel.

  • Super Benutzer
    • Benutzer # 1
  • Admins
    • Benutzer # 2
    • Benutzer # 3
  • Benutzer
    • Benutzer # 4
    • Benutzer # 5
    • Benutzer # 6
    • ....

In diesem Lernprogramm richten wir eine ACL für ein einfaches Blog ein. Wenn Sie Getting Started with CakePHP (und Teil 2) noch nicht auf NetTuts + ausgecheckt haben, tun Sie dies bitte und kehren Sie dann zurück, da wir die Grundlagen des Frameworks für selbstverständlich halten.

Mit dieser Hierarchie können wir für jede Rolle mehrere Berechtigungen vergeben:

  • Die Super User können Beiträge und Benutzer erstellen, lesen, aktualisieren und löschen.
  • Die Administratoren können Beiträge erstellen, lesen, aktualisieren und löschen.
  • Die Benutzer können Beiträge erstellen und lesen.
  • Alle anderen können nur Posts lesen.

Jede Erlaubnis wird der Gruppe und nicht dem Benutzer erteilt; Wenn also Benutzer # 6 zum Administrator befördert wird, wird er gegen die Gruppenberechtigung geprüft - nicht gegen seine. Diese Rollen und untergeordneten Knoten (Benutzer) werden als Zugriffsanforderungsobjekte oder AROs bezeichnet.

Jetzt haben wir auf der anderen Seite die Access Control Objects oder ACOs. Dies sind die zu kontrollierenden Objekte. Oben habe ich Posts und User erwähnt. Normalerweise sind diese Objekte direkt mit den Modellen verknüpft. Wenn wir also ein Post-Modell haben, benötigen wir ein ACO für dieses Modell.

Jedes ACO hat vier grundlegende Berechtigungen: Erstellen, Lesen, Aktualisieren und Löschen. Sie können sich diese mit dem Schlüsselwort CRUD merken. Es gibt eine fünfte Erlaubnis, das Sternchen, das ist eine Abkürzung für vollen Zugriff.

Wir werden nur zwei ACOs für dieses Tutorial verwenden: Post und Benutzer, aber Sie können so viele erstellen, wie Sie benötigen.

Die ACL-Tabellen

Fahren wir fort, die Datenbanktabellen zu erstellen. Sie finden diesen Code in db_acl.sql im Verzeichnis config/sql Ihrer App.

Wir können jetzt beginnen, ARO- und ACO-Knoten zu erstellen, aber hey, wir haben keine Benutzer! Wir müssen ein einfaches Authentifizierungssystem erstellen.


Schritt 1: Ein Basis-Authentifizierungssystem

Da dieses Tutorial für CakePHP-Entwickler mit einem einfachen bis mittleren Wissen über das Framework gedacht ist, werde ich den Code und eine kurze Erklärung liefern. Das Authentifizierungssystem ist jedoch nicht das Ziel dieses Lernprogramms.

Die MySQL-Tabelle:

Das Benutzermodell (models/user.php)

Der Benutzer-Controller (controllers/users_controller.php)

Da wir neue Elemente haben, lassen Sie uns diese überprüfen. Zuerst setzen wir eine $components-Variable. Diese Variable enthält alle Komponenten im Array. Wir werden die Auth-Komponente, die eine Kernkomponente ist, ebenso wie HTML- und Formular-Helfer benötigen, aber da sie nicht standardmäßig von Cake enthalten ist, müssen wir sie manuell hinzufügen.

Die Auth-Komponente behandelt einige grundlegende Authentifizierungsmechanismen: Sie hilft uns, einen Benutzer anzumelden und behandelt die Sitzung eines authentifizierten Benutzers für uns sowie die Abmeldung und die grundlegende Autorisierung für Gäste. Außerdem wird das Passwort automatisch mit einem Hashwert versehen. Ich werde erklären, wie Sie jede Funktion in den folgenden Absätzen aufrufen.

Als Nächstes erstellen wir eine Funktion namens beforeFilter. Dies ist eine callback funktion, mit der wir einige Aktionen durchführen können, bevor die gesamte Controller-Logik verarbeitet wird. Für die Auth-Komponente müssen wir ein Modell angeben, in diesem Fall den Benutzer. Dann wird standardmäßig der gesamte Zugriff auf Benutzer verweigert, die nicht angemeldet sind. Wir müssen dieses Verhalten mit allow() überschreiben, das einen Parameter benötigt. Dieser Parameter kann ein Stern sein, der angibt, dass alle Methoden in diesem Controller von nicht authentifizierten Benutzern aufgerufen werden können. Oder es kann ein Array mit den Funktionen übergeben werden, auf die nicht authentifizierte Benutzer zugreifen können. In diesem Fall, da wir nur drei Funktionen haben, sind die folgenden Zeilen die gleichen.

Für die Funktion login() übernimmt die Auth-Komponente alle Anmeldemechanismen für uns. Wir müssen lediglich die Funktion mit einem Array mit zwei Schlüsseln versehen: den Benutzernamen und das Passwort. Diese Schlüssel können geändert werden, aber standardmäßig werden sowohl der username als auch das password mit der Datenbank abgeglichen und geben true zurück, wenn der Benutzer authentifiziert wurde.

Schließlich versucht die Login-Funktion des Controllers, eine Kombination aus Benutzername und Passwort mit der Datenbank abzugleichen.

Bitte beachten Sie, dass dieser Code sehr einfach ist. Sie müssen die Benutzernamen überprüfen, wenn der Benutzername existiert, die Mindestlänge für das Passwort und so weiter.

Die Registeransicht (views/users/register.ctp)

Die Login-Ansicht (views/users/login.ctp)

Öffne /users/register dich in deinem Webbrowser und registriere ein neues Konto. Ich empfehle admin als Benutzernamen und 123 als Passwort und wenn Ihre Sitzung abläuft, gehen Sie einfach zu /users/login und geben Sie die richtige Kombination Benutzername / Passwort ein, die Sie gerade erstellt haben.


Schritt 2: Den Zugriff auf nicht authentifizierte Benutzer verweigern

Wir arbeiten nicht einmal mit ACL, aber wir können bereits das Posten, Bearbeiten und Löschen von Beiträgen verweigern. Öffnen Sie Ihren Post-Controller und fügen Sie die Auth-Komponente hinzu.

Gehe jetzt zu /posts in deinem Webbrowser. Wenn Sie eingeloggt sind, sollten Sie die Beiträge sehen, aber wenn nicht, werden Sie zu /users/login weitergeleitet. Durch einfaches Einschließen der Auth-Komponente werden standardmäßig alle Aktionen für Gäste abgelehnt. Wir müssen drei Aktionen für nicht autorisierte Benutzer ablehnen: Erstellen, Bearbeiten und Löschen. Mit anderen Worten, wir müssen Index und View zulassen.

Gehe zu bearbeiten oder einen Beitrag erstellen; Wenn Sie nicht eingeloggt sind, sollten Sie zu /users/login weitergeleitet werden. Alles scheint gut zu funktionieren, aber was ist mit den Ansichten? Die Edit- und Delete-Links werden allen angezeigt. Wir sollten eine Bedingung machen.

Bevor wir uns dem widmen, wollen wir uns ansehen, wie die User () - Funktion von Auth funktioniert. Kopieren Sie diese Zeilen und fügen Sie sie in die Indexfunktion ein.

Öffnen Sie Ihre /posts in Ihrem Browser und, wenn Sie eingeloggt sind, wird der pr() so etwas werfen.

Die Funktion user() gibt ein Array genau so zurück, wie es ein Modell tun würde. Wenn wir mehr als drei Felder hatten (das Passwort ist nicht enthalten), werden sie im Array angezeigt. Wenn Sie nicht angemeldet sind, ist das Array leer, sodass Sie wissen, dass ein Benutzer angemeldet ist, wenn das user() -Array von Auth nicht leer ist.

Jetzt ist Auth eine Komponente, die in einem Controller verwendet werden soll. Wir müssen aus einer Sicht wissen, ob ein Benutzer eingeloggt ist, vorzugsweise über einen Helfer. Wie können wir eine Komponente in einem Helfer verwenden? CakePHP ist so großartig und flexibel, dass es möglich ist.

Speichern Sie dieses Snippet in views/helpers als access.php. Jetzt sehen wir den Code Zeile für Zeile. Zuerst richten wir eine $helpers var ein. Helfer können andere Helfer einschließen, genau wie $components. Die Session-Komponente ist für die Auth-Komponente erforderlich, aber wir haben innerhalb eines Helfers keinen Zugriff auf diese Komponente. Zum Glück haben wir einen Session-Helfer, der uns helfen wird.

Als nächstes erstellen wir eine Funktion und verwenden App ::import, wodurch wir ein Element importieren können, auf das wir normalerweise keinen Zugriff hätten. Die nächste Zeile erstellt die Auth-Komponente in einer $auth-Variablen und jetzt einen kleinen schmutzigen Hack; Da die Auth-Komponente die Sitzung liest, um zu wissen, ob wir eingeloggt sind oder nicht, benötigt sie die Session-Komponente, aber da wir sie von einem Ort importieren, dem sie nicht gehören sollte, müssen wir ihr ein neues Session-Objekt geben. Schließlich verwenden wir user() und setzen es auf $user und geben true zurück, wenn die Variable nicht leer ist, andernfalls false.

Lassen Sie uns zum Posts-Controller zurückkehren und mit dem Hinzufügen des Helfers fortfahren.

Auf den Zugriffs-Helper kann jetzt über die Ansicht zugegriffen werden. Öffnen Sie index.ctp in views/posts und ersetzen Sie diese Zeile.

Mit diesem.

Gehe zurück zu deinem Webbrowser, lade die Indexseite neu und wenn du eingeloggt bist, siehst du die Links zum Bearbeiten und Löschen für jeden Beitrag. Sonst wirst du nichts sehen.

Während dies ausreichend wäre, wenn Sie eine App mit ein oder zwei Benutzern haben, ist es nicht genug, wenn Sie Anmeldungen geöffnet haben.


Schritt 3: Installieren der ACL

Öffnen Sie den Benutzer-Controller, und fügen Sie die ACL-Komponente hinzu.

Als nächstes erstellen wir eine Funktion, um die ACOs und AROs Knoten zu installieren.

Durch den Import der ACL-Komponente können wir auf das ACO- und ARO-Modell zugreifen. Wir beginnen mit der Erstellung eines ARO, welches der Anforderer für die Objekte ist; mit anderen Worten, wer wird auf die Objekte zugreifen. Das wäre der Benutzer (daher die User-Zeichenfolge im Modell). Wir schaffen verschiedene Rollen; Super, Admin, Benutzer und suspendiert.

Als nächstes machen wir dasselbe mit ACOs, da wir nur zwei Objekte verwalten müssen (Posts und User), wir werden zwei erstellen, eins für jedes.

Jetzt eine kurze Notiz. Das Array, das wir für ACOs und AROs speichern, hat vier Felder: den Modellnamen, den Fremdschlüssel (was nützlich ist, wenn Sie einem ARO Zugriff gewähren möchten, wie ein von ihm erstellter Post), die Eltern-ID (die später verwendet wird) und ist die grundlegende Eltern-Kind-Knoten-Beziehung, wir werden Benutzer unterhalb dieser Rollen erstellen) und den Alias (der eine schnelle Form zum Suchen der Objekte darstellt).

Schließlich verwenden wir die ACL-Funktion allow(). Der erste Parameter ist der ACO-Alias; zweitens der ARO-Alias und drittens die Berechtigungen, die dem ARO erteilt wurden. Ein Superuser hat vollen Zugriff auf die Post- und Benutzermodelle, ein Administrator hat vollen Zugriff auf das Post-Modell und ein Benutzer kann nur Posts erstellen.

Zu Beginn der Funktion habe ich eine Bedingung definiert, um zu überprüfen, ob die Administratorrolle in ACOs vorhanden ist. Sie möchten das gleiche nicht mehr als einmal installieren, oder? Es würde die Datenbank ziemlich durcheinander bringen.

Öffnen /users/install Sie in Ihrem Webbrowser, und da wir keine Ansicht haben, wird CakePHP einen Fehler auslösen, aber überprüfen Sie einfach den MySQL-Dump. Alle Beziehungen wurden erfolgreich erstellt, es ist Zeit, mit den untergeordneten Knoten zu arbeiten.

Benutzer auf Rollen festlegen

Lasst uns die users tabelle bereinigen. Öffnen Sie phpMyAdmin, wählen Sie Ihre Datenbank, die users tabelle und klicken Sie auf leer. Wir kommen zurück zur register() -Funktion auf dem Benutzer-Controller. Direkt unter dieser Linie:

Füge diesen Code ein:

In der ersten Zeile erstellen wir ein neues ARO-Objekt. Dann erhalten wir den Elternknoten, in dem der Benutzer erstellt wird. Dann erhalten wir den Elternknoten, in dem der Benutzer erstellt wird.

Dann speichern wir eine neue ARO; Das Modell ist das, an dem wir gerade arbeiten, User, der foreign_key ist die ID des letzten Datensatzes, die wir gerade erstellt haben. Die parent_id ist der Knoten, mit dem wir begonnen haben. Wir werden nur die ID und schließlich den Alias übergeben. Es ist eine gute Idee, Model_name, dann ein Trennzeichen :: und dann den Bezeichner zu nennen. Es wird viel einfacher sein, es zu finden.

Jetzt sind wir fertig. Erstelle vier Benutzer: superuser, adminuser, normaluser und suspensionuser. Ich empfehle den gleichen Benutzernamen und das gleiche Passwort für Testzwecke. Vergiss nicht, dass bis zu diesem Zeitpunkt nur der Superuser die Rolle Super hat; alle verbleibenden werden Benutzer sein!


Schritt 4: Lesen von Berechtigungen

Da ACL eine Komponente ist, ist sie nur innerhalb des Controllers zugänglich. Später wird es auch in der Ansicht sein; aber die ersten Dinge zuerst. Nehmen Sie die ACL-Komponente in den Posts-Controller auf, wie wir es im Benutzer-Controller getan haben. Jetzt können Sie mit der Überprüfung von Berechtigungen beginnen. Gehen wir zur Bearbeitungsfunktion und machen einen schnellen Test. Fügen Sie dies in der ersten Zeile dieser Methode hinzu.

Die check() -Funktion von ACL benötigt drei Parameter: den ARO, den ACO und die Aktion. Geh und bearbeite einen Beitrag, und wenn du nicht als Superuser angemeldet bist, stirbt das Skript. Gehen Sie zu /users/login und greifen Sie als Super-Benutzer zu und gehen Sie zurück zur Bearbeitung. Sie sollten in der Lage sein, den Beitrag zu bearbeiten. Überprüfen Sie unten den MySQL-Dump, um die Magie zu sehen. Vier Datenbankabfragen: Das ist sicher nicht skalierbar.

Wir haben zwei Probleme. Zuerst zwei Zeilen für die Berechtigungsprüfung. Zweitens werden die ACLs nicht zwischengespeichert. Und vergessen Sie nicht, dass alle angemeldeten Benutzer den Bearbeitungslink sehen können, auch wenn nur der Super-Benutzer sie verwenden kann.

Lassen Sie uns eine neue Komponente erstellen. Nennen wir es Access.

Speichern Sie es in controllers/components als access.php. Die $user var der Klasse wird initiiert, wenn die Komponente geladen wird, und startup() ist eine Callback-Funktion, so dass sie jetzt in der Klasse gesetzt ist. Jetzt erstellen wir unsere check() -Funktion.

Unsere check() - Methode benötigt nur zwei Parameter: das ACO und die Aktion (optional). Die ARO wird der aktuelle Benutzer für jede Sitzung sein. Der Aktionsparameter wird standardmäßig auf * gesetzt. Dies ist der vollständige Zugriff für das ARO. Die Funktion beginnt damit, zu prüfen, ob der $this->user nicht leer ist (was uns wirklich sagt, ob ein Benutzer eingeloggt ist) und dann gehen wir zu ACL. Das haben wir bereits besprochen.

Wir können nun die Access-Komponente in unseren Post-Controller aufnehmen und die Berechtigungen mit nur einer Zeile prüfen.

Das gleiche Ergebnis wird mit weniger Code erreicht, aber die Fehlermeldung ist hässlich. Du solltest besser die die() mit dem CakePHP Error Handler ersetzen:

Berechtigungen in Ansichten

Das könnte hässlich sein, aber es funktioniert. Wir müssen einen Helper erstellen, der eine Komponente mit einer benutzerdefinierten Methode zur Verwendung im Helper lädt.

Fügen Sie diese Funktion in der Access-Komponente (controllers/components/access.php) hinzu.

Lassen Sie uns nun den Zugriffs-Helper (views/helpers/access.php) neu schreiben.

Die beforeRender() -Methode ist ein Callback, ähnlich dem startup() der Komponente. Wir laden zwei Komponenten und da diese in den meisten Funktionen verwendet werden, ist es eine gute Idee, alle auf einmal zu starten, als sie jedes Mal, wenn die Methode aufgerufen wird, manuell zu starten.

Jetzt können Sie in Ihrer index.ctp-Ansicht in views/posts diese Zeile ersetzen.

Mit diesem.

Vergessen Sie nicht, die Berechtigungen zu überprüfen, sowohl in den Ansichten als auch in den Controllern!

Benutzerdaten

Sie können auf die Benutzerdaten für einen protokollierten Benutzer mit der Methode user() in der Auth-Komponente zugreifen. Dann können Sie auf das Array zugreifen und die gewünschten Informationen erhalten. Aber es muss einen besseren Weg geben. Fügen wir die folgende Funktion in der Access-Komponente hinzu.

Dies ist sehr nützlich, wenn Sie einen Post mit einer user_id-Beziehung speichern müssen.

Und in der Ansicht können wir etwas Ähnliches mit dem Helfer machen.

In Ihrer Vorlagendatei können Sie etwas wie unten tun, um einen Benutzer mit seinem Benutzernamen zu begrüßen.


Schritt 5: Ändern von Berechtigungen

Sagen wir, wir müssen die Rollen für den Benutzer # 4 wechseln: Er muss ein Super User sein. Die ID des Benutzers ist also 4 und Aros ID ist 1.

Jetzt müssen wir den Aro des Benutzers finden, um seinen übergeordneten Aro zu ändern.

Wenn schließlich die Variable $aro_user nicht leer ist, aktualisieren wir das Feld Aro.parent_id.

Bitte beachten Sie, dass Sie sowohl die ID des Nutzers als auch die ID des neuen Nutzers validieren müssen. Wenn einer von diesen nicht vorhanden ist, wird es zu einem Durcheinander in Ihren ACL-Tabellen kommen.


Schritt 6: Optimierung

Obwohl die soeben erstellte Komponente einfach und nützlich ist, wird die Datenbank bei jeder Prüfung abgefragt. Es ist noch nicht produktionsbereit. Zuerst sollte die Datenbank so wenig wie möglich abgefragt werden. Um dies zu optimieren, sollten wir den Cache von CakePHP nutzen.

Die Verwendung von Cache wird die Last ein wenig reduzieren, aber wenn wir zehn Beiträge im Index sehen, und für jeden einzelnen, wir prüfen, ob der Benutzer Update-Berechtigungen für das Post-Aco hat, wird das Framework lesen und analysieren Datei, die das gleiche Ergebnis liefert ... zehnmal für jede Seitenladung.

Das ist der zweite Punkt: Eine Variable innerhalb der Klasse und einige Bedingungen machen die Arbeit leichter, so dass eine wiederholte Anfrage nur einmal gegen Cache überprüft wird.

Diese beiden Änderungen spiegeln sich in access_cache.php im Verzeichnis controllers/components wider. So stellen Sie sicher, dass Sie die Quelle herunterladen!


Schlussfolgerungen

Zugriffskontrolllisten sind grundlegende Funktionen, die die meisten Apps benötigen. CakePHP hat eine nette Implementierung, aber es fehlen sowohl gute Dokumentation als auch Beispiele. Ich hoffe, dass mit diesem Tutorial diese beiden Themen behandelt werden. Danke fürs Lesen!

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.