开发随笔记录——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代表什么时间后可再次重新进行访问。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术