#define JWT // FIRST ADMIN FIXED SLIDING CONCUR TOKEN FIXED2 JWT #if NEVER #elif FIXED // using Microsoft.AspNetCore.RateLimiting; using System.Threading.RateLimiting; var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); static string GetTicks() => (DateTime.Now.Ticks & 0x11111).ToString("00000"); app.UseRateLimiter(new RateLimiterOptions() .AddFixedWindowLimiter(policyName: "fixed", options => { options.PermitLimit = 4; options.Window = TimeSpan.FromSeconds(12); options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst; options.QueueLimit = 2; })); app.MapGet("/", () => Results.Ok($"Hello {GetTicks()}")) .RequireRateLimiting("fixed"); app.Run(); // #elif FIXED2 // using System.Threading.RateLimiting; using Microsoft.AspNetCore.RateLimiting; using WebRateLimitAuth.Models; var builder = WebApplication.CreateBuilder(args); builder.Services.Configure( builder.Configuration.GetSection(MyRateLimitOptions.MyRateLimit)); var app = builder.Build(); static string GetTicks() => (DateTime.Now.Ticks & 0x11111).ToString("00000"); var myOptions = new MyRateLimitOptions(); app.Configuration.GetSection(MyRateLimitOptions.MyRateLimit).Bind(myOptions); var fixedPolicy = "fixed"; app.UseRateLimiter(new RateLimiterOptions() .AddFixedWindowLimiter(policyName: fixedPolicy, options => { options.PermitLimit = myOptions.permitLimit; options.Window = TimeSpan.FromSeconds(myOptions.window); options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst; options.QueueLimit = myOptions.queueLimit; })); app.MapGet("/", () => Results.Ok($"Hello {GetTicks()}")) .RequireRateLimiting(fixedPolicy); app.Run(); // #elif SLIDING // using Microsoft.AspNetCore.RateLimiting; using System.Threading.RateLimiting; using WebRateLimitAuth.Models; var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); static string GetTicks() => (DateTime.Now.Ticks & 0x11111).ToString("00000"); var myOptions = new MyRateLimitOptions(); app.Configuration.GetSection(MyRateLimitOptions.MyRateLimit).Bind(myOptions); var slidingPolicy = "sliding"; app.UseRateLimiter(new RateLimiterOptions() .AddSlidingWindowLimiter(policyName: slidingPolicy, options => { options.PermitLimit = myOptions.permitLimit; options.Window = TimeSpan.FromSeconds(myOptions.window); options.SegmentsPerWindow = myOptions.segmentsPerWindow; options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst; options.QueueLimit = myOptions.queueLimit; })); app.MapGet("/", () => Results.Ok($"Hello {GetTicks()}")) .RequireRateLimiting(slidingPolicy); app.Run(); // #elif CONCUR // Quicktest 10 users, 9 seconds -> 982 requests, 900 errors // using Microsoft.AspNetCore.RateLimiting; using System.Threading.RateLimiting; using WebRateLimitAuth.Models; var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); static string GetTicks() => (DateTime.Now.Ticks & 0x11111).ToString("00000"); var concurrencyPolicy = "Concurrency"; var myOptions = new MyRateLimitOptions(); app.Configuration.GetSection(MyRateLimitOptions.MyRateLimit).Bind(myOptions); app.UseRateLimiter(new RateLimiterOptions() .AddConcurrencyLimiter(policyName: concurrencyPolicy, options => { options.PermitLimit = myOptions.permitLimit; options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst; options.QueueLimit = myOptions.queueLimit; })); app.MapGet("/", async () => { await Task.Delay(500); return Results.Ok($"Concurrency Limiter {GetTicks()}"); }).RequireRateLimiting(concurrencyPolicy); app.Run(); // #elif TOKEN // Quicktest 20 users, 20 seconds -> 8965 requests 2,250 errors // using Microsoft.AspNetCore.RateLimiting; using System.Threading.RateLimiting; using WebRateLimitAuth.Models; var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); static string GetTicks() => (DateTime.Now.Ticks & 0x11111).ToString("00000"); var tokenPolicy = "token"; var myOptions = new MyRateLimitOptions(); app.Configuration.GetSection(MyRateLimitOptions.MyRateLimit).Bind(myOptions); app.UseRateLimiter(new RateLimiterOptions() .AddTokenBucketLimiter(policyName: tokenPolicy, options => { options.TokenLimit = myOptions.tokenLimit; options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst; options.QueueLimit = myOptions.queueLimit; options.ReplenishmentPeriod = TimeSpan.FromSeconds(myOptions.replenishmentPeriod); options.TokensPerPeriod = myOptions.tokensPerPeriod; options.AutoReplenishment = myOptions.autoReplenishment; })); app.MapGet("/", () => Results.Ok($"Token Limiter {GetTicks()}")) .RequireRateLimiting(tokenPolicy); app.Run(); // #elif FIRST // using System.Globalization; using System.Net; using System.Threading.RateLimiting; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.RateLimiting; using Microsoft.EntityFrameworkCore; using WebRateLimitAuth; using WebRateLimitAuth.Data; using WebRateLimitAuth.Models; var builder = WebApplication.CreateBuilder(args); var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found."); builder.Services.AddDbContext(options => options.UseSqlServer(connectionString)); builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores(); builder.Services.Configure( builder.Configuration.GetSection(MyRateLimitOptions.MyRateLimit)); builder.Services.AddRazorPages(); builder.Services.AddControllersWithViews(); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseMigrationsEndPoint(); } else { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); // // Preceding code removed for brevity. app.UseAuthentication(); app.UseAuthorization(); var userPolicyName = "user"; var helloPolicy = "hello"; var myOptions = new MyRateLimitOptions(); var myConfigSection = app.Configuration.GetSection(MyRateLimitOptions.MyRateLimit); myConfigSection.Bind(myOptions); var options = new RateLimiterOptions() { OnRejected = (context, cancellationToken) => { if (context.Lease.TryGetMetadata(MetadataName.RetryAfter, out var retryAfter)) { context.HttpContext.Response.Headers.RetryAfter = ((int)retryAfter.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo); } context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests; context?.HttpContext?.RequestServices?.GetService()? .CreateLogger("Microsoft.AspNetCore.RateLimitingMiddleware") .LogWarning($"OnRejected: {GetUserEndPoint(context.HttpContext)}"); return new ValueTask(); } } .AddPolicy(helloPolicy) .AddPolicy(userPolicyName, context => { var username = "anonymous user"; if (context.User?.Identity?.IsAuthenticated is true) { username = context.User?.ToString()!; } return RateLimitPartition.GetSlidingWindowLimiter(username, key => new SlidingWindowRateLimiterOptions { PermitLimit = myOptions.permitLimit, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = myOptions.queueLimit, Window = TimeSpan.FromSeconds(myOptions.window), SegmentsPerWindow = myOptions.segmentsPerWindow }); }); options.GlobalLimiter = PartitionedRateLimiter.Create(context => { IPAddress? remoteIPaddress = context?.Connection?.RemoteIpAddress; if (!IPAddress.IsLoopback(remoteIPaddress!)) { return RateLimitPartition.GetTokenBucketLimiter (remoteIPaddress!, key => new TokenBucketRateLimiterOptions { TokenLimit = myOptions.tokenLimit2, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = myOptions.queueLimit, ReplenishmentPeriod = TimeSpan.FromSeconds(myOptions.replenishmentPeriod), TokensPerPeriod = myOptions.tokensPerPeriod, AutoReplenishment = myOptions.autoReplenishment }); } else { return RateLimitPartition.GetNoLimiter(IPAddress.Loopback); } }); app.UseRateLimiter(options); app.MapRazorPages().RequireRateLimiting(userPolicyName); app.MapDefaultControllerRoute(); static string GetUserEndPoint(HttpContext context) => $"User {context.User?.Identity?.Name ?? "Anonymous"} endpoint:{context.Request.Path}" + $" {context.Connection.RemoteIpAddress}"; static string GetTicks() => (DateTime.Now.Ticks & 0x11111).ToString("00000"); app.MapGet("/a", (HttpContext context) => $"{GetUserEndPoint(context)} {GetTicks()}") .RequireRateLimiting(userPolicyName); app.MapGet("/b", (HttpContext context) => $"{GetUserEndPoint(context)} {GetTicks()}") .RequireRateLimiting(helloPolicy); app.MapGet("/c", (HttpContext context) => $"{GetUserEndPoint(context)} {GetTicks()}"); app.Run(); // // #elif ADMIN // using System.Threading.RateLimiting; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.RateLimiting; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Primitives; using WebRateLimitAuth.Data; using WebRateLimitAuth.Models; var builder = WebApplication.CreateBuilder(args); var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found."); builder.Services.AddDbContext(options => options.UseSqlServer(connectionString)); builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores(); builder.Services.AddRazorPages(); builder.Services.AddControllersWithViews(); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseMigrationsEndPoint(); } else { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); // var getPolicyName = "get"; var postPolicyName = "post"; var myOptions = new MyRateLimitOptions(); app.Configuration.GetSection(MyRateLimitOptions.MyRateLimit).Bind(myOptions); app.UseRateLimiter(new RateLimiterOptions() .AddConcurrencyLimiter(policyName: getPolicyName, options => { options.PermitLimit = myOptions.permitLimit; options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst; options.QueueLimit = myOptions.queueLimit; }) .AddPolicy(policyName: postPolicyName, partitioner: httpContext => { string userName = httpContext?.User?.Identity?.Name ?? string.Empty; if (!StringValues.IsNullOrEmpty(userName)) { return RateLimitPartition.GetTokenBucketLimiter(userName, key => new TokenBucketRateLimiterOptions { TokenLimit = myOptions.tokenLimit2, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = myOptions.queueLimit, ReplenishmentPeriod = TimeSpan.FromSeconds(myOptions.replenishmentPeriod), TokensPerPeriod = myOptions.tokensPerPeriod, AutoReplenishment = myOptions.autoReplenishment }); } else { return RateLimitPartition.GetTokenBucketLimiter("Anon", key => new TokenBucketRateLimiterOptions { TokenLimit = myOptions.tokenLimit, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = myOptions.queueLimit, ReplenishmentPeriod = TimeSpan.FromSeconds(myOptions.replenishmentPeriod), TokensPerPeriod = myOptions.tokensPerPeriod, AutoReplenishment = true }); } })); // static string GetUserEndPointMethod(HttpContext context) => $"Hello {context.User?.Identity?.Name ?? "Anonymous"} " + $"Endpoint:{context.Request.Path} Method: {context.Request.Method}"; app.MapGet("/test", (HttpContext context) => $"{GetUserEndPointMethod(context)}") .RequireRateLimiting(getPolicyName); app.MapRazorPages().RequireRateLimiting(getPolicyName) .RequireRateLimiting(postPolicyName); app.MapDefaultControllerRoute(); app.Run(); // #elif JWT // using System.Threading.RateLimiting; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.RateLimiting; using Microsoft.Extensions.Primitives; using WebRateLimitAuth.Models; var builder = WebApplication.CreateBuilder(args); builder.Services.AddAuthorization(); builder.Services.AddAuthentication("Bearer").AddJwtBearer(); var app = builder.Build(); app.UseAuthorization(); var jwtPolicyName = "jwt"; var myOptions = new MyRateLimitOptions(); app.Configuration.GetSection(MyRateLimitOptions.MyRateLimit).Bind(myOptions); var options = new RateLimiterOptions() { RejectionStatusCode = StatusCodes.Status429TooManyRequests } .AddPolicy(policyName: jwtPolicyName, partitioner: httpContext => { var accessToken = httpContext?.Features?.Get()? .AuthenticateResult?.Properties?.GetTokenValue("access_token")?.ToString() ?? string.Empty; if (!StringValues.IsNullOrEmpty(accessToken)) { return RateLimitPartition.GetTokenBucketLimiter(accessToken, key => new TokenBucketRateLimiterOptions { TokenLimit = myOptions.tokenLimit2, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = myOptions.queueLimit, ReplenishmentPeriod = TimeSpan.FromSeconds(myOptions.replenishmentPeriod), TokensPerPeriod = myOptions.tokensPerPeriod, AutoReplenishment = myOptions.autoReplenishment }); } else { return RateLimitPartition.GetTokenBucketLimiter("Anon", key => new TokenBucketRateLimiterOptions { TokenLimit = myOptions.tokenLimit, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = myOptions.queueLimit, ReplenishmentPeriod = TimeSpan.FromSeconds(myOptions.replenishmentPeriod), TokensPerPeriod = myOptions.tokensPerPeriod, AutoReplenishment = true }); } }); app.UseRateLimiter(options); app.MapGet("/", () => "Hello, World!"); app.MapGet("/jwt", (HttpContext context) => $"Hello {GetUserEndPointMethod(context)}") .RequireRateLimiting(jwtPolicyName) .RequireAuthorization(); app.MapPost("/post", (HttpContext context) => $"Hello {GetUserEndPointMethod(context)}") .RequireRateLimiting(jwtPolicyName) .RequireAuthorization(); app.Run(); static string GetUserEndPointMethod(HttpContext context) => $"Hello {context.User?.Identity?.Name ?? "Anonymous"} " + $"Endpoint:{context.Request.Path} Method: {context.Request.Method}"; // #endif