使用Attribute在Asp.NetCore中实现限流功能

2025年06月15日/ 浏览 2

使用Attribute在Asp.Net Core中实现限流功能

在Web开发中,限流(Rate Limiting)是一种常用的安全措施,旨在防止因高并发请求导致的服务过载。在Asp.Net Core中,我们可以利用自定义的Attribute来轻松实现这一功能。以下将详细介绍如何通过创建一个自定义Attribute来对Web API进行限流操作的步骤。

1. 创建自定义Attribute

首先,我们需要创建一个名为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状态码。

2. 应用Attribute到Controller或Action上

现在,我们可以在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的响应。

3. 测试与验证

通过单元测试或手动测试来验证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项目中实现限流功能。这有助于提高应用的安全性和稳定性,特别是在面对高并发请求时。

picture loss