2025年06月15日/ 浏览 2
在Web开发中,限流(Rate Limiting)是一种常用的安全措施,旨在防止因高并发请求导致的服务过载。在Asp.Net Core中,我们可以利用自定义的Attribute来轻松实现这一功能。以下将详细介绍如何通过创建一个自定义Attribute来对Web API进行限流操作的步骤。
首先,我们需要创建一个名为RateLimitAttribute
的自定义Attribute。这个Attribute将包含实现限流逻辑所需的所有信息,如每分钟的请求次数限制(Rate Limit)、每次请求的窗口时间(Window Time)等。
“`csharp
using System;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Collections.Generic;
using System.Threading.Tasks;
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class RateLimitAttribute : Attribute, IAsyncActionFilter, IOrderableFilter
{
public int Limit { get; } // 定义每分钟的请求次数限制
public TimeSpan Window { get; } // 定义窗口时间(如1分钟)
public int Order { get; } // 定义执行顺序
public RateLimitAttribute(int limit, TimeSpan window)
{
Limit = limit;
Window = window;
Order = 1; // 默认执行顺序为1,通常放在最前面执行
}
public async Task OnActionExecutionAsync(ActionExecutingContext context)
{
var requests = context.HttpContext.Items["RateLimitRequests"] as Dictionary<string, int?>;
if (requests == null)
{
requests = new Dictionary<string, int?>();
context.HttpContext.Items["RateLimitRequests"] = requests;
}
var key = $"{context.HttpContext.Connection.RemoteIpAddress}:{context.HttpContext.Request.Path}"; // 生成键值用于追踪特定IP和路径的请求
if (!requests.ContainsKey(key))
{
requests[key] = 1; // 首次访问,计数为1
}
else if (requests[key] >= Limit) // 如果达到或超过限制,则返回429 Too Many Requests响应
{
context.Result = new StatusCodeResult(StatusCodes.Status429TooManyRequests);
return; // 停止后续的filter执行和Action执行
}
else // 计数未达到限制,则增加计数器并继续执行Action
{
requests[key] += 1;
}
}
}
“`
这段代码定义了一个RateLimitAttribute
,它实现了IAsyncActionFilter
接口以在Action执行前进行异步操作。我们使用Dictionary<string, int?>
来追踪每个IP和路径的请求次数,当达到预设的Limit
时,返回429状态码。
现在,我们可以在Controller或单个Action上应用这个RateLimitAttribute
来实施限流策略。例如:
csharp
[ApiController]
[Route("[controller]")]
public class ValuesController : ControllerBase
{
[HttpGet]
[RateLimit(Limit = 5, Window = TimeSpan.FromMinutes(1))] // 应用限流策略,每分钟最多5次请求
public IActionResult Get() { return Ok("Hello, World!"); }
}
这样,ValuesController
中的Get
方法将受到每分钟最多5次请求的限制。如果某IP在1分钟内请求超过5次,客户端将收到429 Too Many Requests的响应。
通过单元测试或手动测试来验证RateLimitAttribute
的行为是否符合预期。确保在不同的并发场景下都能正确工作。使用工具如Postman或curl进行多次请求测试是验证其效果的有效方式。
bash # 示例:使用curl进行测试的命令行命令(假设API已部署) curl -i http://localhost:5000/values -H "X-Forwarded-For: 192.168.1.1" -L -o /dev/null -w "%{http_code}"
运行上述命令多次(间隔小于1分钟),观察返回的HTTP状态码是否符合预期的429或200。 ## 4. 扩展与定制 根据项目的具体需求,可以对RateLimitAttribute
进行扩展和定制。例如,为不同的API路径设置不同的限流策略、引入更复杂的算法(如漏桶算法或令牌桶算法)等。此外,还可以考虑集成现有的限流库或服务,如Redis等,以实现更高级的限流功能。 ## 结论 通过创建自定义的RateLimitAttribute
并应用于Controller或Action上,我们可以简单而有效地在Asp.Net Core项目中实现限流功能。这有助于提高应用的安全性和稳定性,特别是在面对高并发请求时。