浅析如何在 ASP.NET Core中实现速率限制

ASP.NET教程 2025-08-27

目录

  • 1.使用自定义中间件实现速率限制
    • 1.1 实现速率限制中间件
    • 1.2 注册中间件
  • 2.使用第三方库实现速率限制
    • 3.使用分布式缓存实现速率限制
      • 3.1 使用 Redis 实现速率限制
      • 3.2 注册中间件
    • 4.总结

      在 ASP.NET Core 中实现速率限制(Rate Limiting)中间件可以帮助你控制客户端对 API 的请求频率,防止滥用和过载。速率限制通常用于保护服务器资源,确保服务的稳定性和可用性。

      ASP.NET Core 本身并没有内置的速率限制中间件,但你可以通过自定义中间件或使用第三方库来实现速率限制。以下是实现速率限制的几种常见方法:

      1.使用自定义中间件实现速率限制

      你可以通过自定义中间件来实现速率限制。以下是一个简单的实现示例:

      1.1 实现速率限制中间件

      using Microsoft.AspNetCore.Http;
      using System.Collections.Concurrent;
      using System.Threading.Tasks;
      
      public class RateLimitingMiddleware
      {
          private readonly RequestDelegate _next;
          private readonly int _maxRequests; // 每分钟允许的最大请求数
          private readonly ConcurrentDictionarystring, RateLimiter _rateLimiters;
      
          public RateLimitingMiddleware(RequestDelegate next, int maxRequests)
          {
              _next = next;
              _maxRequests = maxRequests;
              _rateLimiters = new ConcurrentDictionarystring, RateLimiter();
          }
      
          public async Task InvokeAsync(HttpContext context)
          {
              // 获取客户端的唯一标识(例如 IP 地址)
              var clientId = context.Connection.RemoteIpAddress.ToString();
      
              // 获取或创建速率限制器
              var rateLimiter = _rateLimiters.GetOrAdd(clientId, _ = new RateLimiter(_maxRequests));
      
              if (rateLimiter.AllowRequest())
              {
                  await _next(context);
              }
              else
              {
                  context.Response.StatusCode = StatusCodes.Status429TooManyRequests;
                  await context.Response.WriteAsync("请求太多。请稍后再试.");
              }
          }
      }
      
      public class RateLimiter
      {
          private readonly int _maxRequests;
          private int _requestCount;
          private DateTime _windowStart;
      
          public RateLimiter(int maxRequests)
          {
              _maxRequests = maxRequests;
              _requestCount = 0;
              _windowStart = DateTime.UtcNow;
          }
      
          public bool AllowRequest()
          {
              var now = DateTime.UtcNow;
      
              // 如果当前时间窗口已过期,重置计数器
              if ((now - _windowStart).TotalSeconds  60)
              {
                  _requestCount = 0;
                  _windowStart = now;
              }
      
              // 检查请求是否超出限制
              if (_requestCount  _maxRequests)
              {
                  _requestCount++;
                  return true;
              }
      
              return false;
          }
      }
      

      1.2 注册中间件

      在Startup.cs中注册中间件:

      public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
      {
          app.UseMiddlewareRateLimitingMiddleware(10); // 每分钟最多 10个请求
      
          app.UseRouting();
      
          app.UseEndpoints(endpoints =
                           {
                               endpoints.MapControllers();
                           });
      }
      

      2.使用第三方库实现速率限制

      如果你不想自己实现速率限制逻辑,可以使用一些现成的第三方库,例如:

      AspNetCoreRateLimit

      AspNetCoreRateLimit 是一个流行的 ASP.NET Core 速率限制库,支持 IP 地址、客户端 ID 和端点级别的速率限制。

      安装

      通过 NuGet 安装:

      dotnet add package AspNetCoreRateLimit
      

      配置

      在Startup.cs中配置速率限制:

      public void ConfigureServices(IServiceCollection services)
      {
          // 添加内存缓存
          services.AddMemoryCache();
      
          // 配置速率限制
          services.ConfigureIpRateLimitOptions(Configuration.GetSection("IpRateLimiting"));
          services.AddSingletonIIpPolicyStore, MemoryCacheIpPolicyStore();
          services.AddSingletonIRateLimitCounterStore, MemoryCacheRateLimitCounterStore();
          services.AddSingletonIRateLimitConfiguration, RateLimitConfiguration();
          services.AddSingletonIProcessingStrategy, AsyncKeyLockProcessingStrategy();
          services.AddInMemoryRateLimiting();
      }
      
      public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
      {
          app.UseIpRateLimiting();
      
          app.UseRouting();
      
          app.UseEndpoints(endpoints =
                           {
                               endpoints.MapControllers();
                           });
      }
      

      配置文件

      在appsettings.json中添加速率限制配置:

      {
          "IpRateLimiting": {
              "EnableEndpointRateLimiting": true,
              "StackBlockedRequests": false,
              "RealIpHeader": "X-Real-IP",
              "ClientIdHeader": "X-ClientId",
              "GeneralRules": [
                  {
                      "Endpoint": "*",
                      "Period": "1m",
                      "Limit": 10
                      }
              ]
          }
      }
      

      3.使用分布式缓存实现速率限制

      如果你的应用是分布式的(例如部署在 Kubernetes 或多个服务器上),可以使用分布式缓存(如 Redis)来实现速率限制。

      3.1 使用 Redis 实现速率限制

      你可以使用 Redis 来存储每个客户端的请求计数。以下是一个简单的示例:

      using Microsoft.AspNetCore.Http;
      using StackExchange.Redis;
      using System.Threading.Tasks;
      
      public class RedisRateLimitingMiddleware
      {
          private readonly RequestDelegate _next;
          private readonly int _maxRequests;
          private readonly ConnectionMultiplexer _redis;
      
          public RedisRateLimitingMiddleware(RequestDelegate next, int maxRequests, ConnectionMultiplexer redis)
          {
              _next = next;
              _maxRequests = maxRequests;
              _redis = redis;
          }
      
          public async Task InvokeAsync(HttpContext context)
          {
              var clientId = context.Connection.RemoteIpAddress.ToString();
              var db = _redis.GetDatabase();
      
              var key = $"rate_limit:{clientId}";
              var requestCount = await db.StringIncrementAsync(key);
      
              if (requestCount == 1)
              {
                  await db.KeyExpireAsync(key, TimeSpan.FromMinutes(1));
              }
      
              if (requestCount  _maxRequests)
              {
                  context.Response.StatusCode = StatusCodes.Status429TooManyRequests;
                  await context.Response.WriteAsync("请求太多。请稍后再试.");
              }
              else
              {
                  await _next(context);
              }
          }
      }
      

      3.2 注册中间件

      在Startup.cs中注册中间件:

      public void ConfigureServices(IServiceCollection services)
      {
          services.AddSingletonConnectionMultiplexer(ConnectionMultiplexer.Connect("localhost:6379"));
      }
      
      public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
      {
          app.UseMiddlewareRedisRateLimitingMiddleware(10); // 每分钟最多 10个请求
      
          app.UseRouting();
      
          app.UseEndpoints(endpoints =
                           {
                               endpoints.MapControllers();
                           });
      }
      

      4.总结

      在 ASP.NET Core 中实现速率限制有多种方式:

      • 自定义中间件:适合简单的场景,但需要自己实现逻辑。
      • 第三方库:如 AspNetCoreRateLimit,提供了更强大的功能和灵活性。
      • 分布式缓存:如 Redis,适合分布式环境。

      根据你的需求选择合适的方式,确保你的 API 能够有效防止滥用和过载。

      到此这篇关于浅析如何在 ASP.NET Core中实现速率限制的文章就介绍到这了,更多相关ASP.NET Core速率限制内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

      您可能感兴趣的文章:
      • asp.netcore服务限制堆内存大小的操作方法
      • Asp.net Core 如何设置黑白名单(路由限制)
      • ASP.NET Core 3.x 并发限制的实现代码
      • 在ASP.NET MVC下限制同一个IP地址单位时间间隔内的请求次数的解决方法
      • ASP.NETMVC限制同一个IP地址单位时间间隔内的请求次数
      • ASP.NET MVC实现单个图片上传、限制图片格式与大小并在服务端裁剪图片