A login form without limits invites brute-force attempts; a public API without limits can be saturated by a single client. ASP.NET Core includes a rate limiting middleware configurable per endpoint.
Configuration
builder.Services.AddRateLimiter(o =>
{
o.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
o.AddPolicy("login", ctx => RateLimitPartition.GetFixedWindowLimiter(
ctx.Connection.RemoteIpAddress?.ToString() ?? "unknown",
_ => new FixedWindowRateLimiterOptions
{
PermitLimit = 5,
Window = TimeSpan.FromMinutes(1)
}));
o.AddTokenBucketLimiter("api", t =>
{
t.TokenLimit = 100;
t.TokensPerPeriod = 20;
t.ReplenishmentPeriod = TimeSpan.FromSeconds(10);
});
});
var app = builder.Build();
app.UseRateLimiter();
Applying the policies
app.MapPost("/login", Login).RequireRateLimiting("login");
app.MapGroup("/api").RequireRateLimiting("api");
With Razor Pages and MVC you use the [EnableRateLimiting("login")] attribute on the page or controller.
Available algorithms
- Fixed window: N requests per interval; simple and predictable.
- Sliding window: avoids spikes straddling two windows.
- Token bucket: allows short bursts while keeping a sustainable average.
- Concurrency: limits simultaneous requests, useful for heavy operations.
Behind a proxy
If the application sits behind IIS, a load balancer or a CDN, the client IP address arrives in forwarded headers: configure UseForwardedHeaders before the rate limiter, otherwise every user will look like the same client.
Comments (0)
No comments yet.