AspNetCore 限流中間件IpRateLimitMiddleware 介紹

  IpRateLimitMiddleware(Github: AspNetCoreRateLimit) 是ASPNETCore的一個限流的中間件,用於控制客戶端調用API的頻次, 如果客戶端頻繁訪問服務器,可以限制它的頻率,已降低訪問服務器端的壓力。或者如果有爬蟲在爬取關鍵數據,也可以限制某個/某些API或者某些IP的每天調取次數, 這樣限制他爬取的速度。
 
首先nuget安裝 Install-Package AspNetCoreRateLimit ,在Startup中Code以下代碼,添加服務和注入
 

StartUp.cs代碼

        public void ConfigureServices(IServiceCollection services)
        {
            // needed to load configuration from appsettings.json
            services.AddOptions();

            // needed to store rate limit counters and ip rules
            services.AddMemoryCache();

            //load general configuration from appsettings.json
            services.Configure<IpRateLimitOptions>(Configuration.GetSection("IpRateLimiting"));

            //load ip rules from appsettings.json
            services.Configure<IpRateLimitPolicies>(Configuration.GetSection("IpRateLimitPolicies"));

            // inject counter and rules stores
            services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>();
            services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();

            // Add framework services.
            services.AddMvc();

            // https://github.com/aspnet/Hosting/issues/793
            // the IHttpContextAccessor service is not registered by default.
            // the clientId/clientIp resolvers use it.
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

            // configuration (resolvers, counter key builders)
            services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
        }
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseIpRateLimiting();
            //if (env.IsDevelopment())
            //    app.UseDeveloperExceptionPage();
            app.UseMvc();
        }

IPRateLimiting應該在其他中間件之前註冊, 否則API請求計算可能不正確。

如果您對應用程序進行負載平衡,則需要使用IDistributedCacheRedis或SQLServer,以便所有的kestrel實例都具有相同的速率限制存儲。您應該像這樣注入分佈式存儲,而不是使用MemoryCache:

配置和一般規則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": 1
      },
      {
        "Endpoint": "*",
        "Period": "15m",
        "Limit": 100
      },
      {
        "Endpoint": "*",
        "Period": "12h",
        "Limit": 1000
      },
      {
        "Endpoint": "*",
        "Period": "7d",
        "Limit": 10000
      }
    ]
  }

如果EnableEndpointRateLimiting設置爲false則全局將應用限制,並且僅應用具有作爲端點的規則*。例如,如果您設置每秒5次調用的限制,則對任何端點的任何HTTP調用都將計入該限制。

如果EnableEndpointRateLimiting設置爲true,則限制將應用於每個端點,如{HTTP_Verb}{PATH}。例如,如果您爲*:/api/values客戶端設置每秒5個呼叫的限制,則可以GET /api/values每秒呼叫5次,但也可以呼叫5次PUT /api/values

如果StackBlockedRequests設置爲false,拒絕的API調用不會添加到調用次數計數器上。比如: 如果客戶端每秒發出3個請求並且您設置了每秒一個調用的限制,則每分鐘或每天計數器等其他限制將僅記錄第一個調用,即成功的API調用。如果您希望被拒絕的API調用計入其他時間的顯示(分鐘,小時等),則必須設置StackBlockedRequeststrue

RealIpHeader使用時,你的Kestrel 服務器背後是一個反向代理,如果你的代理服務器使用不同的頁眉然後提取客戶端IP X-Real-IP使用此選項來設置它。

ClientIdHeader被用於提取白名單的客戶端ID。如果此標頭中存在客戶端ID並且與ClientWhitelist中指定的值匹配,則不應用速率限制。

覆蓋特定IP appsettings.json的一般規則:

"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值以及範圍,如 "192.168.0.0/24", "fe80::/10" 或 "192.168.0.0-192.168.0.255"。

 



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章