English 简体中文 繁體中文 한국 사람 日本語 Deutsch русский بالعربية TÜRKÇE português คนไทย french
查看: 6|回复: 0

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

[复制链接]
查看: 6|回复: 0

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

[复制链接]
查看: 6|回复: 0

316

主题

0

回帖

958

积分

高级会员

积分
958
自动销售设备

316

主题

0

回帖

958

积分

高级会员

积分
958
2025-2-6 17:54:36 | 显示全部楼层 |阅读模式
在 ASP.NET Core 中实现速率限制(Rate Limiting)中间件可以帮助你控制客户端对 API 的请求频率,防止滥用和过载。速率限制通常用于保护服务器资源,确保服务的稳定性和可用性。
ASP.NET Core 本身并没有内置的速率限制中间件,但你可以通过自定义中间件或使用第三方库来实现速率限制。以下是实现速率限制的几种常见方法:
<hr>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 ConcurrentDictionary<string, RateLimiter> _rateLimiters;    public RateLimitingMiddleware(RequestDelegate next, int maxRequests)    {        _next = next;        _maxRequests = maxRequests;        _rateLimiters = new ConcurrentDictionary<string, 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.UseMiddleware<RateLimitingMiddleware>(10); // 每分钟最多 10个请求    app.UseRouting();    app.UseEndpoints(endpoints =>                     {                         endpoints.MapControllers();                     });}<hr>2. 使用第三方库实现速率限制

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

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

通过 NuGet 安装:
dotnet add package AspNetCoreRateLimit配置

在 Startup.cs 中配置速率限制:
public void ConfigureServices(IServiceCollection services){    // 添加内存缓存    services.AddMemoryCache();    // 配置速率限制    services.Configure<IpRateLimitOptions>(Configuration.GetSection("IpRateLimiting"));    services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>();    services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();    services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();    services.AddSingleton<IProcessingStrategy, 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                }        ]    }}<hr>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.AddSingleton<ConnectionMultiplexer>(ConnectionMultiplexer.Connect("localhost:6379"));}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){    app.UseMiddleware<RedisRateLimitingMiddleware>(10); // 每分钟最多 10个请求    app.UseRouting();    app.UseEndpoints(endpoints =>                     {                         endpoints.MapControllers();                     });}<hr>4. 总结

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

  • 自定义中间件:适合简单的场景,但需要自己实现逻辑。
  • 第三方库:如 AspNetCoreRateLimit,提供了更强大的功能和灵活性。
  • 分布式缓存:如 Redis,适合分布式环境。
根据你的需求选择合适的方式,确保你的 API 能够有效防止滥用和过载。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

316

主题

0

回帖

958

积分

高级会员

积分
958

QQ|智能设备 | 粤ICP备2024353841号-1

GMT+8, 2025-3-10 15:37 , Processed in 0.858089 second(s), 27 queries .

Powered by 智能设备

©2025

|网站地图