Die Ratenbegrenzung ist entscheidend für den Schutz von Anwendungs- oder Website-Ressourcen vor übermäßiger oder unsachgemäßer Nutzung. Ob durch böswillige menschliche Eingriffe, Bot-basierte Angriffe oder eine übersehene Schwachstelle – der Missbrauch von Ressourcen kann den rechtmäßigen Zugriff auf deine Anwendung beeinträchtigen und schwerwiegende Schwachstellen verursachen.

In diesem Artikel erfährst du, wie du einer API in einer Laravel-Anwendung eine Ratenbegrenzung hinzufügen kannst.

Drossele deinen API-Verkehr in Laravel

Die Ratenbegrenzung ist ein Mechanismus, der die Ausbeutung der Ressourcen deiner Anwendung eindämmen soll. Es gibt viele Einsatzmöglichkeiten, aber besonders nützlich ist es für öffentliche APIs in großen, skalierbaren Systemen. Sie stellt sicher, dass alle legitimen Nutzer/innen einen fairen Zugang zu den Systemressourcen erhalten.

Die Ratenbegrenzung ist auch wichtig für die Sicherheit, die Kostenkontrolle und die allgemeine Systemstabilität. Sie kann dazu beitragen, anfragebasierte Angriffe wie verteilte Denial-of-Service-Angriffe (DDoS) zu verhindern. Bei diesem Angriff werden wiederholte Anfragen gesendet, um den Zugang zu einem Anwendungs- oder Webserver zu überlasten und zu stören.

Es gibt mehrere Methoden, um die Ratenbegrenzung zu implementieren. Du kannst Variablen verwenden, die den Anfragenden charakterisieren, um zu bestimmen, wer auf deine Anwendung zugreifen darf und wie häufig. Einige gängige Variablen sind:

  • IP-Adresse – Durch die Implementierung von Ratenbeschränkungen auf Basis von IP-Adressen kannst du die Anzahl der Anfragen pro Adresse begrenzen. Diese Methode ist besonders dann von Vorteil, wenn Nutzer/innen auf eine Anwendung zugreifen können, ohne ihre Anmeldedaten anzugeben.
  • API-Schlüssel – Wenn du den Zugriff über API-Schlüssel beschränkst, erhältst du vom Anfragenden vorgenerierte API-Schlüssel und legst Ratenbeschränkungen für jeden Schlüssel fest. Bei diesem Ansatz kannst du auch verschiedene Zugriffsstufen auf die generierten API-Schlüssel anwenden.
  • Kunden-ID – Du kannst auch eine Kunden-ID vorgenerieren, die ein Nutzer in die Kopfzeile oder den Text der API-Anfrage einfügen kann. Mit dieser Methode kannst du Zugriffsstufen pro ID festlegen, um sicherzustellen, dass kein Client die Systemressourcen monopolisieren kann.

Laravel Middleware

Middleware ist ein praktischer Mechanismus zur Überprüfung und Filterung von HTTP-Anfragen, die in eine Anwendung eingehen. Im Wesentlichen handelt es sich dabei um eine Codeschicht zwischen der Anwendung und der zugrunde liegenden Infrastruktur, die die Kommunikation zwischen den Ressourcen ermöglicht.

Wie man Ratenbegrenzungen implementiert

In diesem Lernprogramm wird eine bestehende Mini-Bibliotheks-API des Laravel 10-Frameworks verwendet, um die Verwendung von Laravel Throttle zu demonstrieren. Das Beispielprojekt enthält die grundlegenden CRUD-Implementierungen (Create, Read, Update und Delete), die für die Verwaltung von Büchern in einer Sammlung benötigt werden, sowie zwei zusätzliche Routen, um einige Konzepte zur Ratenbegrenzung zu demonstrieren.

Voraussetzungen

Das Tutorial setzt voraus, dass du mit den Grundlagen der API-Entwicklung in Laravel vertraut bist. Vergewissere dich, dass du über die folgenden Voraussetzungen verfügst:

Du verwendest auch MyKinsta, um diese API einzurichten und bereitzustellen. Du kannst dich an der mitgelieferten Projektvorlage orientieren und dir das Endergebnis anhand des vollständigen Quellcodes ansehen.

Laravel-Anwendung einrichten

  1. Um zu beginnen, klone die Projektvorlage.
  2. Dann erstellst du eine .env-Datei im Stammverzeichnis des Projekts und kopierst den Inhalt von .env.example in diese Datei.
  3. Vervollständige das Setup mit den folgenden Befehlen, um die Abhängigkeiten der Anwendung zu installieren und den Anwendungs-Schlüssel zu erzeugen.
composer install
php artisan key:generate

Wenn dieser Befehl den Anwendungs-Schlüssel nicht automatisch zu deiner .env-Datei hinzufügt, führe php artisan key:generate --show aus, kopiere den generierten Schlüssel und füge ihn als Wert für APP_KEY in deine .env-Datei ein.

  1. Sobald die Installation der Abhängigkeiten und die Generierung des App-Schlüssels abgeschlossen sind, startest du die Anwendung mit dem folgenden Befehl:
php artisan serve

Dieser Befehl startet die Anwendung und macht sie über den Browser unter https://127.0.0.1:8000 zugänglich.

  1. Besuche die URL und bestätige, dass die Laravel-Begrüßungsseite angezeigt wird:

Auf der Laravel-Willkommensseite wird das Logo oben in der Mitte angezeigt.
Die Laravel-Willkommensseite

Datenbank-Konfigurationen

Lass uns die Anwendungsdatenbank in MyKinsta konfigurieren und einrichten.

  1. Navigiere zum Dashboard deines MyKinsta-Kontos und klicke auf die Schaltfläche Dienst hinzufügen:

Das obere Segment des MyKinsta-Dashboard-Tabs enthält eine obere Symbolleiste.
MyKinsta-Dashboard mit mehreren konfigurierten Diensten

  1. Klicke in der Liste Dienst hinzufügen auf Datenbank und konfiguriere die Parameter, um deine Datenbankinstanz zu starten:

Das Modul "Datenbank erstellen" von Kinsta zeigt den ersten Abschnitt "Grundlegende Informationen" an.
MyKinsta-Datenbankkonfiguration

In diesem Tutorial wird MariaDB verwendet, aber du kannst jede der von Laravel unterstützten Datenbankoptionen wählen, die Kinsta anbietet.

  1. Wenn du die Details deiner Datenbank eingegeben hast, klicke auf die Schaltfläche Weiter, um den Vorgang abzuschließen.

Datenbanken, die auf Kinsta bereitgestellt werden, haben interne und externe Verbindungsparameter. Du solltest interne Verbindungsparameter für Anwendungen verwenden, die innerhalb desselben Kinsta-Kontos gehostet werden, und externe Parameter für externe Verbindungen. Verwende daher die externen Datenbank-Anmeldedaten von Kinsta für deine Anwendung.

  1. Kopiere und aktualisiere die .env-Anmeldedaten der App-Datenbank mit den externen Anmeldedaten, wie im Screenshot unten gezeigt:

Das Kinsta-Dashboard zeigt den Abschnitt "Grundlegende Details" der neu erstellten Datenbank "library-records" an. Alle Informationen stimmen mit denen überein, die im vorherigen Datenbank-Setup-Bild eingegeben wurden.
Details zur Konfiguration der MyKinsta-Datenbank

DB_CONNECTION=mysql
DB_HOST=your_host_name
DB_PORT=your_port
DB_DATABASE=your_database_info
DB_USERNAME=your_username
DB_PASSWORD=your_password
  1. Nachdem du die Zugangsdaten für die Datenbank eingegeben hast, teste die Verbindung, indem du die Datenbankmigration mit dem folgenden Befehl anwendest:
php artisan migrate

Wenn alles ordnungsgemäß funktioniert, solltest du eine ähnliche Antwort wie die unten abgebildete erhalten.

Die Terminalausgabe zeigt den Bash-Befehl "php artisan migrate" und seine Ausgabe an. Unmittelbar unter dem Befehl steht unter "INFO" "Running migrations". Darunter sind die vier Migrationen und ihre Status wie folgt aufgelistet:2014_10_12_000000_create_users_table...812ms DONE.2014 _10_12_100000_erstelle_passwort_zurueck_tokens_table...882ms DONE.2019_08_19_000000_erstelle_failed_jobs_table...942ms DONE.2019_12_14_000001_erstelle_personal_access_tokens_table...1.250ms DONE. Unten steht der Cursor auf einer leeren Befehlszeile, um weitere Eingaben zu ermöglichen.
Erfolgreiche Datenbankmigration auf einem Terminal

  1. Als Nächstes verwendest du den folgenden Befehl, um die Anwendungsrouten aufzulisten und die bereits implementierten Routen zu sehen.
php artisan route:list

Du solltest jetzt die verfügbaren API-Endpunkte sehen:

  1. Starte die Anwendung und überprüfe, ob alles noch gut funktioniert. Du kannst diese Endpunkte über das Terminal mit einem Tool wie Postman oder CURL testen.

Wie man die Rate in einer Laravel-Anwendung begrenzt

Für Laravel-Anwendungen gibt es verschiedene Techniken zur Ratenbegrenzung. Du kannst eine Reihe von IP-Adressen sperren oder eine zeitliche Begrenzung der Anfragen auf Basis der IP-Adresse oder der User_id eines Nutzers durchsetzen. Als Nächstes wendest du jede dieser Methoden an.

  1. Installiere das Paket Laravel Throttle mit dem folgenden Befehl:
composer require "graham-campbell/throttle:^10.0"
  1. Du kannst auch zusätzliche Änderungen an den Laravel Throttle-Konfigurationen vornehmen, indem du die Datei vendor configurations veröffentlichst:
php artisan vendor:publish --provider="GrahamCampbellThrottleThrottleServiceProvider"

Wie man IP-Adressen blockiert

Eine Technik zur Ratenbegrenzung ermöglicht es dir, Anfragen von einer bestimmten Gruppe von IP-Adressen zu blockieren.

  1. Zunächst erstellst du die notwendige Middleware:
php artisan make:middleware RestrictMiddleware
  1. Öffne als Nächstes die erstellte Middleware-Datei app/Http/Middleware/RestrictMiddleware.php und ersetze den Code in der Funktion handle durch das folgende Snippet. Achte darauf, dass du use App; zur Liste der Importe am Anfang der Datei hinzufügst.
$restrictedIps = ['127.0.0.1', '102.129.158.0'];
if(in_array($request->ip(), $restrictedIps)){
  App::abort(403, 'Request forbidden');
}
return $next($request);
  1. In der Datei app/Http/Kernel.php erstellst du einen Alias für diese Middleware-Anwendung, indem du das Array middlewareAliases wie folgt aktualisierst:
    protected $middlewareAliases = [
    . . .
    'custom.restrict' => AppHttpMiddlewareRestrictMiddleware::class,
    ];
    1. Dann wende diese Middleware auf die /restricted-route in der Datei routes/api.php wie folgt an und teste:
    Route::middleware(['custom.restrict'])->group(function () {
      Route::get('/restricted-route', [BookController::class, 'getBooks']);
    });

    Wenn sie korrekt funktioniert, blockiert diese Middleware alle Anfragen von den IPs im Array $restrictedIps: 127.0.0.1 und 102.129.158.0. Anfragen von diesen IPs geben eine 403 Forbidden-Antwort zurück, wie unten gezeigt:

    Die Postman-Anwendung gibt eine "403 Request Forbidden"-Antwort auf eine GET-Anfrage an die URL
    Eine 403 Forbidden Antwort für den /restricted-route GET Endpunkt auf Postman

    Wie man Anfragen nach IP-Adresse drosselt

    Als Nächstes schränkst du die Anfragen anhand der IP-Adresse des Nutzers ein.

    1. Wende die Throttle-Middleware auf die Routen GET und PATCH des Endpunkts /book in routes/api.php an:
    Route::middleware(['throttle:minute'])->group(function () {
      Route::get('/book', [BookController::class, 'getBooks']);
    });
    
    Route::middleware(['throttle:5,1'])->group(function () {
      Route::patch('/book', [BookController::class, 'updateBook']);
    });
    1. Du musst auch die Funktion configureRateLimiting in der Datei app/Providers/RouteServiceProvider mit der Middleware aktualisieren, die du zu den oben genannten Routen hinzugefügt hast.
    … 
    RateLimiter::for('minute', function (Request $request) {
      return Limit::perMinute(5)->by($request->ip());
    });

    Diese Konfiguration begrenzt die Anfragen an den Endpunkt /book GET auf 5 pro Minute, wie unten dargestellt.

    Die Postman-Anwendung gibt eine "429 Too Many Requests"-Antwort auf eine GET-Anfrage an die URL
    Eine „429 Too Many Requests“-Antwort für den /book GET-Endpunkt auf Postman

    Drosselung auf Basis von Benutzer-ID und Sitzungen

    1. Um die Raten mithilfe der Parameter user_id und session zu begrenzen, aktualisiere die Funktion configureRateLimiting in der Datei app/Providers/RouteServiceProvider mit den folgenden zusätzlichen Begrenzern und Variablen:
    ...
    RateLimiter::for('user', function (Request $request) {
      return Limit::perMinute(10)->by($request->user()?->id ?: $request->ip());
    });
    RateLimiter::for('session', function (Request $request) {
      return Limit::perMinute(15)->by($request->session()->get('key') ?: $request->ip());
    });
    1. Wende diesen Code auf die Routen /book/{id} GET und /book POST in der Datei routes/api.php an:
    Route::middleware(['throttle:user'])->group(function () {
      Route::get('/book/{id}', [BookController::class, 'getBook']);
    });
    Route::middleware(['throttle:session'])->group(function () {
      Route::post('/book', [BookController::class, 'createBook']);
    });

    Dieser Code begrenzt die Anfragen mit user_id bzw. session.

    Zusätzliche Methoden in Throttle

    Laravel Throttle bietet mehrere zusätzliche Methoden, mit denen du deine Implementierung der Ratenbegrenzung besser kontrollieren kannst. Zu diesen Methoden gehören:

    • attempt – Ruft den Endpunkt auf, erhöht die Trefferzahl und gibt einen booleschen Wert zurück, der angibt, ob die konfigurierte Treffergrenze überschritten wurde.
    • hit – Trifft die Drossel, erhöht die Trefferzahl und gibt $this zurück, um einen weiteren (optionalen) Methodenaufruf zu ermöglichen.
    • clear – Setzt den Throttle-Zähler auf Null zurück und gibt $this zurück, damit du auf Wunsch einen weiteren Methodenaufruf machen kannst.
    • count – Gibt die Gesamtzahl der Treffer für die Drossel zurück.
    • check – Gibt einen booleschen Wert zurück, der angibt, ob das Throttle-Trefferlimit überschritten wurde.
    1. Um die Ratenbegrenzung mit diesen Methoden zu testen, erstelle eine Middleware-Anwendung namens CustomMiddleware mit dem folgenden Befehl:
    php artisan make:middleware CustomMiddleware
    1. Füge dann die folgenden Importdateien zu der neu erstellten Middleware-Datei in app/Http/Middleware/CustomMiddleware.php hinzu:
    use GrahamCampbellThrottleFacadesThrottle;
    use App;
    1. Ersetze als Nächstes den Inhalt der Methode handle durch den folgenden Codeschnipsel:
    $throttler = Throttle::get($request, 5, 1);
    Throttle::attempt($request);
    if(!$throttler->check()){
      App::abort(429, 'Too many requests');
    }
    return $next($request);
    1. In der Datei app/Http/Kernel.php erstellst du einen Alias für diese Middleware-Anwendung, indem du das Array middlewareAliases wie folgt aktualisierst.
    protected $middlewareAliases = [
    . . .
    'custom.throttle' => AppHttpMiddlewareCustomMiddleware::class, 
    ];
    1. Dann wendest du diese Middleware auf die /custom-route in der Datei routes/api.php an:
    Route::middleware(['custom.throttle'])->group(function () {
      Route::get('/custom-route', [BookController::class, 'getBooks']);
    });

    Die soeben implementierte benutzerdefinierte Middleware prüft, ob das Throttle-Limit überschritten wurde, indem sie die check method. If the limit is exceeded, it responds with a 429 error. Otherwise, it allows the request to continue.

    Wie du die Anwendung auf dem Kinsta-Server bereitstellst

    Nachdem du nun erfahren hast, wie du eine Ratenbegrenzung in einer Laravel-Anwendung implementieren kannst, musst du die Anwendung auf dem Kinsta-Server bereitstellen, damit sie weltweit zugänglich ist.

    1. Beginne damit, den aktualisierten Code auf GitHub, GitLab oder Bitbucket hochzuladen.
    2. Klicke in deinem Kinsta-Dashboard auf die Schaltfläche Dienst hinzufügen und wähle Anwendung aus der Liste aus. Verbinde dein Git-Konto mit deinem Kinsta-Konto und wähle das richtige Repository für die Bereitstellung aus.
    3. Unter Grundlegende Details gibst du der Anwendung einen Namen und wählst dein bevorzugtes Rechenzentrum aus. Vergewissere dich außerdem, dass du die notwendigen Umgebungsvariablen für die Anwendung hinzugefügt hast. Diese entsprechen den Variablen in deiner lokalen .env-Datei: die APP_KEY und die Datenbank-Konfigurationsvariablen.

    Der Abschnitt "Anwendungsdetails" des Kinsta-Moduls "Anwendung hinzufügen".
    Details zur Anwendung auf MyKinsta

    1. Klicke auf die Schaltfläche Weiter, um die Build-Umgebungsvariablen auszuwählen. Du kannst die Standardwerte beibehalten, da Kinsta die notwendigen Parameter automatisch ausfüllt.
    2. Auf der Registerkarte Prozesse kannst du die Standardwerte beibehalten oder einen Namen für deinen Prozess eingeben. Auf dieser Registerkarte kannst du auch die Pod- und Instanzgrößen auswählen.
    3. Auf der Registerkarte Zahlung schließlich siehst du eine Zusammenfassung deiner Auswahlen. Füge deine bevorzugte Zahlungsoption hinzu, um den Prozess abzuschließen.
    4. Wenn du fertig bist, klicke auf die Registerkarte Anwendungen, um eine Liste der bereitgestellten Anwendungen anzuzeigen.
    5. Klicke auf den Namen der Anwendung, um ihre Einsatzdetails anzuzeigen (siehe unten). Du kannst die URL der Anwendung verwenden, um sie aufzurufen.

    Auf der MyKinsta-Registerkarte " Bereitstellungen" werden Details zu den bereitgestellten Anwendungen angezeigt.
    Bereitstellungsdetails auf dem MyKinsta Dashboard

    Wie du die Anwendung testest

    1. Um die Anwendung lokal zu testen, verwende den Befehl php artisan serve.

    Dieser Befehl macht deinen Anwendungsbrowser unter http://localhost:8000 zugänglich. Du kannst die API-Endpunkte, für die du die Ratenbegrenzung implementiert hast, von hier aus testen, indem du die Ratenbegrenzungsfunktion wiederholt aufrufst.

    Der Kinsta-Server zeigt eine Access Forbidden-Antwort an, weil du keine Konfigurationsdetails hinzugefügt hast, die Kinsta sagen, wie die Anwendung bedient werden soll. Füge diese Details jetzt hinzu.

    1. Erstelle eine Datei .htaccess im Hauptverzeichnis deiner Anwendung und füge den folgenden Code in die Datei ein:
     <IfModule mod_rewrite.c>
      RewriteEngine On
      RewriteRule ^(.*)$ public/$1 [L]
    </IfModule>
    1. Pushe diese Änderungen auf GitHub und Kinsta setzt die Änderungen automatisch um.
    2. Öffne nun die Anwendung über die angegebene URL und stelle sicher, dass du die Laravel-Begrüßungsseite siehst.

    Jetzt kannst du die API-Endpunkte, für die du die Ratenbegrenzung mit Postman implementiert hast, testen, indem du sie wiederholt aufrufst, bis du das konfigurierte Limit erreicht hast. Wenn du das Limit überschreitest, erhältst du eine Antwort 429 Too Many Requests.

    Zusammenfassung

    Die Integration von Ratenbegrenzungsfunktionen in eine Laravel-API hilft dabei, die Rate zu kontrollieren, mit der Nutzer die Ressourcen einer Anwendung verbrauchen. Die Ratenbegrenzung hilft dir, ein zuverlässiges Nutzererlebnis zu bieten, ohne dass es zu einer Über- oder Unterauslastung kommt. Außerdem wird so sichergestellt, dass die zugrunde liegende Infrastruktur der Anwendung funktional und effizient bleibt.

    Du kannst auch den Kinsta-Blog besuchen, um mehr über andere spannende Konzepte zu Laravel und anderen Webtechnologien zu erfahren. Die erschwinglichen und nahtlosen Hosting-Dienste sind für deine Anwendung und die Bedürfnisse deines Teams sehr zu empfehlen.

Marcia Ramos Kinsta

Ik ben de Editorial Team Lead bij Kinsta. Ik ben een open source liefhebber en ik houd van coderen. Met meer dan 7 jaar ervaring in technisch schrijven en redactiewerk voor de tech-industrie, werk ik graag samen met mensen om duidelijke en beknopte content te creëren en workflows te verbeteren.