Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# AspNetCoreRateLimit在匹配规则时不使用查询参数_C#_Asp.net Core_Throttling_Rate Limiting - Fatal编程技术网

C# AspNetCoreRateLimit在匹配规则时不使用查询参数

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

我正在使用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&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
      }
    ]
  }