C# AspNetCoreRateLimit在匹配规则时不使用查询参数
我正在使用Asp.NETCore2.2WebAPI库。如图所示,我在C# AspNetCoreRateLimit在匹配规则时不使用查询参数,c#,asp.net-core,throttling,rate-limiting,C#,Asp.net Core,Throttling,Rate Limiting,我正在使用Asp.NETCore2.2WebAPI库。如图所示,我在Startup.cs中使用了IpRateLimiting及其默认设置 我有带查询参数的API端点,它用于http GET查询,如下所示(请参见参数startDate和stopDate): 我只想将唯一的请求(具有唯一参数组合)限制为每小时5个请求。因此,例如,以下场景应在1小时内实现: 5 times: GET "https://host/api/endpoint/path?startDate=2020-04-04&st
Startup.cs
中使用了IpRateLimiting及其默认设置
我有带查询参数的API端点,它用于http GET查询,如下所示(请参见参数startDate
和stopDate
):
我只想将唯一的请求(具有唯一参数组合)限制为每小时5个请求。因此,例如,以下场景应在1小时内实现:
5 times: GET "https://host/api/endpoint/path?startDate=2020-04-04&stopDate=2020-04-04"
5 times: GET "https://host/api/endpoint/path?startDate=2020-04-05&stopDate=2020-04-05"
问题是,无论参数如何,我每小时只能发送总计5个请求
以下是我在appsettings.json中的IpRateLimiting设置
"IpRateLimiting": {
"EnableEndpointRateLimiting": true,
"StackBlockedRequests": false,
"RealIPHeader": "X-Real-IP",
"ClientIdHeader": "X-ClientId",
"HttpStatusCode": 429,
"GeneralRules": [
{
"Endpoint": "*:/api/endpoint/path",
"Period": "1h",
"Limit": 5
}
]
}
请注意,我不想改变@Yongqing Yu在正确回答中提出的端点路由,因为有很多API客户端使用我的API,我不想引入任何突破性的更改。您可以
更改相应操作的路径
,并将参数直接转换为路径的一部分,如'https://host/api/endpoint/path/2020-04-04/2020-04-04“
,因此,一般规则
中的端点
可以通过*
满足您的条件
你可以参考
这是我的演示:
[Route("api/[controller]")]
[ApiController]
public class DefaultController : ControllerBase
{
[HttpGet("Test/{startDate}/{stopDate}")]
public string Test(string startDate, string stopDate)
{
return "Ok";
}
}
appsettings.json:
"IpRateLimiting": {
"EnableEndpointRateLimiting": true,
"StackBlockedRequests": false,
"RealIPHeader": "X-Real-IP",
"ClientIdHeader": "X-ClientId",
"HttpStatusCode": 429,
"GeneralRules": [
{
"Endpoint": "*:/api/default/Test/*",
"Period": "1h",
"Limit": 5
}
]
}
以下是测试结果:
我找到了一个解决方案,因此对自己做出了回答。在我的情况下,我无法更改中建议的控制器方法路由 如上所述,可以实现自己的路径提取逻辑。我编写了自定义IpRateLimitMiddleware并重写了ResolveIdentity方法,如下所示:
public class CustomIpRateLimitMiddleware : IpRateLimitMiddleware
{
private readonly ILogger<CustomIpRateLimitMiddleware> _logger;
private readonly IRateLimitConfiguration _config;
public CustomIpRateLimitMiddleware(RequestDelegate next,
IOptions<IpRateLimitOptions> options,
IRateLimitCounterStore counterStore,
IIpPolicyStore policyStore,
IRateLimitConfiguration config,
ILogger<CustomIpRateLimitMiddleware> logger)
: base(next, options, counterStore, policyStore, config, logger)
{
_config = config;
_logger = logger;
}
public override ClientRequestIdentity ResolveIdentity(HttpContext httpContext)
{
var identity = base.ResolveIdentity(httpContext);
if (httpContext.Request.Query == null && !httpContext.Request.Query.Any())
{
return identity;
}
StringBuilder path = new StringBuilder(httpContext.Request.Path.ToString().ToLowerInvariant());
foreach (var parameter in httpContext.Request.Query)
{
path.Append("/" + parameter.Value);
}
identity.Path = path.ToString();
return identity;
}
}
配置
-方法:
services.AddOptions();
services.AddMemoryCache();
services.Configure<IpRateLimitOptions>(Configuration.GetSection("IpRateLimiting"));
services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>();
services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
app.UseMiddleware<CustomIpRateLimitMiddleware>();
AspNetCoreRateLimit正在获取以下格式的路径:
/api/endpoint/path/2020-04-04/2020-04-04
..现在我的速率限制配置可以是:
"IpRateLimiting": {
"EnableEndpointRateLimiting": true,
"StackBlockedRequests": false,
"RealIPHeader": "X-Real-IP",
"ClientIdHeader": "X-ClientId",
"HttpStatusCode": 429,
"GeneralRules": [
{
"Endpoint": "*:/api/path/*",
"Period": "1h",
"Limit": 5
}
]
}
也许你需要一个自定义解析器,看看这里:@alessandro我会试试这个..@alessandro这个很有效,我把它作为一个完整的答案来回答..谢谢你的好答案。在我的例子中,更改控制器方法签名有点问题,因为有很多API客户端使用我的端点,所以我不想引入任何破坏性的更改。。我必须看看是否可以创建自定义解析程序。您是如何使用自定义中间件的,您在启动时注册了中间件吗?感谢您的更新,我想您已经替换了这行应用程序。UseIpRateLimiting();使用这个app.useMidleware();没错,因为我自己做了中间件。现在,在我的答案中有了整个类CustomIpRateLimitMiddleware。
/api/endpoint/path/2020-04-04/2020-04-04
"IpRateLimiting": {
"EnableEndpointRateLimiting": true,
"StackBlockedRequests": false,
"RealIPHeader": "X-Real-IP",
"ClientIdHeader": "X-ClientId",
"HttpStatusCode": 429,
"GeneralRules": [
{
"Endpoint": "*:/api/path/*",
"Period": "1h",
"Limit": 5
}
]
}