Rate limiting is essentieel voor het beschermen van resources van apps of websites tegen overmatig of onjuist gebruik. Of dit nu het gevolg is van kwaadwillig menselijk ingrijpen, botgebaseerde aanvallen of een over het hoofd geziene kwetsbaarheid, misbruik van bronnen kan de legitieme toegang tot je applicatie verstoren en ernstige kwetsbaarheden introduceren.

Dit artikel onderzoekt hoe je snelheidsbeperking kunt toevoegen aan een API in een Laravel applicatie.

Je API verkeer beperken in Laravel

Rate limiting is een mechanisme dat is ontworpen om het gebruik van de resources van je applicatie te beperken. Hoewel het veel toepassingen heeft, is het vooral nuttig voor openbare API’s in grote, schaalbare systemen. Het zorgt ervoor dat alle legitieme gebruikers eerlijke toegang behouden tot systeemresources.

Rate limiting is bovendien cruciaal voor beveiliging, kostenbeheersing en algehele stabiliteit van het systeem. Het kan op verzoeken gebaseerde aanvallen helpen voorkomen, zoals DDoS aanvallen (Distributed Denial-of-Service). Dit soort aanval is gebaseerd op het verzenden van herhaalde verzoeken om de toegang tot een applicatie of website server te overweldigen en te verstoren.

Er zijn verschillende methoden om rate limiting te implementeren. Je kunt variabelen gebruiken die de aanvrager karakteriseren om te bepalen wie toegang krijgt tot je applicatie en hoe vaak. Enkele veelgebruikte variabelen zijn:

  • IP adres – Door rate limits te implementeren op basis van IP adressen kun je het aantal aanvragen per adres beperken. Deze methode is vooral nuttig in omstandigheden waarin gebruikers toegang kunnen krijgen tot een applicatie zonder referenties op te geven.
  • API sleutel – Het beperken van toegang via API sleutels houdt in dat je de aanvrager voorziet van vooraf gegenereerde API sleutels en dat je per sleutel rate limits instelt. Met deze aanpak kun je ook verschillende toegangsniveaus toepassen op de gegenereerde API sleutels.
  • Client ID – Je kunt ook vooraf een Client ID genereren die een gebruiker kan invoegen in de header of body van API verzoeken. Met deze methode kun je toegangsniveaus per ID instellen om ervoor te zorgen dat geen enkele client systeembronnen kan monopoliseren.

Laravel Middleware

Middleware biedt een handig mechanisme voor het inspecteren en filteren van HTTP-verzoeken die een applicatie binnenkomen. In wezen is het een laag code tussen de applicatie en de onderliggende infrastructuur om communicatie tussen de bronnen mogelijk te maken.

Zo implementeer je rate limits

Deze tutorial maakt gebruik van een bestaande mini-library API op het Laravel 10 framework om het gebruik van Laravel throttling te demonstreren. Het voorbeeld startproject bevat de basis create, read, update en delete (CRUD) implementaties die nodig zijn om booksin een collectie te beheren en twee extra routes om een aantal rate-limiting concepten te demonstreren.

Vereisten

De tutorial gaat ervan uit dat je bekend bent met de basisprincipes van API ontwikkeling in Laravel. Zorg ervoor dat je over het volgende beschikt:

Je gebruikt ook MyKinsta om deze API in te stellen en te implementeren. Je kunt de meegeleverde projecttemplates volgen en een voorbeeld van het eindresultaat bekijken vanuit de volledige sourcecode.

Laravel applicatie opzetten

  1. Om te beginnen kloon je de projecttemplate.
  2. Maak vervolgens een .env bestand aan in de hoofdmap van het project en kopieer de inhoud van .env.example hierin.
  3. Voltooi vervolgens de installatie met de volgende commando’s om de dependencies van de app te installeren en de app key te genereren.
composer install
php artisan key:generate

Als dit commando niet automatisch de app key aan je .env bestand toevoegt, voer dan php artisan key:generate --show uit, kopieer de gegenereerde sleutel en plak deze in je .env bestand als de waarde voor APP_KEY.

  1. Zodra de installatie van de dependencies en het genereren van de app-sleutel voltooid zijn, start je de applicatie met het volgende commando:
php artisan serve

Dit commando start de applicatie en maakt deze toegankelijk via de browser op https://127.0.0.1:8000.

  1. Bezoek de URL om te bevestigen dat de Laravel welkomstpagina verschijnt:

Op de welkomstpagina van Laravel staat het logo middenboven.
Het Laravel welkomstscherm

Configuratie database

Laten we de applicatiedatabase configureren en instellen in MyKinsta.

  1. Navigeer naar het dashboard van je MyKinsta account en klik op de knop Dienst toevoegen:

Het bovenste segment van het tabblad MyKinsta Dashboard featuret een bovenste werkbalk.
MyKinsta dashboard met verschillende services geconfigureerd.

  1. Klik in de lijst Dienst toevoegen op Database en configureer de parameters om je database-instantie te starten:

De module "Een database maken" van Kinsta toont de eerste sectie, genaamd "Basisgegevens".
MyKinsta database configuratie.

Deze tutorial gebruikt MariaDB, maar je kunt elke door Laravel ondersteunde database kiezen die Kinsta biedt.

  1. Zodra je je databasegegevens hebt ingevoerd, klik je op de knop Doorgaan om het proces af te ronden.

Databases die worden aangeboden op Kinsta hebben interne en externe verbindingsparameters. Je moet interne verbindingsparameters gebruiken voor applicaties die binnen hetzelfde Kinsta account worden gehost en externe parameters voor externe verbindingen. Gebruik daarom de externe databasegegevens van Kinsta voor je applicatie.

  1. Kopieer de .env referenties van de database van je app en werk ze bij met de externe referenties in de schermafbeelding hieronder:

Het Kinsta dashboard toont het gedeelte "Basisgegevens" van de nieuw aangemaakte database " library-records". Alle informatie komt overeen met de informatie die is ingevoerd in de vorige afbeelding voor het instellen van de database.
MyKinsta database configuratie details.

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. Nadat je de databasegegevens hebt ingevuld, test je de verbinding door de databasemigratie toe te passen met het onderstaande commando:
php artisan migrate

Als alles naar behoren werkt, zou je een respons moeten zien zoals hieronder.

De uitvoer van de terminal toont het Bash-commando "php artisan migrate" en de uitvoer daarvan.Direct onder het commando staat een "INFO"-label met de tekst "Lopende migraties."Daaronder staan de vier migraties en hun statussen, als volgt opgesomd:2014_10_12_000000_create_users_table...812ms DONE.2014_10_12_100000_create_password_reset_tokens_table...882ms DONE.2019_08_19_000000_create_failed_jobs_table...942ms DONE.2019_12_14_000001_create_personal_access_tokens_table...1250ms DONE.Hieronder staat de cursor op een lege command line om extra invoer mogelijk te maken.
Succesvolle databasemigratie in een terminal.

  1. Gebruik vervolgens het volgende commando om de applicatieroutes op te sommen en de reeds geïmplementeerde routes te bekijken.
php artisan route:list

Je zou nu de beschikbare API endpoints moeten zien:

De terminal geeft de "php artisan route" weer:
De routelijst van de toepassing op de terminal.

  1. Start de applicatie en controleer of alles nog steeds goed werkt. Je kunt deze endpoints via de terminal testen met een tool als Postman of CURL.

Zo stel je een rate limit in een Laravel applicatie

Er zijn verschillende rate limit technieken beschikbaar voor Laravel applicaties. Je kunt een set IP adressen blokkeren of op duur gebaseerde aanvraaglimieten afdwingen op basis van het IP adres of user_id van een gebruiker. Vervolgens pas je elk van deze methoden toe.

  1. Installeer het Laravel Throttle pakket met het volgende commando:
composer require "graham-campbell/throttle:^10.0"
  1. Je kunt ook extra wijzigingen aanbrengen in de Laravel Throttle configuraties door het vendor configurations bestand te publiceren:
php artisan vendor:publish --provider="GrahamCampbell\Throttle\ThrottleServiceProvider"

IP adressen blokkeren

Met deze techniek voor het beperken van de snelheid kun je verzoeken blokkeren van een bepaalde set IP adressen.

  1. Maak om te beginnen de benodigde middleware:
php artisan make:middleware RestrictMiddleware
  1. Open vervolgens het aangemaakte app/Http/Middleware/RestrictMiddleware.php middleware-bestand en vervang de code in de functie handle door het onderstaande fragment. Zorg ervoor dat je use App; toevoegt aan de lijst met imports bovenaan het bestand.
$restrictedIps = ['127.0.0.1', '102.129.158.0'];
if(in_array($request->ip(), $restrictedIps)){
  App::abort(403, 'Request forbidden');
}
return $next($request);
  1. Maak in het bestand app/Http/Kernel.php een alias aan voor deze middleware-app door de array middlewareAliases als volgt aan te passen:
    protected $middlewareAliases = [
    . . .
    'custom.restrict' => \App\Http\Middleware\RestrictMiddleware::class,
    ];
    1. Pas deze middleware vervolgens als volgt toe op de /restricted-route in het bestand routes/api.php en test:
    Route::middleware(['custom.restrict'])->group(function () {
      Route::get('/restricted-route', [BookController::class, 'getBooks']);
    });

    Als het goed werkt, blokkeert deze middleware alle verzoeken van de IP’s in de $restrictedIps array: 127.0.0.1 en 102.129.158.0. Verzoeken van deze IP’s geven een 403 Forbidden respons, zoals hieronder te zien is:

    De Postman-app stuurt een "403 Request Forbidden" respons terug op een GET-verzoek naar de URL
    Een 403 Forbidden respons voor het /restricted-route GET endpoint op Postman

    Zo beperk je verzoeken op IP adres

    Ook kun je verzoeken beperken op basis van het IP adres van de gebruiker.

    1. Pas de Throttle middleware toe op de routes GET en PATCH van het /book endpoint in routes/api.php:
    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. Je moet ook de functie configureRateLimiting in het bestand app/Providers/RouteServiceProvider bijwerken met de middleware die je hebt toegevoegd aan de bovenstaande routes.
    … 
    RateLimiter::for('minute', function (Request $request) {
      return Limit::perMinute(5)->by($request->ip());
    });

    Deze configuratie beperkt verzoeken aan het /book GET endpoint tot 5 per minuut, zoals hieronder getoond.

    De Postman app geeft een "429 Too Many Requests" antwoord op een GET verzoek naar de URL
    Een “429 Too Many Requests” antwoord voor het /book GET endpoint op Postman.

    Hoe te beginnen op basis van gebruikers-ID en sessies

    1. Om rate limits in te schakelen met behulp van de parameters user_id en session, moet je de functie configureRateLimiting in het bestand app/Providers/RouteServiceProvider bijwerken met de volgende aanvullende begrenzers en variabelen:
    ...
    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. Pas ten slotte deze code toe op de routes /book/{id} GET en /book POST in het bestand routes/api.php:
    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']);
    });

    Deze code beperkt verzoeken met respectievelijk user_id en session.

    Extra methoden in Throttle

    Laravel Throttle heeft verschillende aanvullende methoden voor meer controle over je implementatie van de rate limit. Deze methoden zijn onder andere:

    • attempt – Voert een hit uit op het endpoint, verhoogt de hit-telling en geeft een boolean terug die aangeeft of de geconfigureerde hitlimiet is overschreden.
    • hit – Voert een hit uit op de Throttle, verhoogt de hit-telling en retourneert $this om een andere (optionele) method call mogelijk te maken.
    • clear – Zet de Throttle telling terug op nul en geeft $this terug, zodat je desgewenst nog een method call kunt doen.
    • count – Geeft het totale aantal hits voor de Throttle terug.
    • check – Geeft een boolean terug dat aangeeft of de Throttle hitlimiet is overschreden.
    1. Om rate limits met behulp van deze methoden te onderzoeken, maak je een middleware app genaamd CustomMiddleware met behulp van het onderstaande commando:
    php artisan make:middleware CustomMiddleware
    1. Voeg vervolgens de volgende importbestanden toe aan het nieuw aangemaakte middleware-bestand in app/Http/Middleware/CustomMiddleware.php:
    use GrahamCampbell\Throttle\Facades\Throttle;
    use App;
    1. Vervang vervolgens de inhoud van de methode handle door het volgende codefragment:
    $throttler = Throttle::get($request, 5, 1);
    Throttle::attempt($request);
    if(!$throttler->check()){
      App::abort(429, 'Too many requests');
    }
    return $next($request);
    1. Maak in het bestand app/Http/Kernel.php een alias aan voor deze middleware-app door de array middlewareAliases als volgt bij te werken.
    protected $middlewareAliases = [
    . . .
    'custom.throttle' => \App\Http\Middleware\CustomMiddleware::class, 
    ];
    1. Pas vervolgens deze middleware toe op de /custom-route in het bestand routes/api.php:
    Route::middleware(['custom.throttle'])->group(function () {
      Route::get('/custom-route', [BookController::class, 'getBooks']);
    });

    De aangepaste middleware die zojuist is geïmplementeerd controleert of de throttle limiet is overschreden met de check methode. Als de limiet is overschreden, wordt er gereageerd met een 429 foutmelding. Anders wordt het verzoek doorgezet.

    De applicatie deployen op de Kinsta server

    Nu je hebt onderzocht hoe je rate limiting kunt implementeren in een Laravel applicatie, kun je de applicatie deployen naar de Kinsta server om deze wereldwijd toegankelijk te maken.

    1. Begin met het pushen van de bijgewerkte code naar GitHub, GitLab of Bitbucket.
    2. Klik op je Kinsta dashboard op de Dienst toevoegen knop en selecteer Applicatie uit de lijst. Koppel je Git account aan je Kinsta account en selecteer de juiste repository om te deployen.
    3. Onder Basisgegevens geef je de applicatie een naam en kies je het datacenter van je voorkeur. Zorg er ook voor dat je de benodigde applicatie omgevingsvariabelen hebt toegevoegd. Deze komen overeen met de variabelen in je lokale .env bestand: de APP_KEY en de database configuratie variabelen.

    Het gedeelte "Details applicatie" van de module "Applicatie toevoegen" van Kinsta.
    Applicatiedetails op MyKinsta.

    1. Klik op de knop Doorgaan om de omgevingsvariabelen voor het bouwen te selecteren. Je kunt de standaardwaarden laten staan, omdat Kinsta de benodigde parameters automatisch invult.
    2. Op het tabblad Processen kun je de standaardwaarden laten staan of een naam voor je proces invoeren. Je kunt op dit tabblad ook de grootte van de pod en de instantie selecteren.
    3. Op het tabblad Betaling zie je ten slotte een overzicht van je selecties. Voeg de betalingsoptie van je voorkeur toe om het proces af te ronden.
    4. Klik op het tabblad Applicaties om een lijst met uitgerolde applicaties te bekijken.
    5. Klik op de naam van de applicatie om de details van de deployments te bekijken, zoals hieronder getoond. Je kunt de URL van de applicatie gebruiken om toegang te krijgen.

    Het tabblad MyKinsta "Deployments" toont details over de ge deployen applicaties.
    Deployment details in het MyKinsta dashboard.

    De applicatie testen

    1. Gebruik het commando php artisan serve om de applicatie lokaal te testen.

    Dit commando maakt je applicatiebrowser toegankelijk op http://localhost:8000. Je kunt de API endpoints waarnaar je de rate limit hebt geïmplementeerd vanaf hier testen door herhaaldelijk calls te maken om de rate limit functionaliteit te activeren.

    De Kinsta server geeft een Access Forbidden respons omdat je geen configuratiedetails hebt toegevoegd die Kinsta vertellen hoe de applicatie geleverd moet worden. Voeg deze details nu toe.

    1. Maak een .htaccess bestand in de hoofdmap van je app en voeg de volgende code toe aan het bestand:
     <IfModule mod_rewrite.c>
      RewriteEngine On
      RewriteRule ^(.*)$ public/$1 [L]
    </IfModule>
    1. Push deze wijzigingen naar GitHub en Kinsta auto-deploys om de wijziging door te voeren.
    2. Open nu de applicatie met de opgegeven URL en zorg ervoor dat je de Laravel welkomstpagina ziet.

    Je kunt nu de API endpoints testen waarop je rate limiting hebt geïmplementeerd met Postman door herhaalde calls te maken totdat je de geconfigureerde limiet hebt bereikt. Je ontvangt een 429 Too Many Requests respons na het overschrijven van de limiet.

    Samenvatting

    Het integreren van rate limit functionaliteiten in een Laravel API helpt bij het beheersen van de mate waarin gebruikers de resources van een applicatie gebruiken. Rate limiting helpt je om een betrouwbare gebruikerservaring te bieden zonder onder- of overbelasting. Het zorgt er ook voor dat de onderliggende infrastructuur van de applicatie functioneel en efficiënt blijft.

    Je kunt de Kinsta blog bekijken voor meer informatie over andere interessante concepten over Laravel en andere webtechnologieën. De betaalbare en vlekkeloze hostingdiensten worden ten zeerste aanbevolen omdat ze perfect aansluiten bij de behoeften van je applicatie en team.

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.