在 ASP.NET Core 中实现速率限制(Rate Limiting)主要是为了防止接口被高频调用,从而保护服务器资源、提高系统稳定性,并减少恶意攻击(如 DoS/DDoS)的影响。
我给你分成三种常见方式来讲解:
1. 使用 .NET 7+ 内置的 Rate Limiting 中间件
从 .NET 7 开始,ASP.NET Core 提供了官方的 Rate Limiting Middleware,不需要第三方库就能实现限流。
1.1 安装包
如果是 .NET 7 或更高版本,无需额外安装,直接在 Program.cs
中配置。
1.2 示例代码
using Microsoft.AspNetCore.RateLimiting;
using System.Threading.RateLimiting;
var builder = WebApplication.CreateBuilder(args);
// 添加限流策略
builder.Services.AddRateLimiter(options =>
{
// 按 IP 地址限流,每 10 秒允许 5 次请求
options.AddFixedWindowLimiter("fixed", opt =>
{
opt.PermitLimit = 5; // 允许的最大请求数
opt.Window = TimeSpan.FromSeconds(10);// 时间窗口
opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
opt.QueueLimit = 2; // 队列等待的请求数
});
});
var app = builder.Build();
app.UseRateLimiter();
app.MapGet("/test", () => "限流测试接口")
.RequireRateLimiting("fixed"); // 应用到指定接口
app.Run();
运行效果:
- 同一 IP 在 10 秒内只能访问
/test
5 次。 - 超过次数会返回 HTTP 503 Service Unavailable。
2. 使用第三方库(AspNetCoreRateLimit)
如果你的项目是 .NET 6 或更低版本,可以使用 AspNetCoreRateLimit 库。
2.1 安装 NuGet 包
dotnet add package AspNetCoreRateLimit
2.2 添加配置文件(appsettings.json
)
{
"IpRateLimiting": {
"EnableEndpointRateLimiting": true,
"StackBlockedRequests": false,
"RealIpHeader": "X-Real-IP",
"ClientIdHeader": "X-ClientId",
"HttpStatusCode": 429,
"GeneralRules": [
{
"Endpoint": "*:/api/*",
"Period": "10s",
"Limit": 5
}
]
}
}
2.3 注册服务(Program.cs
)
using AspNetCoreRateLimit;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMemoryCache();
builder.Services.Configure<IpRateLimitOptions>(builder.Configuration.GetSection("IpRateLimiting"));
builder.Services.AddInMemoryRateLimiting();
builder.Services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
var app = builder.Build();
app.UseIpRateLimiting();
app.MapGet("/api/test", () => "限流测试");
app.Run();
运行效果:
- 同一 IP 10 秒内只能访问
/api/*
5 次。 - 超过会返回 HTTP 429 Too Many Requests。
3. 自定义中间件实现速率限制
如果想要完全掌控限流逻辑,可以自己写中间件,结合 MemoryCache / Redis 存储请求计数。
示例:基于内存的简单限流中间件
using Microsoft.Extensions.Caching.Memory;
public class RateLimitMiddleware
{
private readonly RequestDelegate _next;
private readonly IMemoryCache _cache;
public RateLimitMiddleware(RequestDelegate next, IMemoryCache cache)
{
_next = next;
_cache = cache;
}
public async Task InvokeAsync(HttpContext context)
{
var ip = context.Connection.RemoteIpAddress?.ToString();
var cacheKey = $"RateLimit_{ip}";
var requestCount = _cache.Get<int>(cacheKey);
if (requestCount >= 5)
{
context.Response.StatusCode = 429;
await context.Response.WriteAsync("请求过于频繁,请稍后再试");
return;
}
_cache.Set(cacheKey, requestCount + 1, TimeSpan.FromSeconds(10));
await _next(context);
}
}
// 注册中间件
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMemoryCache();
var app = builder.Build();
app.UseMiddleware<RateLimitMiddleware>();
app.MapGet("/", () => "Hello World");
app.Run();
对比总结
方法 | 适用版本 | 优点 | 缺点 |
---|---|---|---|
内置 RateLimiter | .NET 7+ | 官方支持、简单易用、性能好 | 不适用于旧版本 |
AspNetCoreRateLimit | .NET 5/6 及以下 | 功能丰富、成熟稳定 | 配置较复杂 |
自定义中间件 | 所有版本 | 灵活可控、可支持分布式(Redis) | 需要自己维护逻辑 |
发表回复