Zum Hauptinhalt springen

Unterschied zwischen Authentifizierung und Autorisierung

Authentifizierung stellt fest, „wer” ein Benutzer ist. Der Login-Vorgang ist das klassische Beispiel. Autorisierung entscheidet, „was” dieser Benutzer tun darf. Etwa: dass Benutzer nur ihre eigenen Beiträge bearbeiten dürfen oder dass Einstellungen nur von Administratoren geändert werden können. Nachdem Sie mit der Authentifizierung die Anmeldung implementiert haben, folgt als nächster Schritt die Autorisierung.
Für die Autorisierung bietet Laravel zwei Ansätze: Gates und Policies. Welchen Sie einsetzen, hängt vom Anwendungsfall ab.
Entscheidungshilfe
SzenarioEmpfehlung
Einfache Prüfung ohne Bezug auf ein bestimmtes ModelGate
Berechtigungen für CRUD-Operationen an einem ModelPolicy
Zugriffssteuerung für ein Admin-DashboardGate
Berechtigungen für das Erstellen, Bearbeiten und Löschen von BlogbeiträgenPolicy

Gates

Ein Gate ist eine schlanke, auf Closures basierende Autorisierungsprüfung. Es eignet sich für Berechtigungsentscheidungen, die nicht an ein bestimmtes Model gebunden sind.

Autorisierungsablauf mit einem Gate

Ein Gate definieren

Gates werden mit Gate::define() in der Methode boot von App\Providers\AppServiceProvider definiert.
// app/Providers/AppServiceProvider.php

use App\Models\Post;
use App\Models\User;
use Illuminate\Support\Facades\Gate;

public function boot(): void
{
    Gate::define('update-post', function (User $user, Post $post) {
        return $user->id === $post->user_id;
    });
}
Die Closure eines Gates erhält als ersten Parameter stets den aktuell authentifizierten Benutzer. Weitere Parameter können zusätzliche Informationen wie das zu prüfende Model enthalten.

Berechtigungen mit einem Gate prüfen

Um im Controller mithilfe eines Gates zu prüfen, verwenden Sie Gate::allows() oder Gate::denies().
use Illuminate\Support\Facades\Gate;

public function update(Request $request, Post $post): RedirectResponse
{
    if (! Gate::allows('update-post', $post)) {
        abort(403);
    }

    // Beitrag aktualisieren ...

    return redirect('/posts');
}

Ausnahmen mit Gate::authorize() auslösen

Um bei fehlender Berechtigung automatisch eine 403-Antwort zu senden, verwenden Sie Gate::authorize(). Damit sparen Sie sich den manuellen Aufruf von abort(403).
public function update(Request $request, Post $post): RedirectResponse
{
    Gate::authorize('update-post', $post);

    // Nur bei ausreichender Berechtigung erreicht die Ausführung diesen Punkt
    // Beitrag aktualisieren ...

    return redirect('/posts');
}
Gate::authorize() wirft bei fehlender Berechtigung eine Illuminate\Auth\Access\AuthorizationException. Laravel wandelt diese automatisch in eine HTTP-403-Antwort um.

Administrator-Bypass (Methode before)

Wenn Administratoren alle Berechtigungen erhalten sollen, verwenden Sie Gate::before().
use App\Models\User;
use Illuminate\Support\Facades\Gate;

public function boot(): void
{
    // $ability enthält den Namen des aufgerufenen Gates (z. B. 'update-post')
    Gate::before(function (User $user, string $ability) {
        if ($user->isAdministrator()) {
            return true;
        }
    });

    Gate::define('update-post', function (User $user, Post $post) {
        return $user->id === $post->user_id;
    });
}
Wenn die Closure in before einen Wert ungleich null zurückgibt, ist dieses Ergebnis die endgültige Entscheidung. Bei null (oder keiner Rückgabe) läuft die reguläre Gate-Prüfung weiter.

@can / @cannot in Blade-Templates

In Templates sind die Direktiven @can und @cannot für Gate-Prüfungen praktisch.
@can('update-post', $post)
    <a href="{{ route('posts.edit', $post) }}">Bearbeiten</a>
@endcan

@cannot('update-post', $post)
    <p>Sie haben keine Berechtigung, diesen Beitrag zu bearbeiten.</p>
@endcannot

Policies

Eine Policy bündelt die Autorisierungslogik zu einem bestimmten Model in einer eigenen Klasse. Für Berechtigungen zum Anlegen, Anzeigen, Bearbeiten und Löschen eines Post-Models eignen sich Policies besser als Gates.

Autorisierungsablauf mit einer Policy

Eine Policy erzeugen

Erzeugen Sie eine Policy-Klasse mit dem Artisan-Befehl make:policy.
php artisan make:policy PostPolicy
Mit der Option --model erstellen Sie eine Vorlage, die bereits alle CRUD-Methoden für das zugehörige Model enthält.
php artisan make:policy PostPolicy --model=Post
Dies erzeugt die Datei app/Policies/PostPolicy.php.

Automatische Erkennung von Model und Policy

Laravel erkennt Policies standardmäßig anhand einer Namenskonvention automatisch.
  • Model: app/Models/Post.php
  • Policy: app/Policies/PostPolicy.php
Wenn Sie diese Konvention einhalten, entfällt das explizite Registrieren der Policy.
Wenn Sie die Konvention nicht einhalten oder die Policy manuell registrieren möchten, verwenden Sie Gate::policy() in der boot-Methode des AppServiceProvider.
use App\Models\Post;
use App\Policies\PostPolicy;
use Illuminate\Support\Facades\Gate;

Gate::policy(Post::class, PostPolicy::class);
In Laravel 13 können Sie die Zuordnung auch deklarativ über das Attribut #[UsePolicy] am Model festlegen.
use App\Policies\PostPolicy;
use Illuminate\Database\Eloquent\Attributes\UsePolicy;

#[UsePolicy(PostPolicy::class)]
class Post extends Model {}

Policy-Methoden implementieren

Eine mit --model erzeugte Policy enthält Methoden, die den üblichen CRUD-Aktionen entsprechen.
<?php

namespace App\Policies;

use App\Models\Post;
use App\Models\User;

class PostPolicy
{
    /**
     * Darf der Benutzer die Beitragsübersicht ansehen?
     */
    public function viewAny(User $user): bool
    {
        return true; // Jeder authentifizierte Benutzer darf die Übersicht sehen
    }

    /**
     * Darf der Benutzer einen bestimmten Beitrag ansehen?
     */
    public function view(User $user, Post $post): bool
    {
        return true; // Jeder authentifizierte Benutzer darf den Beitrag sehen
    }

    /**
     * Darf der Benutzer einen Beitrag erstellen?
     */
    public function create(User $user): bool
    {
        return true; // Jeder authentifizierte Benutzer darf posten
    }

    /**
     * Darf der Benutzer einen Beitrag bearbeiten?
     */
    public function update(User $user, Post $post): bool
    {
        return $user->id === $post->user_id; // Nur eigene Beiträge dürfen bearbeitet werden
    }

    /**
     * Darf der Benutzer einen Beitrag löschen?
     */
    public function delete(User $user, Post $post): bool
    {
        return $user->id === $post->user_id; // Nur eigene Beiträge dürfen gelöscht werden
    }
}

Administrator-Bypass (Methode before)

Auch in einer Policy können Sie mit einer before-Methode Administratoren pauschal alle Berechtigungen erteilen.
/**
 * Vorabprüfung, die vor allen anderen Policy-Methoden ausgeführt wird.
 * $ability enthält den Namen der Policy-Methode (z. B. 'update' oder 'delete').
 */
public function before(User $user, string $ability): bool|null
{
    if ($user->isAdministrator()) {
        return true; // Administratoren dürfen alles
    }

    return null; // Rückgabe null → Ausführung der regulären Policy-Methode
}
Die before-Methode wird nur aufgerufen, wenn in der Policy-Klasse eine passende Methode existiert. Fehlt zum Beispiel die Methode update, wird auch before nicht aufgerufen.

Ausführungsreihenfolge des before-Callbacks

Policies im Controller nutzen

authorize()-Methode

Der Basis-Controller von Laravel stellt die Hilfsmethode authorize() bereit (wenn Sie nicht vom Basis-Controller erben, verwenden Sie Gate::authorize()).
<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;

class PostController extends Controller
{
    public function update(Request $request, Post $post): RedirectResponse
    {
        Gate::authorize('update', $post);

        // Beitrag aktualisieren ...

        return redirect()->route('posts.index');
    }

    public function store(Request $request): RedirectResponse
    {
        Gate::authorize('create', Post::class);

        // Beitrag erstellen ...

        return redirect()->route('posts.index');
    }

    public function destroy(Post $post): RedirectResponse
    {
        Gate::authorize('delete', $post);

        $post->delete();

        return redirect()->route('posts.index');
    }
}

RESTful-Policies gesammelt mit authorizeResource() registrieren

Rufen Sie im Konstruktor authorizeResource() auf, um für jede Aktion eines Controllers automatisch die passende Policy-Methode zu verknüpfen.
<?php

namespace App\Http\Controllers;

use App\Models\Post;

class PostController extends Controller
{
    public function __construct()
    {
        $this->authorizeResource(Post::class, 'post');
    }

    // Für index(), show(), create(), store(), edit(), update() und destroy()
    // wird automatisch die passende Policy-Methode angewendet
}
Zuordnung zwischen Controller-Aktionen und Policy-Methoden:
Controller-AktionPolicy-Methode
indexviewAny
showview
create / storecreate
edit / updateupdate
destroydelete
Mit authorizeResource() müssen Sie nicht in jeder Aktion einzeln authorize() aufrufen. In Kombination mit einem RESTful-Resource-Controller ist das besonders praktisch.

Autorisierung per Middleware

Um Autorisierungsprüfungen auf Routen-Ebene durchzuführen, verwenden Sie die Middleware can.
use App\Models\Post;

// Nur Benutzer mit Berechtigung zum Aktualisieren von Beiträgen
Route::put('/posts/{post}', [PostController::class, 'update'])
    ->middleware('can:update,post');

// Nur Benutzer mit Berechtigung zum Erstellen von Beiträgen
Route::post('/posts', [PostController::class, 'store'])
    ->middleware('can:create,App\Models\Post');
Eine kürzere Schreibweise mit der Methode can:
Route::put('/posts/{post}', [PostController::class, 'update'])
    ->can('update', 'post');

Policies in Blade-Templates verwenden

Sobald eine Policy registriert ist, werden die Blade-Direktiven @can und @cannot automatisch über die Policy ausgewertet.
{{-- Bearbeiten-Button nur bei entsprechender Berechtigung anzeigen --}}
@can('update', $post)
    <a href="{{ route('posts.edit', $post) }}" class="btn">Bearbeiten</a>
@endcan

{{-- Löschen-Button ebenso --}}
@can('delete', $post)
    <form method="POST" action="{{ route('posts.destroy', $post) }}">
        @csrf
        @method('DELETE')
        <button type="submit">Löschen</button>
    </form>
@endcan

{{-- Button für neuen Beitrag --}}
@can('create', App\Models\Post::class)
    <a href="{{ route('posts.create') }}">Neuer Beitrag</a>
@endcan

Praxisbeispiel: Berechtigungen für Blogbeiträge

Beispiel für eine Blog-Anwendung, in der „nur der Autor eines Beitrags ihn bearbeiten und löschen darf”.
1

Policy erzeugen

php artisan make:policy PostPolicy --model=Post
2

Policy-Methoden implementieren

<?php

namespace App\Policies;

use App\Models\Post;
use App\Models\User;

class PostPolicy
{
    /**
     * Administratoren alle Berechtigungen erteilen
     */
    public function before(User $user, string $ability): bool|null
    {
        if ($user->is_admin) {
            return true;
        }

        return null;
    }

    public function viewAny(User $user): bool
    {
        return true;
    }

    public function view(User $user, Post $post): bool
    {
        return true;
    }

    public function create(User $user): bool
    {
        return true;
    }

    public function update(User $user, Post $post): bool
    {
        return $user->id === $post->user_id;
    }

    public function delete(User $user, Post $post): bool
    {
        return $user->id === $post->user_id;
    }
}
3

authorizeResource() im Controller hinzufügen

<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class PostController extends Controller
{
    public function __construct()
    {
        $this->authorizeResource(Post::class, 'post');
    }

    public function index(): View
    {
        $posts = Post::latest()->paginate(10);
        return view('posts.index', compact('posts'));
    }

    public function store(Request $request): RedirectResponse
    {
        $post = $request->user()->posts()->create(
            $request->validate([
                'title' => ['required', 'string', 'max:255'],
                'body'  => ['required', 'string'],
            ])
        );

        return redirect()->route('posts.show', $post);
    }

    public function update(Request $request, Post $post): RedirectResponse
    {
        $post->update(
            $request->validate([
                'title' => ['required', 'string', 'max:255'],
                'body'  => ['required', 'string'],
            ])
        );

        return redirect()->route('posts.show', $post);
    }

    public function destroy(Post $post): RedirectResponse
    {
        $post->delete();

        return redirect()->route('posts.index');
    }
}
4

Berechtigungsprüfungen im Blade-Template ergänzen

{{-- resources/views/posts/show.blade.php --}}
<h1>{{ $post->title }}</h1>
<p>{{ $post->body }}</p>
<p>Autor: {{ $post->user->name }}</p>

@can('update', $post)
    <a href="{{ route('posts.edit', $post) }}">Bearbeiten</a>
@endcan

@can('delete', $post)
    <form method="POST" action="{{ route('posts.destroy', $post) }}">
        @csrf
        @method('DELETE')
        <button type="submit">Löschen</button>
    </form>
@endcan

Zusammenfassung

  • Gate: einfache Berechtigungsentscheidungen ohne Model-Bezug, zum Beispiel für den Zugriff auf ein Admin-Dashboard oder für globale Konfigurationsrechte.
  • Policy: Berechtigungen für CRUD-Operationen an einem Model. Legen Sie pro Ressource wie Post, Order oder Comment eine Policy-Klasse an.
// Prüfung über ein Gate
Gate::allows('update-post', $post);      // true/false
Gate::denies('update-post', $post);      // true/false
Gate::authorize('update-post', $post);   // Ausnahme bei fehlender Berechtigung

// Prüfung am User-Model
$user->can('update', $post);     // true/false
$user->cannot('update', $post);  // true/false

// Prüfung im Controller
Gate::authorize('update', $post);        // 403 bei fehlender Berechtigung

// Prüfung in Blade
@can('update', $post) ... @endcan
@cannot('update', $post) ... @endcannot
# Leere Policy erzeugen
php artisan make:policy PostPolicy

# Mit passenden CRUD-Methoden für das Model erzeugen
php artisan make:policy PostPolicy --model=Post
Zuletzt geändert am 13. Juli 2026