ASP.NET Core WebApi AspNetCoreRateLimit限流ミドルウェア学習

10233 ワード

AspNetCoreRateLimitの紹介:
AspNetCoreRateLimitはASP.NETコアレート制限フレームワークは、WebApi、Mvcで限流を制御することができ、AspNetCoreRateLimitパッケージにはIpRateLimitミドルウェアとClientRateLimitミドルウェアが含まれており、各ミドルウェアは異なるシーンに複数の制限を設定することができ、このフレームワークの著者はstefanprodanであり、プロジェクトnugetアドレスはhttps://github.com/stefanprodan/AspNetCoreRateLimit.
クライアント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();
        }

コンフィギュレーションで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();
        }

もっと必要だ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 v 4とv 6の値をサポートし、レート制限ルールを定義する必要があります.
ルールは、エンドポイント、期間、および制限から構成され、例(すべてのエンドポイントのレートを毎秒2回のコールに制限する)では、次のように定義されます.
{
 "Endpoint": "*", "Period": "1s", "Limit": 2 }

同じエンドポイント、例えばget/valuesが1秒で3回呼び出された場合、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: 429
    Retry-After: 58
    Content: 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制限のルールをデータベースに格納してキャッシュにプッシュすることができます.