基于Microsoft.AspNetCore.RateLimiting中间件实现用户级限流方案咨询
ASP.NET 7 基于自定义认证用户的限流实现方案
核心思路
无需为每个用户动态单独定义限流策略,直接利用RateLimiting中间件的**分区限流(PartitionedRateLimiter)**功能,以已认证用户的唯一标识(如用户ID)作为分区键,每个用户会自动拥有独立的限流计数,复用统一的限流规则即可。
具体实现步骤
1. 注册限流服务
在Program.cs中配置RateLimiting服务,通过PartitionedRateLimiter.Create创建基于用户ID的分区限流规则。需确保自定义认证后,HttpContext.User能获取到用户ID(示例中通过ClaimTypes.NameIdentifier获取)。
builder.Services.AddRateLimiter(options => { // 定义每个用户的限流规则:示例为1分钟最多10次请求 options.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, string>(httpContext => { var userId = httpContext.User.FindFirstValue(ClaimTypes.NameIdentifier); // 处理未认证用户:可选择不限流、严格限流或直接拒绝 if (string.IsNullOrEmpty(userId)) { // 示例:给未认证用户设置更严格的限流 return RateLimitPartition.GetFixedWindowLimiter("unauthenticated", _ => new FixedWindowRateLimiterOptions { PermitLimit = 5, Window = TimeSpan.FromMinutes(1), QueueLimit = 1 }); } // 为每个已认证用户创建独立限流分区,复用统一规则 return RateLimitPartition.GetFixedWindowLimiter(userId, _ => new FixedWindowRateLimiterOptions { PermitLimit = 10, Window = TimeSpan.FromMinutes(1), QueueProcessingOrder = QueueProcessingOrder.OldestFirst, QueueLimit = 2 }); }); // 自定义限流触发后的响应 options.OnRejected = async (context, token) => { context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests; await context.HttpContext.Response.WriteAsync("请求过于频繁,请稍后再试。", token); }; });
2. 启用限流中间件
在Program.cs的管道中,将限流中间件放在认证中间件之后,确保能获取到已认证用户的信息:
// 先启用自定义认证中间件 app.UseAuthentication(); app.UseAuthorization(); // 启用限流中间件 app.UseRateLimiter(); // 后续路由、控制器等中间件 app.MapControllers();
3. 适配自定义认证逻辑
确保自定义认证成功后,将用户ID添加到ClaimsPrincipal的Claims集合中,示例代码如下:
// 自定义认证成功后构建ClaimsPrincipal var claims = new List<Claim> { new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()), // 其他业务相关Claims }; var identity = new ClaimsIdentity(claims, "CustomAuthScheme"); var principal = new ClaimsPrincipal(identity);
方案说明
- 该方案无需动态生成用户级策略,中间件会自动按分区键(用户ID)维护每个用户的限流计数,性能和扩展性更优。
- 可根据业务需求替换限流算法,比如滑动窗口(
SlidingWindowRateLimiter)、令牌桶(TokenBucketRateLimiter),只需替换对应的GetXXXLimiter方法即可。 - 未认证用户可单独配置规则,避免恶意未授权请求占用资源。
内容的提问来源于stack exchange,提问作者kalitsov
相关产品推荐
相关产品推荐

