在 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 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();
                     });
}

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
                }
        ]
    }
}

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();
                     });
}

4. 总结

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

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

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

如何在 ASP.NET Core 中实现速率限制?的更多相关文章

  1. 如何在ASP.NET Core中实现CORS跨域

    注:下载本文的完整代码示例请访问 > How to enable CORS(Cross-origin resource sharing) in ASP.NET Core 如何在ASP.NET C ...

  2. 如何在ASP.NET Core中实现一个基础的身份认证

    注:本文提到的代码示例下载地址> How to achieve a basic authorization in ASP.NET Core 如何在ASP.NET Core中实现一个基础的身份认证 ...

  3. 如何在ASP.NET Core中应用Entity Framework

    注:本文提到的代码示例下载地址> How to using Entity Framework DB first in ASP.NET Core 如何在ASP.NET Core中应用Entity ...

  4. [转]如何在ASP.NET Core中实现一个基础的身份认证

    本文转自:http://www.cnblogs.com/onecodeonescript/p/6015512.html 注:本文提到的代码示例下载地址> How to achieve a bas ...

  5. 如何在ASP.NET Core中使用Azure Service Bus Queue

    原文:USING AZURE SERVICE BUS QUEUES WITH ASP.NET CORE SERVICES 作者:damienbod 译文:如何在ASP.NET Core中使用Azure ...

  6. 如何在ASP.NET Core中自定义Azure Storage File Provider

    文章标题:如何在ASP.NET Core中自定义Azure Storage File Provider 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p ...

  7. 如何在ASP.NET Core中使用JSON Patch

    原文: JSON Patch With ASP.NET Core 作者:.NET Core Tutorials 译文:如何在ASP.NET Core中使用JSON Patch 地址:https://w ...

  8. [翻译] 如何在 ASP.Net Core 中使用 Consul 来存储配置

    [翻译] 如何在 ASP.Net Core 中使用 Consul 来存储配置 原文: USING CONSUL FOR STORING THE CONFIGURATION IN ASP.NET COR ...

  9. [译]如何在ASP.NET Core中实现面向切面编程(AOP)

    原文地址:ASPECT ORIENTED PROGRAMMING USING PROXIES IN ASP.NET CORE 原文作者:ZANID HAYTAM 译文地址:如何在ASP.NET Cor ...

  10. 如何在 ASP.Net Core 中使用 Serilog

    记录日志的一个作用就是方便对应用程序进行跟踪和排错调查,在实际应用上都是引入 日志框架,但如果你的 日志文件 包含非结构化的数据,那么查询起来将是一个噩梦,所以需要在记录日志的时候采用结构化方式. 将 ...

随机推荐

  1. 2.11 Linux四种远程管理协议

    提到远程管理,通常指的是远程管理服务器,而非个人计算机.个人计算机可以随时拿来用,服务器通常放置在机房中,用户无法直接接触到服务器硬件,只能采用远程管理的方式. 远程管理,实际上就是计算机(服务器)之 ...

  2. Groovy基础语法!

    Groovy是什么语言? Groovy是一种基于JVM(Java虚拟机)的敏捷开发语言,它结合了Python.Ruby和Smalltalk的许多强大的特性,Groovy 代码能够与 Java 代码很好 ...

  3. 这可能是最好的Spring教程!即便无基础也能看懂的入门Spring,仍在持续更新。

    开启这样一个系列的原因 这一段时间都在学spring,但是在学习的过程中一直都很难找到一个通俗易懂,又带了学习体系的文章教程,很多地方都不懂,需要自己去慢慢查询和理解,感觉学起来很耗时,所以我自己就像 ...

  4. 配置NVIDIA Container Runtime和容器运行GPUStack教程

    GPUStack 是一个设计用于运行大模型的开源 GPU 集群管理器,提供私有部署的大模型服务,支持大语言模型.Embedding 文本嵌入模型.Reranker 重排序模型.Vision 多模态模型 ...

  5. CommonsCollections7(基于ysoserial)

    环境准备 JDK1.8(8u421)我以本地的JDK8版本为准.commons-collections(3.x 4.x均可这里使用3.2版本) cc3.2: <dependency> &l ...

  6. kubernetesApi官方文档

    kubernetes API官方文档在github上经常打不开,于是就放在博客了,以下内容均复制于github All URIs are relative to http://localhost Me ...

  7. (Redis基础教程之十一) 如何使Redis中的Key过期

    介绍 Redis是一个开源的内存中键值数据存储.默认情况下,Redis密钥是_永久性_的,这意味着Redis服务器将继续存储它们,除非手动将其删除.但是,在某些情况下,您已经设置了密钥,但是您知道要在 ...

  8. 看不懂来打我,Vue3的watch是如何实现监听的?

    前言 watch这个API大家都很熟悉,今天这篇文章欧阳来带你搞清楚Vue3的watch是如何实现对响应式数据进行监听的.注:本文使用的Vue版本为3.5.13. 关注公众号:[前端欧阳],给自己一个 ...

  9. golang之json.RawMessage

    RawMessage 具体来讲是 json 库中定义的一个类型.它实现了 Marshaler 接口以及 Unmarshaler 接口,以此来支持序列化的能力.注意上面我们引用 官方 doc 的说明. ...

  10. Nuxt.js 应用中的 close 事件钩子

    title: Nuxt.js 应用中的 close 事件钩子 date: 2024/12/2 updated: 2024/12/2 author: cmdragon excerpt: close 钩子 ...