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配置信息写入缓存

  • 相关阅读:
    Oracle Function REGEXP
    Asp.net 注册IIS
    SAP모듈
    C# 程序中,不使用TNS File 中的服务名进行数据库连接
    跟我一起学XNA(2)让物体动起来②(附源码)
    ubuntu显卡的几个帖子
    每秒改变一次背景颜色以及由此引发的一些有趣的小事情(.net方向)
    to myself
    vi编辑器上下左右键盘变成ABCD
    一个最简单的linux hello world模块
  • 原文地址:https://www.cnblogs.com/fanfan-90/p/14519358.html
Copyright © 2011-2022 走看看