ASP.NET Core-請求頻率限制(AspNetCoreRateLimit)


參考:
https://github.com/stefanprodan/AspNetCoreRateLimit/wiki
https://www.cnblogs.com/EminemJK/p/12720691.html (使用Redis緩存)

簡介

在網站或API應用中,為了防止惡意攻擊,通常希望屏蔽某一客戶端短時間的內高頻率請求。在ASP.NET Core中,AspNetCoreRateLimit為我們提供此功能。
AspNetCoreRateLimit是一個ASP.NET Core速率限制的解決方案,旨在控制客戶端根據IP地址或客戶端ID向Web API或MVC應用發出的請求的速率。AspNetCoreRateLimit包含一個IpRateLimitMiddleware和ClientRateLimitMiddleware,每個中間件可以根據不同的場景配置限制允許IP或客戶端,自定義這些限制策略,也可以將限制策略應用在每​​個API URL或具體的HTTP Method上。

GitHub鏈接:https://github.com/stefanprodan/AspNetCoreRateLimit

配置文件

通過IP限制流量

{
  "IpRateLimiting": {
    //false則全局將應用限制,並且僅應用具有作為端點的規則* 。 true則限制將應用於每個端點,如{HTTP_Verb}{PATH}
    "EnableEndpointRateLimiting": true,
    //false:被拒絕的API調用不會添加到調用次數計數器上
    "StackBlockedRequests": false,   
    //表示獲取用戶端的真實IP
    "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": "*:/fw/*",
        "Period": "5s",
        "Limit": 3
      }
    ]
  }
}
  • EnableEndpointRateLimiting設置為true,意思是IP限制會應用於單個配置的Endpoint上。如果是false的話,只會限制所有 * 的規則,而不能達到針對單個Endpoint配置的目的。
  • HttpStatusCode設置為429,意思是觸發限制之后給客戶端返回的HTTP狀態碼。
  • GeneralRules里我只配置了一條,針對/fw這URL的限制。其中,開頭的 : 表示任何HTTP VERB,如GET、POST,而結尾的 / 表示需要考慮/fw后面的參數,也就是我MVC Action參數里的route參數。
    針對不同參數,會有不同的計數。比如IP為127.0.0.1的用戶在1分鍾內請求了 /fw/abcd 10次,又請求了 /fw/qwer 25次,也請求了 /fw/996icu 32次。那么對於該用戶,/fw/abcd 的機會還剩下20次,/fw/qwer 的機會還剩下5次,而 /fw/996icu 在第31次請求時會返回429。
  • StackBlockedRequests設置為true,表示被拒絕的請求會添加到計數器,比如配置了兩個GeneralRules:(1秒2個請求)(10秒6個請求),你一秒訪問了5次,其中三個請求被拒絕,這三個請求被加入了計數器,你10秒內只能請求6-3=3次了。如果您希望被拒絕的請求計入其他限制,則必須設置StackBlockedRequests為true。如果不希望被拒絕的請求加入計數器,就設置為false。
  • IpWhitelist是IP白名單,本地調試或者UAT環境,可以加入相應的IP,略過策略的限制;
  • EndpointWhitelist是端點白名單,如果全局配置了訪問策略,設置端點白名單相當於IP白名單一樣,略過策略的限制;
  • GeneralRules是具體的策略,根據不同需求配置不同端點即可, Period的單位可以是s, m, h, d,Limint是單位時間內的允許訪問的次數;

通過ClientID限制流量

{
  "ClientRateLimiting": {
    "EnableEndpointRateLimiting": false,
    "EnableRegexRuleMatching": false,
    "StackBlockedRequests": false,
    "RealIpHeader": "X-Real-IP",
    "ClientIdHeader": "X-ClientId",
    "EndpointWhitelist": [ "get:/check/do" ],
    "ClientWhitelist": [ "other" ],
    "HttpStatusCode": 429,
    "GeneralRules": [
      {
        "Endpoint": "*",
        "Period": "1m",
        "Limit": 10
      }
    ]
  },
  "ClientRateLimitPolicies": {
    "ClientRules": [
      {
        "ClientId": "facebook",
        "Rules": [
          {
            "Endpoint": "*",
            "Period": "5s",
            "Limit": 2
          },
          {
            "Endpoint": "*",
            "Period": "10s",
            "Limit": 5
          }
        ]
      },
      {
        "ClientId": "other",
        "Rules": [
          {
            "Endpoint": "*",
            "Period": "5s",
            "Limit": 2
          }
        ]
      }
    ]
  }
}
  • ClientIdHeader用於設置ClientID的HeaderKey
  • ClientRateLimitPolicies 用於配置指定ClientID

代碼

演示ClientID限制:

services.AddMemoryCache();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

var clientRateLimiting = configuration.GetSection("ClientRateLimiting");
            if (clientRateLimiting.Exists())
            {
                //公共配置
                services.Configure<ClientRateLimitOptions>(clientRateLimiting);
                //注入Policy存儲器
                services.AddSingleton<IClientPolicyStore, MemoryCacheClientPolicyStore>();
                //注入計數器
                services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
                //計數器秘鑰生成器
                services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
                var clientRateLimitPolicies = configuration.GetSection("ClientRateLimitPolicies");
                if (clientRateLimitPolicies.Exists())
                {
                    //客戶端配置
                    services.Configure<ClientRateLimitPolicies>(clientRateLimitPolicies);
                }
            }

如果配置文件中有ClientRateLimitPolicies 元素,需要根據指定客戶端做限制,就需要添加以下代碼:

public static async Task Main(string[] args)
{
    IWebHost webHost = CreateWebHostBuilder(args).Build();
    using (var scope = webHost.Services.CreateScope())
    {
         // get the ClientPolicyStore instance
         var clientPolicyStore = scope.ServiceProvider.GetRequiredService<IClientPolicyStore>();
         // seed client data from appsettings
         await clientPolicyStore.SeedAsync();
    }
    await webHost.RunAsync();
}

以上代碼的目的是在執行到中間件之前將ClientRateLimitPolicies配置信息寫入緩存


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM