AspNetCoreRateLimit最省事但需严格遵循中间件顺序:UseRateLimiter()必须在UseRouting()之后、UseEndpoints()之前;默认按IP限流,代理场景需配置RealIPHeader;EnableEndpointRateLimiting启用路由级限流,StackBlockedRequests建议关闭;自定义IClientResolveContributor提取Token或ApiKey;429响应体为空是因异常中间件误吞,非异常需避免捕获。

用 AspNetCoreRateLimit 库最省事,但得配对中间件顺序
直接装 AspNetCoreRateLimit 是当前最主流、维护最勤的方案,它不侵入业务逻辑,靠中间件拦截请求计数。但很多人装完没效果,核心原因就一个:中间件注册顺序错了——UseRateLimiter() 必须放在 UseRouting() 之后、UseEndpoints() 或 UseAuthorization() 之前。
- 错误顺序:
app.UseRateLimiter(); app.UseRouting(); app.UseEndpoints(...);→ 完全不生效 - 正确顺序:
app.UseRouting(); app.UseRateLimiter(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(...); - 它默认基于客户端 IP 做限流,如果 API 走了代理(如 Nginx、Cloudflare),要手动配置
ClientIpHeader或用RealIPHeader解析真实 IP,否则所有请求都算成同一个 IP
IRateLimitConfiguration 配置里,EnableEndpointRateLimiting 和 StackBlockedRequests 很关键
这个接口是整个库的配置入口,两个布尔值最容易被忽略却影响行为逻辑:
-
EnableEndpointRateLimiting = true:开启按路由模板(如GET /api/users/{id})限流;设为false就只按 IP 或客户端 ID 限流,无法区分不同接口 -
StackBlockedRequests = false:建议关掉。开启后,被限流的请求会排队等窗口重置,用户感知就是“卡住几秒才返回 429”,实际反而加重服务压力 - 注意
GeneralRules中的Endpoint字段写法:支持通配符,比如GET:/api/health或*:/api/v1/*,但大小写敏感,get:不行,必须小写get:
自定义 IClientResolveContributor 才能按用户 Token 或 AppKey 限流
默认只认 IP,但真实场景常需按 JWT 用户 ID、API Key 或 Header 中的 X-Api-Key 区分额度。这时必须实现 IClientResolveContributor 接口:
- 重写
ResolveClientAsync方法,从HttpContext.Request.Headers或HttpContext.User.Identity.Name提取标识符 - 返回值不能为 null 或空字符串,否则会被 fallback 到 IP,导致限流失效
- 示例逻辑:
return context.Request.Headers.TryGetValue("X-Api-Key", out var key) ? key.ToString() : "anonymous"; - 注册时别漏掉:
services.AddSingleton<iclientresolvecontributor apikeyclientresolvecontributor>();</iclientresolvecontributor>
限流响应体被吞掉?得配 RateLimitOptions.HttpStatusCode 并检查异常处理中间件
默认返回 429 状态码,但响应体为空——前端只看到“请求失败”,不知道被限流了。想返回 JSON 提示,得两步走:
- 在
RateLimitOptions中设HttpStatusCode = StatusCodes.Status429TooManyRequests(这步其实默认就有,但很多人以为要改) - 真正关键的是:确保没有全局异常处理中间件(如
UseExceptionHandler)把 429 当异常吞掉并返回 500 页面。它不是异常,是正常业务响应 - 若需自定义响应内容,可注入
IRateLimitCounterStore和IRateLimitConfiguration,在中间件里手动写响应体,但代价是绕过原库的自动头字段(X-Rate-Limit-Limit,X-Rate-Limit-Remaining)
IP 解析、中间件顺序、客户端标识提取这三处一错,限流就形同虚设。尤其是多层代理下不调 ForwardedHeaders,本地测得好好的,上线全崩。


















