开发随笔记录——ASP.NET Core自定义中间件通过本地缓存实现客户端IP访问限流

声明:本文章中框架使用ASP.NET Core 3.1

首先,在appsettings.json中配置该中间件中需要使用的配置信息,如下:

  "RateLimiting": {
    "Count": 5, //限定时间内能够访问的次数
    "Seconds": 60 //达到访问上限后多少秒后可以重新访问
  }

其次,创建RequestRateLimitingMiddleware实现类,代码如下:

复制代码
public class RequestRateLimitingMiddleware
    {
        //限定时间内能够访问的次数
        private readonly int Limit;
        //达到访问上限后多少秒后可以重新访问
        private readonly int Seconds;

        private readonly RequestDelegate next;

        private readonly IMemoryCache requestStore;

        public RequestRateLimitingMiddleware(RequestDelegate next, IConfiguration Configuration, IMemoryCache requestStore)
        {
            this.next = next;
            this.requestStore = requestStore;
            Limit = Configuration.GetValue<int>("RateLimiting:Count");
            Seconds = Configuration.GetValue<int>("RateLimiting:Seconds");
        }
       
        public async Task Invoke(HttpContext context)
        {
            var requestKey = $"{context.Connection.RemoteIpAddress.MapToIPv4()}-{context.Request.Method}-{context.Request.Path}";
            int hitCount = 0;
            var cacheOptions = new MemoryCacheEntryOptions() {
                AbsoluteExpiration = DateTime.Now.AddSeconds(Seconds)
            };

            if (requestStore.TryGetValue(requestKey, out hitCount))
            {
                if (hitCount < Limit)
                {
                    await ProcessRequest(context, requestKey, hitCount, cacheOptions);
                }
                else
                {
                    context.Response.Headers["X-RateLimit-RetryAfter"] = cacheOptions.AbsoluteExpiration?.ToString("yyyy-MM-dd HH:mm:ss");
                    context.Response.StatusCode = StatusCodes.Status429TooManyRequests;
                }
            }
            else
            {
                await ProcessRequest(context, requestKey, hitCount, cacheOptions);
            }
        }
        private async Task ProcessRequest(HttpContext context,string requestKey,int hitCount,MemoryCacheEntryOptions cacheOptions)
        {
            hitCount++;
            requestStore.Set(requestKey, hitCount, cacheOptions);
            context.Response.Headers["X-RateLimit-Limit"] = Limit.ToString();
            context.Response.Headers["X-RateLimit-Remaining"] = (Limit - hitCount).ToString();
            await next(context);
        }
    }
复制代码

稍后,在Startup.cs文件中,对自定义的中间件进行注册使用,如下:

复制代码
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseAuthorization();

            app.UseMiddleware<RequestRateLimitingMiddleware>();
            
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
复制代码

最后,就可以进行测试了,测试结果对比如下:

提示:X-RateLimit-Limit代表在限定时间内可访问次数上限。

X-RateLimit-Remaining代表在限定时间内已经访问了多少次。
    X-RateLimit-RetryAfter代表什么时间后可再次重新进行访问。
posted @   苏瑾~  阅读(170)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示