Rate Limiting
Le Rate Limiting (limitation de débit) est une technique essentielle pour protéger une API contre les abus, les attaques par déni de service (DoS) et pour gérer équitablement les ressources du serveur.
Cela consiste à limiter le nombre de requêtes qu’un client (identifié par son IP ou son ID utilisateur) peut effectuer dans un intervalle de temps donné.
Le concept
Imaginez un tourniquet à l’entrée d’un métro. Si tout le monde essaie de passer en même temps, ça bloque. Le Rate Limiting, c’est comme imposer un délai d’une seconde entre chaque passage.
En ASP.NET Core, depuis la version 7, un middleware de Rate Limiting est intégré nativement.
Configuration
1. Enregistrement du service
Dans Program.cs, on configure les règles (policies) de limitation.
Il existe plusieurs algorithmes. Le plus courant est la Fixed Window (Fenêtre fixe). Par exemple : “Max 10 requêtes par minute”.
using Microsoft.AspNetCore.RateLimiting;
using System.Threading.RateLimiting;
// ...
builder.Services.AddRateLimiter(options =>
{
// Rejet avec le code 429 Too Many Requests
options.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
// Définition d'une politique nommée "fixed"
options.AddFixedWindowLimiter("fixed", limiterOptions =>
{
limiterOptions.PermitLimit = 10; // Max 10 requêtes
limiterOptions.Window = TimeSpan.FromSeconds(10); // Toutes les 10 secondes
limiterOptions.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
limiterOptions.QueueLimit = 0; // Pas de file d'attente
});
});
2. Activation du middleware
Comme toujours, il faut l’ajouter au pipeline dans Program.cs.
app.UseRateLimiter();
Utilisation
Une fois configuré, vous pouvez appliquer le Rate Limiting sur vos contrôleurs ou vos routes avec l’attribut [EnableRateLimiting].
[ApiController]
[Route("api/[controller]")]
[EnableRateLimiting("fixed")] // Applique la politique "fixed" à tout le contrôleur
public class GameController : ControllerBase
{
// ...
}
Vous pouvez aussi désactiver le rate limiting sur une action spécifique :
[DisableRateLimiting]
[HttpGet("status")]
public IActionResult GetStatus()
{
return Ok("Online");
}
Rate Limiting par Utilisateur
L’exemple précédent limite tout le monde globalement ou par IP (selon la configuration par défaut). Pour limiter par utilisateur connecté, il faut utiliser le partitionnement.
options.AddPolicy("user-limit", context =>
{
// On récupère le nom de l'utilisateur (ou son IP s'il n'est pas connecté)
var username = context.User.Identity?.Name ?? context.Connection.RemoteIpAddress?.ToString();
return RateLimitPartition.GetFixedWindowLimiter(username, _ => new FixedWindowRateLimiterOptions
{
PermitLimit = 5,
Window = TimeSpan.FromSeconds(10)
});
});
Cette configuration crée un compteur séparé pour chaque utilisateur. Alice peut faire 5 requêtes, et Bob peut aussi en faire 5, sans qu’ils se bloquent mutuellement.