Zum Hauptinhalt springen
Manchmal möchten Sie den Modellen eines Pakets Autorisierung hinzufügen und der nutzenden Anwendung trotzdem Spielraum lassen, eigene Regeln einzusetzen. Wenn Sie die Zuordnung von Modell und Policy explizit angeben und den Benutzer erst zum Zeitpunkt der Autorisierung prüfen, trennen Sie die Registrierung von den Entscheidungen pro Request. Diese Seite bezieht sich auf den Standard-Branch 13.x der offiziellen Laravel-Dokumentation sowie auf die offizielle Implementierung und die Tests des neuesten Framework-Releases v13.42.0, geprüft am 10. November 2026. Die Grundlagen der Autorisierung finden Sie im Autorisierungs-Leitfaden, das Laden von Providern unter Paket-Auto-Discovery.

Nicht von der User-Klasse der nutzenden Anwendung abhängen

Als Beispiel fügen wir dem Modell Acme\Reports\Models\Report des Pakets eine Autorisierung für update hinzu. Vorausgesetzt wird, dass die Tabelle acme_reports eine Spalte owner_id hat, in der der Authentifizierungs-Identifier des Eigentümers gespeichert ist. Wie Sie Migrationen ausliefern, behandelt Paket-Migrationen. src/Models/Report.php ist ein gewöhnliches Eloquent-Modell.
Wenn die Policy des Pakets App\Models\User als Typ angibt, hängt sie vom Namespace und Modellaufbau der nutzenden Anwendung ab. Wenn Sie nur den Authentifizierungs-Identifier des Benutzers benötigen, verwenden Sie den Laravel-Vertrag Authenticatable. Legen Sie Folgendes in src/Policies/ReportPolicy.php ab.
Zuerst werden null-Identifier ausgeschlossen. Den Typunterschied zwischen einer Ganzzahl aus der Datenbank und einem String gleicht der Vergleich über Strings aus. In diesem Beispiel darf nur der Eigentümer aktualisieren. In Anwendungen mit mehreren Benutzertypen oder Guards prüfen Sie außerdem, ob der Identifier allein das Subjekt eindeutig bestimmt. Falls nicht, ersetzen Sie die Policy durch eine eigene, die Benutzertyp- oder Mandantengrenzen berücksichtigt.
Authenticatable ist ein Vertrag für Dinge wie den Authentifizierungs-Identifier. Er stellt weder isAdministrator() noch Methoden zum Abrufen von Rollen bereit. Wenn Sie paketeigene Berechtigungsinformationen benötigen, definieren Sie einen separaten Vertrag und lassen die nutzende Anwendung eine Implementierung injizieren.

Die Zuordnung im Service-Provider registrieren

Registrieren Sie in boot() von src/ReportsServiceProvider.php nur die Modelle, die dem Paket gehören.
Gate::policy() speichert den Klassennamen der Policy unter dem Klassennamen des Modells. Die Registrierung selbst erzeugt keine Policy, führt keine Datenbankabfrage aus und prüft keinen Benutzer. Erst wenn die Policy benötigt wird, etwa durch Gate::getPolicyFor(), wird sie über make() des Containers erzeugt. Deshalb können Sie Abhängigkeiten in den Konstruktor der Policy injizieren. Die Ablage von Report und ReportPolicy passt auch zur Standard-Auto-Discovery. Hier wird aber explizit registriert, um deutlich zu machen, welche Zuordnung das Paket bereitstellt. Die Registrierung allein wendet keine Autorisierung auf HTTP-Endpunkte an. Rufen Sie vor der Aktualisierung zum Beispiel im Controller Folgendes auf.
Bei Ablehnung wird eine AuthorizationException ausgelöst, die in der normalen HTTP-Verarbeitung zu einer 403-Antwort wird. Die Argumente der Policy-Methode unterscheiden sich zwischen update, das ein Modell erhält, und Fähigkeiten wie create, die den Klassennamen des Modells erhalten. Richten Sie sich nach den Aufrufkonventionen im Autorisierungs-Leitfaden.

Die Auflösungsreihenfolge der Policies lesen

Gate::getPolicyFor() wandelt ein Objekt in seinen Klassennamen um und sucht in der folgenden Reihenfolge. Das ist die Reihenfolge der Policy-Auswahl, nicht die Ausführungsreihenfolge aller Autorisierungs-Hooks. Solange es also eine explizite Registrierung für dieselbe Klasse Report gibt, wird die Policy nicht ersetzt, wenn Sie nur #[UsePolicy] oder die Namenskonvention ändern. Verwendet die nutzende Anwendung dagegen ein Modell, das von Report erbt, haben Policies, die über das eigene Attribut der Kindklasse oder die Ableitung gefunden werden, Vorrang vor der expliziten Registrierung der Elternklasse. Prüfen Sie das auch mit der Modellklasse, die tatsächlich verwendet wird.
guessPolicyNamesUsing() fügt keinen Callback zu einer Liste hinzu, sondern ersetzt den einen Ableitungs-Callback des Gates. Setzt ein unabhängiges Paket ihn nur für seine eigenen Modelle, beeinflusst das auch die Ableitung der nutzenden Anwendung und anderer Pakete. Nutzen Sie als Grundlage policy()-Registrierungen für die Modelle, die dem Paket gehören.

In der nutzenden Anwendung explizit überschreiben

Wenn Sie policy() für dasselbe Modell erneut aufrufen, ersetzt die spätere Registrierung die Zuordnung. Sie einfach in das boot() eines anderen Providers zu legen, hängt von der Ladereihenfolge ab. Eine Möglichkeit ist, in AppServiceProvider::boot() der nutzenden Anwendung einen Callback für den Abschluss des Bootvorgangs zu registrieren.
ApplicationReportPolicy ist eine Policy, die die nutzende Anwendung implementiert. Registriert das Paket in einem normalen boot(), läuft dieser Callback danach. Es ist kein Mechanismus, der bedingungslos Vorrang hat, auch nicht gegenüber erneuten Registrierungen in anderen Booted-Callbacks oder später geladenen Providern. Der registrierende Provider des Paketes ist in diesem Beispiel kein Deferred Provider. Alternativ können Sie die Zuordnung unverändert lassen und im Container das Auflösungsziel von ReportPolicy::class ersetzen. resolvePolicy() lässt die Policy jedes Mal vom Container auflösen, ob dabei tatsächlich eine neue Instanz entsteht, hängt aber vom Binding dieser Policy ab. Vermeiden Sie Designs, die Benutzer- oder Request-Informationen im Konstruktor holen und in einer Singleton-Policy festhalten.

Hooks mit Auswirkung auf die gesamte Autorisierung trennen

Bei einer normalen Gate-Prüfung läuft zuerst das globale Gate::before(). Gibt es einen anderen Wert als null zurück, wird die Entscheidung der Policy nicht ausgeführt. Das Diagramm zeigt nur den Pfad, auf dem eine Policy gefunden wird und die passende Methode aufgerufen werden kann. Die anschließenden globalen after-Hooks und den Rückfall auf Gate-Definitionen, wenn der Policy die Zielmethode fehlt, lässt es aus. Registrieren Sie kein globales Gate::before(), das alle Fähigkeiten erlaubt, nur um eine Administrator-Behandlung im Paket umzusetzen. Damit würden Sie auch die Autorisierung anderer Pakete und der nutzenden Anwendung freigeben. Ein before() innerhalb der Policy gilt nur für diese Policy, wird aber nicht aufgerufen, wenn es keine Methode für die Fähigkeit gibt. Wenn die folgende Methode entscheiden soll, geben Sie null statt false zurück. Außerdem verlangt update() in diesem Beispiel ein nicht-nullable Authenticatable, sodass die Policy-Methode für Gäste nicht ausgeführt wird. Ohne Überschreiben des Ergebnisses, etwa durch globale Hooks, wird die Anfrage abgelehnt. Wenn Sie Gäste zulassen wollen, etwa für öffentliches Lesen, sehen Sie separat ein nullable Benutzerargument und eine explizite Prüfung vor.

Registrierung und Entscheidung getrennt testen

Vorausgesetzt wird die in Paket-Tests vorgestellte Testbench-Basisklasse, die ReportsServiceProvider::class in getPackageProviders() lädt. Das folgende Beispiel ist tests/Feature/ReportPolicyTest.php. Als Benutzer dient das generische Authentifizierungsmodell von Laravel, sodass Sie ohne Speichern in der Datenbank prüfen können.
forUser() schreibt den Benutzer des gemeinsamen Gates nicht um. Es erzeugt ein separates Gate und übergibt ihm die Zuordnungen, Fähigkeiten und Callbacks zum jeweiligen Zeitpunkt. Ein bereits erzeugtes benutzerspezifisches Gate sieht daher spätere Änderungen an Policy-Registrierungen des gemeinsamen Gates nicht. Schließen Sie die Registrierung beim Booten ab und speichern Sie benutzerspezifische Gates nicht in langlebigen Services. In der nutzenden Anwendung brauchen Sie außerdem Prüfungen mit dem echten Guard und Benutzermodell sowie HTTP-Tests für den Update-Endpunkt. Die obigen Tests allein prüfen weder, ob die Route autorisiert ist, noch das Speicherformat des Eigentümer-Identifiers in der Datenbank.

Bei Updates einzuhaltende Verträge

  • Sind die Ergebnisse für Eigentümer, Nicht-Eigentümer, Gäste und Datensätze ohne Eigentümer unverändert?
  • Stimmen die veröffentlichten Fähigkeitsnamen mit den Argumenten der Policy-Methoden überein?
  • Funktioniert das Ersetzen der Policy durch die nutzende Anwendung weiterhin?
  • Wird bei unterstützten Kindmodellen für die Kindklasse tatsächlich die richtige Policy gewählt?
  • Werden echte Update-Requests einschließlich der globalen Hooks der Anwendung wie erwartet erlaubt oder abgelehnt?
Updates, die bestehende Fähigkeiten entfernen oder das Standardverhalten von Erlauben und Ablehnen ändern, wirken sich auf nutzende Anwendungen aus. Behandeln Sie Änderungen der Autorisierung zusammen mit der Versionskompatibilität als öffentlichen Vertrag.

Primärquellen

Zuletzt geändert am 10. November 2026