> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Laravel Sentinel – Analyse der Route-Schutz-Middleware

> Analyse des Quellcodes des Pakets laravel/sentinel. Wir erläutern, wie diese treiberbasierte Route-Schutz-Middleware Management-Tools wie Telescope, Horizon und Pulse absichert.

<Info>
  Dieser Artikel basiert auf einer Quellcode-Analyse (Branch `1.x`). Eine offizielle Dokumentation gibt es noch nicht; das Paket ist vor dem offiziellen Release (Stand: April 2026).
</Info>

## Was ist Sentinel?

[Laravel Sentinel](https://github.com/laravel/sentinel) ist ein Security-Middleware-Paket, das den Zugriff auf Routen treiberbasiert steuert. Es wird von Taylor Otwell und Mior Muhammad Zaki entwickelt und unterstützt PHP ^8.0 sowie Laravel 8–13.

Der Hauptzweck ist der Schutz von Routen der Management-Tools Telescope, Horizon und Pulse. Es genügt, `SentinelMiddleware` auf eine Route anzuwenden, um den Zugriff über die vom Treiber definierte Autorisierungslogik zu steuern.

```mermaid theme={null}
graph TD
    A["HTTP-Anfrage"] --> B["SentinelMiddleware"]
    B --> C["Sentinel-Facade"]
    C --> D["SentinelManager<br>(Illuminate\\Support\\Manager)"]
    D --> E["Treiber auflösen<br>driverOrFallback()"]
    E --> F["Driver#authorize()"]
    F -->|true| G["Weiter zur nächsten Middleware"]
    F -->|false| H["abort 401"]
```

## Vergleich mit dem bisherigen Vorgehen

Telescope und Horizon boten jeweils eigene Autorisierungsmechanismen über `gate`.

```php theme={null}
// Bisheriges Verfahren (etwa im TelescopeServiceProvider)
Gate::before(function ($user) {
    return $user->isAdmin() ? true : null;
});
```

Dieser Weg hängt vom Authentifizierungsstatus des Nutzers ab: „ohne Login lässt sich nicht entscheiden". Sentinel arbeitet als Middleware und steuert den Zugriff pro Anfrage – unabhängig davon, ob der Nutzer authentifiziert ist. Zudem lassen sich Regeln für mehrere Management-Tools an einer Stelle definieren.

## Installation

```bash theme={null}
composer require laravel/sentinel
```

Da in `composer.json` unter `extra.laravel.providers` der `SentinelServiceProvider` registriert ist, wird der Service Provider automatisch erkannt. Es muss keine Konfigurationsdatei veröffentlicht werden.

## Architektur des Pakets

```mermaid theme={null}
classDiagram
    class Sentinel {
        +static getFacadeAccessor()
    }
    class SentinelManager {
        +createLaravelDriver() Laravel
        +getDefaultDriver() string
        +driverOrFallback(?string driver) mixed
        +extend(string driver, Closure callback) SentinelManager
    }
    class Driver {
        #Closure applicationResolver
        +authorize(Request request) bool*
        +authorizeOrFail(Request request) void
        #authorizeAccessingViaReverseProxies(Request request) bool
        #isRunningOnDockerLocally(Request request) bool
        #isPrivateIp(string requestIp) bool
        #app() Application
    }
    class Laravel {
        +authorize(Request request) bool
    }
    class SentinelMiddleware {
        +handle(Request request, Closure next, ?string driver) mixed
    }

    Sentinel --> SentinelManager : Facade
    SentinelManager --|> Manager
    Laravel --|> Driver
    SentinelMiddleware --> Sentinel : nutzt
```

## Verhalten des Standard-Treibers (Laravel-Treiber)

Der Standard-Treiber `Laravel` steuert **nur in der lokalen Umgebung (`APP_ENV=local`)** den Zugriff.

```php theme={null}
// src/Drivers/Laravel.php
public function authorize(Request $request): bool
{
    if (! $this->app()->environment('local')) {
        return true; // Außerhalb von local immer erlauben
    }

    // Warnung bei Zugriff über Tunnel-Dienste
    if ($this->isPrivateIp($request->ip())
        && ! $request->isFromTrustedProxy()
        && Str::endsWith($request->host(), ['.sharedwithexpose.com', '.ngrok-free.app', '.ngrok.io'])) {
        throw new RuntimeException(
            'Unable to access "..." using "local" environment, ...'
        );
    }

    // Docker-Lokalumgebung erlauben
    if ($this->isRunningOnDockerLocally($request)) {
        return true;
    }

    // Zugriff über Reverse-Proxies prüfen
    return $this->authorizeAccessingViaReverseProxies($request);
}
```

Zusammenfassung des Ablaufs:

```mermaid theme={null}
flowchart TD
    A[Anfrage empfangen] --> B{Lokale Umgebung?}
    B -->|Nein| C[Gibt true zurück<br>(immer erlaubt)]
    B -->|Ja| D{Private IP und<br>nicht trustedProxy und<br>Tunnel-Dienst?}
    D -->|Ja| E[RuntimeException auslösen<br>Konfigurationshinweis ausgeben]
    D -->|Nein| F{Docker-Lokal?<br>127.0.0.1 + .dockerenv}
    F -->|Ja| G[Gibt true zurück<br>(erlaubt)]
    F -->|Nein| H{Nicht-private IP und<br>Zugriff über trustedProxy?}
    H -->|Ja| I[Gibt false zurück<br>(blockiert)]
    H -->|Nein| J[Gibt true zurück<br>(erlaubt)]
```

<Warning>
  Der `Laravel`-Treiber gibt außerhalb der `local`-Umgebung immer `true` (erlauben) zurück. Für Zugriffssteuerung in der Produktion erstellen Sie einen eigenen Treiber.
</Warning>

### Erkennung privater IPs

Die Basismethode `isPrivateIp()` der Klasse `Driver` erkennt anhand von Symfonys `IpUtils` folgende Bereiche als private IPs.

| Bereich          | Beschreibung         |
| ---------------- | -------------------- |
| `127.0.0.0/8`    | Loopback (RFC1700)   |
| `10.0.0.0/8`     | Privat (RFC1918)     |
| `192.168.0.0/16` | Privat (RFC1918)     |
| `172.16.0.0/12`  | Privat (RFC1918)     |
| `169.254.0.0/16` | Link-Local (RFC3927) |
| `::1/128`        | IPv6-Loopback        |
| `fc00::/7`       | IPv6 Unique Local    |
| `fe80::/10`      | IPv6 Link-Local      |

### Erkennung von Docker-Lokalumgebungen

```php theme={null}
// src/Drivers/Driver.php
protected function isRunningOnDockerLocally(Request $request): bool
{
    return $request->server->get('REMOTE_ADDR') === '127.0.0.1'
        && file_exists(base_path('.dockerenv'));
}
```

Wenn `REMOTE_ADDR` auf `127.0.0.1` steht und die Datei `.dockerenv` im Projekt-Root existiert, wird eine Docker-Lokalumgebung erkannt.

## Einsatz als Middleware

### Grundlegende Verwendung

```php theme={null}
use Laravel\Sentinel\Http\Middleware\SentinelMiddleware;

Route::middleware(SentinelMiddleware::class)->group(function () {
    Route::get('/telescope', function () { /* ... */ });
    Route::get('/horizon', function () { /* ... */ });
    Route::get('/pulse', function () { /* ... */ });
});
```

### Einen Treiber angeben

Sie können den Treibernamen als Argument der Middleware übergeben. Bei einem nicht existierenden Treibernamen wird auf den Default-Treiber zurückgefallen (Verhalten von `driverOrFallback()`).

```php theme={null}
Route::middleware([SentinelMiddleware::class . ':custom-driver'])->group(function () {
    // Autorisierung durch benutzerdefinierten Treiber
});
```

### Implementierung der Middleware

```php theme={null}
// src/Http/Middleware/SentinelMiddleware.php
public function handle(Request $request, Closure $next, ?string $driver = null)
{
    abort_unless(Sentinel::driverOrFallback($driver)->authorize($request), 401);

    return $next($request);
}
```

Gibt `authorize()` `false` zurück, wird mit HTTP 401 abgebrochen. Mit `Driver::authorizeOrFail()` ließe sich stattdessen eine `AuthorizationException` werfen (die Middleware selbst nutzt dies nicht).

## Eigene Treiber erstellen

Durch Erben von der abstrakten `Driver`-Klasse und Implementierung der Methode `authorize()` erstellen Sie einen eigenen Treiber.

```php theme={null}
use Laravel\Sentinel\Sentinel;
use Laravel\Sentinel\Drivers\Driver;
use Illuminate\Http\Request;

Sentinel::extend('admin-only', function ($app) {
    return new class extends Driver {
        public function authorize(Request $request): bool
        {
            // Nur authentifizierte Nutzer mit admin-Rolle erlauben
            $user = $request->user();

            return $user !== null && $user->hasRole('admin');
        }
    };
});
```

Die Registrierung von `extend()` erfolgt beispielsweise in `AppServiceProvider::boot()`.

### Utility-Methoden der Basisklasse nutzen

Die Klasse `Driver` stellt praktische Methoden wie IP-Prüfungen bereit, die eigene Treiber frei verwenden können.

```php theme={null}
public function authorize(Request $request): bool
{
    // In der Produktion nur private IPs erlauben
    if ($this->app()->environment('production')) {
        return $this->isPrivateIp($request->ip());
    }

    // Lokal nur Docker oder Direktzugriff erlauben
    return $this->isRunningOnDockerLocally($request)
        || $this->authorizeAccessingViaReverseProxies($request);
}
```

## Funktionsweise des SentinelManager

`SentinelManager` erbt von `Illuminate\Support\Manager`. `Manager` ist Laravels Basisklasse für das Treibermuster; über `driver()` werden Treiberinstanzen aufgelöst und gecacht.

```php theme={null}
// src/SentinelManager.php
class SentinelManager extends Manager
{
    protected function createLaravelDriver()
    {
        return new Laravel(fn () => $this->getContainer());
    }

    public function getDefaultDriver()
    {
        return 'laravel';
    }

    public function driverOrFallback(?string $driver)
    {
        return rescue(
            fn () => $this->driver($driver),
            value(fn () => $this->driver()),
            false  // nicht loggen
        );
    }
}
```

`driverOrFallback()` fällt bei nicht gefundenem Treiber still auf den Default-Treiber zurück. Ein nicht existierender Treibername im Middleware-Argument führt daher nicht zu einem Fehler.

`SentinelManager` wird vom `SentinelServiceProvider` als Scoped Singleton (`scoped`) registriert, sodass die Treiber-Instanz innerhalb einer Anfrage wiederverwendet wird.

```php theme={null}
// src/SentinelServiceProvider.php
public function register(): void
{
    $this->app->scoped(SentinelManager::class, fn ($app) => new SentinelManager($app));
}
```

## Fazit

`laravel/sentinel` ist ein kleines Paket, das dank des Treibermusters auf Basis von `Illuminate\Support\Manager` hoch erweiterbar ist.

| Aspekt                | Inhalt                              |
| --------------------- | ----------------------------------- |
| Version               | 1.x                                 |
| Unterstütztes PHP     | ^8.0                                |
| Unterstütztes Laravel | 8–13                                |
| Default-Treiber       | steuert nur die local-Umgebung      |
| Eigene Treiber        | über `Sentinel::extend()` ergänzbar |

Der Standard-`Laravel`-Treiber ist darauf spezialisiert, in der lokalen Entwicklung Zugriffe über Tunnel-Dienste zu blockieren. Für den Schutz produktiver Umgebungen ist ein eigener Treiber erforderlich. Sobald die offizielle Dokumentation vorliegt, werden konkretere Einsatzmuster deutlicher werden.

<Card title="Repository laravel/sentinel" icon="github" href="https://github.com/laravel/sentinel">
  Quellcode und aktuelle Änderungen finden Sie im GitHub-Branch `1.x`.
</Card>


## Related topics

- [CSRF-Schutz](/de/csrf.md)
- [Middleware](/de/middleware.md)
- [Laravel Sanctum (API-Token-Authentifizierung)](/de/sanctum.md)
- [E-Mail-Verifizierung (Email Verification)](/de/verification.md)
- [Routing](/de/routing.md)
