zoukankan      html  css  js  c++  java
  • 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配置信息写入缓存

  • 相关阅读:
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    微信小程序TodoList
    C语言88案例-找出数列中的最大值和最小值
    C语言88案例-使用指针的指针输出字符串
  • 原文地址:https://www.cnblogs.com/fanfan-90/p/14519358.html
Copyright © 2011-2022 走看看