博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ASP.NET Core WebApi AspNetCoreRateLimit 限流中间件学习
阅读量:6229 次
发布时间:2019-06-21

本文共 6485 字,大约阅读时间需要 21 分钟。

AspNetCoreRateLimit介绍:

AspNetCoreRateLimit是ASP.NET核心速率限制框架,能够对WebApi,Mvc中控制限流,包含IpRateLimit中间件和ClientRateLimit中间件,每个中间件都可以为不同的场景设置多个限,该框架的作者是stefanprodan,项目nuget地址是。

对客户端IP限流控制。

首先nuget安装 Install-Package AspNetCoreRateLimit ,在Startup中Code以下代码,添加服务和注入,其中的配置是什么;注释都有了。

// This method gets called by the runtime. Use this method to add services to the container.        public void ConfigureServices(IServiceCollection services)        {            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);            //添加appsettings.json            services.AddOptions();            //需要存储速率和ip规则            services.AddMemoryCache();            //加载appsettings.json中的配置项 ,下面三项是加载general,rules            services.Configure
(Configuration.GetSection("IpRateLimiting")); services.Configure
(Configuration.GetSection("IpRateLimitPolicies")); //注入计时器和规则 services.AddSingleton
(); services.AddSingleton
(); //添加框架服务 services.AddMvc(); }

在Configure中配置RateLimit的启动

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.        public void Configure(IApplicationBuilder app, IHostingEnvironment env,ILoggerFactory loggerFactory)        {            loggerFactory.AddConsole(Configuration.GetSection("Logging"));            loggerFactory.AddDebug();            app.UseIpRateLimiting();            if (env.IsDevelopment())                app.UseDeveloperExceptionPage();            app.UseMvc();        }

 我们还需要再appsettings.json中写入配置和规则:

"IpRateLimiting": {    "EnableEndpointRateLimiting": false,    "StackBlockedRequests": false,    "RealIpHeader": "X-Real-IP",    "ClientIdHeader": "X-ClientId",    "HttpStatusCode": 429,    "IpWhitelist": [ "127.0.0.1", "::1/10", "192.168.0.0/24" ],    "EndpointWhitelist": [ "get:/api/license", "*:/api/status" ],    "ClientWhitelist": [ "dev-id-1", "dev-id-2" ],    "GeneralRules": [      {        "Endpoint": "*",        "Period": "1s",        "Limit": 2      },      {        "Endpoint": "*",        "Period": "15m",        "Limit": 100      },      {        "Endpoint": "*",        "Period": "12h",        "Limit": 1000      },      {        "Endpoint": "*",        "Period": "7d",        "Limit": 10000      }    ]  }

如果EnableEndpointRateLimiting设置为false,那么这些限制就全局使用,例如,如果设置每秒5次调用的限制,对任何端口的任何http调用都计入这个限制,反之,如果它是true,那么该限制将应用于{端口}{path}中的每个端点。

如果stackblockedrequest设置为false,则不会将拒绝调用添加到节流阀计数器,如果你要拒绝你必须设置为true;

ClientidHeader用于提取白清单的客户端id,如果客户端id在这个里面,就不会应用速率限制。

覆盖特定IP一般规则:

"IpRateLimitPolicies": {    "IpRules": [      {        "Ip": "84.247.85.224",        "Rules": [          {            "Endpoint": "*",            "Period": "1s",            "Limit": 10          },          {            "Endpoint": "*",            "Period": "15m",            "Limit": 200          }        ]      },      {        "Ip": "192.168.3.22/25",        "Rules": [          {            "Endpoint": "*",            "Period": "1s",            "Limit": 5          },          {            "Endpoint": "*",            "Period": "15m",            "Limit": 150          },          {            "Endpoint": "*",            "Period": "12h",            "Limit": 500          }        ]      }    ]  }

 IP字段支持IP v4和v6值,我们还需要去定义速率限制规则

规则由端点,期间和限制组成,示例(将所有的端点的速率限制每秒2次呼叫),那么定义如下:

{ "Endpoint": "*", "Period": "1s", "Limit": 2 }

 如果在同一端点,例如get/values在一秒中你调用了3次,那么第三次将会被阻止;但是如果说你在同一秒内还调用了Put/values那么不会阻止,因为他们不是在同一端点之中。在期间(Period)中,还有单位 s m h 等.

有的时候我们对拦截有一定的自定义需求的时候,我们可以继承IpRateLimitMiddleware,如以下定义:

public class CustomizationLimitMiddleware : IpRateLimitMiddleware    {        private readonly IpRateLimitOptions _options;        private readonly IIpPolicyStore _ipPolicyStore;        public CustomizationLimitMiddleware(RequestDelegate next, IOptions
options, IRateLimitCounterStore counterStore, IIpPolicyStore policyStore, ILogger
logger, IIpAddressParser ipParser = null) : base(next, options, counterStore, policyStore, logger, ipParser) { _options = options.Value; _ipPolicyStore = policyStore; } public override ClientRequestIdentity SetIdentity(HttpContext httpContext) { var clientId = "anon"; if (httpContext.Request.Headers.Keys.Contains(_options.ClientIdHeader, StringComparer.CurrentCultureIgnoreCase)) { clientId = httpContext.Request.Headers[_options.ClientIdHeader].First(); } return new ClientRequestIdentity { Path = httpContext.Request.Path.ToString().ToLowerInvariant(), HttpVerb = httpContext.Request.Method.ToLowerInvariant(), ClientId = clientId }; } }

 行为

当客户端进行HTTP调用时,IpRateLimitMiddleware执行以下操作:

  • 从请求体中获取IP,客户端IP,Http信息,和一些URL,如果需要修改自己的提取逻辑,可以覆盖IpRateLimitMiddleware.SetIdentity。
  • 在白名单中搜索IP,客户端ID和URL,如果有匹配则不执行任何操作
  • 在IP规则中搜索匹配项,所有适用的规则按期间分组,对于每个期间使用最严格的规则
  • 在匹配的一般规则中搜索,如果匹配的一般规则具有IP规则中不存在的定义时间段,则也使用此一般规则
  • 对于每个匹配规则,速率限制计数器递增,如果计数器值大于规则限制,则请求被阻止

如果请求被阻止,则客户端会收到如下文本响应:

Status Code: 429Retry-After: 58Content: API calls quota exceeded! maximum admitted 2 per 1m.

 如果请求没有得到速率限制,那么匹配规则中定义的最长周期用于组成X-Rate-Limit标头,这些标头将在响应中注入:

X-Rate-Limit-Limit: the rate limit period (eg. 1m, 12h, 1d)X-Rate-Limit-Remaining: number of request remaining X-Rate-Limit-Reset: UTC date time (ISO 8601) when the limits resets

默认情况下,组织了客户端的调用我们都会记录到日志中,那么我们可以使用Microsoft.Extensions.Logging.ILogger,这个就略过了。

我们有的时候需要添加ip规则或者更新速率,如一下所示:

public class IpRateLimitController : Controller{	private readonly IpRateLimitOptions _options;	private readonly IIpPolicyStore _ipPolicyStore;	public IpRateLimitController(IOptions
optionsAccessor, IIpPolicyStore ipPolicyStore) { _options = optionsAccessor.Value; _ipPolicyStore = ipPolicyStore; } [HttpGet] public IpRateLimitPolicies Get() { return _ipPolicyStore.Get(_options.IpPolicyPrefix); } [HttpPost] public void Post() { var pol = _ipPolicyStore.Get(_options.IpPolicyPrefix);          //add pol.IpRules.Add(new IpRateLimitPolicy { Ip = "8.8.4.4", Rules = new List
(new RateLimitRule[] { new RateLimitRule { Endpoint = "*:/api/testupdate", Limit = 100, Period = "1d" } }) });          //update _ipPolicyStore.Set(_options.IpPolicyPrefix, pol); }}

这样呢,你可以将ip限制的规则放到数据库中再推送到缓存中。

转载于:https://www.cnblogs.com/ZaraNet/p/10119475.html

你可能感兴趣的文章
App 卸载记录
查看>>
JavaScript变量和作用域
查看>>
开源SIP服务器加密软件NethidPro升级
查看>>
作业:实现简单的shell sed替换功能和修改haproxy配置文件
查看>>
Altium 拼板方法以及 注意的 地方
查看>>
Apache Pulsar中的地域复制,第1篇:概念和功能
查看>>
python pip install 出现 OSError: [Errno 1] Operation not permitted
查看>>
oracle12C 重做日志
查看>>
zookeeper与kafka安装部署及java环境搭建(发布订阅模式)
查看>>
从源码分析scrollTo、scrollBy、Scroller方法的区别和作用
查看>>
ObjectOutputStream和ObjectInputStream
查看>>
创建使用 framework和 a静态库
查看>>
Codeigniter 4.0-dev 版源码学习笔记之五——相对于 3.x 的变化
查看>>
mariadb 实用功能3 修改表结构显示进度
查看>>
部署 Office Communications Server 2007 R2 Enterprise Edition-Part01
查看>>
烂泥:阿里云RDS本地恢复数据
查看>>
[IE 技巧] 显示/隐藏IE 的菜单/工具栏
查看>>
Hadoop概念学习系列之搭建(windows)Eclipse/MyEclipse远程操作(Linux上)hadoop2.2.0/hadoop2.6.0 出错集(三十五)...
查看>>
一些C++11语言新特性 - Uniform Initialization
查看>>
nagios客户端未启动报错
查看>>