.Net Core結合AspNetCoreRateLimit實現限流

前言

  相信使用過WebApiThrottle的童鞋對AspNetCoreRateLimit應該不陌生,AspNetCoreRateLimit是一個ASP.NET Core速率限制的解決方案,旨在控制客戶端根據IP地址或客戶端ID向Web API或MVC應用發出的請求的速率。AspNetCoreRateLimit包含一個IpRateLimitMiddlewareClientRateLimitMiddleware,每一箇中間件能夠根據不一樣的場景配置限制容許IP或客戶端,自定義這些限制策略,也能夠將限制策略應用在每​​個API URL或具體的HTTP Method上。html

實踐

   起初是由於新作的項目中,有天查詢日誌發現,對外的幾個公共接口常常被「惡意」調用,考慮到接口安全性問題,增長限流策略。git

  AspNetCoreRateLimit GayHub:https://github.com/stefanprodan/AspNetCoreRateLimitgithub

根據IP進行限流

  經過nuget安裝AspNetCoreRateLimit,當前版本是3.0.5,由於實際項目中用的都是分佈式緩存,在這裏不用內存存儲,而是結合Redis進行使用,內存存儲直接參考官方的Wiki就能夠了。json

Install-Package AspNetCoreRateLimit 

Install-Package Microsoft.Extensions.Caching.Redis

  在Startup.ConfigureServices中將服務和其餘依賴注入api

public void ConfigureServices(IServiceCollection services) { #region MVC services.AddMvc( options => { options.UseCentralRoutePrefix(new RouteAttribute("api/")); } ).SetCompatibilityVersion(CompatibilityVersion.Version_2_2); #endregion services.AddDistributedRedisCache(options => { options.Configuration = "127.0.0.1:6379,password=123456,connectTimeout=5000,syncTimeout=10000"; 
                options.InstanceName = "WebRatelimit"; }); //加載配置
 services.AddOptions(); //從appsettings.json獲取相應配置
            services.Configure<IpRateLimitOptions>(Configuration.GetSection("IpRateLimiting")); //注入計數器和規則存儲
            services.AddSingleton<IIpPolicyStore, DistributedCacheIpPolicyStore>(); services.AddSingleton<IRateLimitCounterStore, DistributedCacheRateLimitCounterStore>(); services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); //配置(計數器密鑰生成器)
            services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>(); }

  在Startup.Configure啓用跨域

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseHsts(); } //啓用限流,需在UseMvc前面
            app.UseIpRateLimiting(); app.UseMvc(); }

  爲了避免影響appsettings.json的美觀吧,能夠新建一個RateLimitConfig.json,並Program中啓動加載中增長緩存

public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>().ConfigureAppConfiguration((host,config)=> { config.AddJsonFile($"RateLimitConfig.json", optional: true, reloadOnChange: true); });

  RateLimitConfig.json 配置以下:安全

{ "IpRateLimiting": { //false則全局將應用限制,而且僅應用具備做爲端點的規則* 。 true則限制將應用於每一個端點,如{HTTP_Verb}{PATH}
    "EnableEndpointRateLimiting": true, //false則拒絕的API調用不會添加到調用次數計數器上
    "StackBlockedRequests": false, "RealIpHeader": "X-Real-IP", "ClientIdHeader": "X-ClientId", "HttpStatusCode": 200, "QuotaExceededResponse": { "Content": "{{\"code\":429,\"msg\":\"訪問過於頻繁,請稍後重試\",\"data\":null}}", "ContentType": "application/json", "StatusCode": 200 }, "IpWhitelist": [ ], "EndpointWhitelist": [], "ClientWhitelist": [], "GeneralRules": [ { "Endpoint": "*:/api/values/test", "Period": "5s", "Limit": 3 } ] } }

  重要配置說明:app

       QuotaExceededResponse 是自定義返回的內容,因此必須設置HttpStatusCodeStatusCode爲200。分佈式

  GeneralRules是具體的策略,根據不一樣需求配置不一樣端點便可, Period的單位能夠是s, m, h, dLimint是單位時間內的容許訪問的次數;

  IpWhitelist是IP白名單,本地調試或者UAT環境,能夠加入相應的IP,略過策略的限制;

       EndpointWhitelist是端點白名單,若是全局配置了訪問策略,設置端點白名單至關於IP白名單同樣,略過策略的限制;

       其餘配置項請參考Wiki:https://github.com/stefanprodan/AspNetCoreRateLimit/wiki/IpRateLimitMiddleware#setup

Fiddler開始測試

測試接口:http://127.0.0.1:5000/api/values/Test

 [HttpGet] public object test() { return "ok"; }

調用結果:

 

 調用次數和剩餘調用次數在Head能夠看到,(吃我一個連接:https://www.cnblogs.com/EminemJK/p/12720691.html

 

 若是調用超過策略後,調用失敗,返回咱們自定義的內容

 

 在Redis客戶端能夠看到策略的一些狀況,

 其餘

  一般在項目中,Authorization受權是少不了了,加入限流後,在被限流的接口調用後,限流攔截器使得跨域策略失效,故重寫攔截器中間件,繼承IpRateLimitMiddleware 便可:

public class IPLimitMiddleware : IpRateLimitMiddleware { public IPLimitMiddleware(RequestDelegate next, IOptions<IpRateLimitOptions> options, IRateLimitCounterStore counterStore, IIpPolicyStore policyStore, IRateLimitConfiguration config, ILogger<IpRateLimitMiddleware> logger) : base(next, options, counterStore, policyStore, config, logger) { } public override Task ReturnQuotaExceededResponse(HttpContext httpContext, RateLimitRule rule, string retryAfter) { httpContext.Response.Headers.Append("Access-Control-Allow-Origin", "*"); return base.ReturnQuotaExceededResponse(httpContext, rule, retryAfter); } }

  而後修改Startup.Configure

//啓用限流,需在UseMvc前面 //app.UseIpRateLimiting();
        app.UseMiddleware<IPLimitMiddleware>(); app.UseMvc(); 

  特別須要注意的坑是,在其餘文章的教程中,他們會寫成:

app.UseMiddleware<IPLimitMiddleware>().UseIpRateLimiting();//錯誤的演示 https://www.cnblogs.com/EminemJK/p/12720691.html

  這些寫你測試的時候會發現,

X-Rate-Limit-Remaining 遞減量會變成2,也不是遞減1,舉栗子,配置以下:

"Endpoint": "*:/api/values/test", "Period": "3s", "Limit": 1

表示3秒內能夠訪問的次數是1一次,當發生調用的時候會直接返回被限制的提示,而不能正常訪問接口。

最後

  AspNetCoreRateLimit還能夠根據客戶端ID進行配置策略,具體能夠看一下官方的Wiki吧。

相關文章
相關標籤/搜索