• AspNetCoreRateLimit 学习


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

    Coding:https://huawu.coding.net/public/aspnetcoreratelimit/aspnetcoreratelimit/git/files

    主要包含 IP 和 ClientID 两种规则

    IP

    优先获取请求头:X-Real-IP

    其次获取:_httpContextAccessor.HttpContext.Connection.RemoteIpAddress?.ToString()

    ClientID 

    使用配置中 ClientIdHeader 定义的请求头 

    如:ClientIdHeader:X-ClientId,则请求头为:X-ClientId

    普通规则 GeneralRules 用法

    1.当启用 EnableEndpointRateLimiting 时,会匹配 普通规则中 * 或 *:/matching_path 或 matching_verb:/matching_path  会对比一个 IsUrlMatch 方法

    var limits = new List<RateLimitRule>();
    
    //rules 为对应的IP或ClientID中定义的Rules if (rules?.Any() == true) { if (_options.EnableEndpointRateLimiting) { // search for rules with endpoints like "*" and "*:/matching_path" string path = _options.EnableRegexRuleMatching ? $".+:{identity.Path}" : $"*:{identity.Path}"; var pathLimits = rules.Where(r => path.IsUrlMatch(r.Endpoint, _options.EnableRegexRuleMatching)); limits.AddRange(pathLimits); // search for rules with endpoints like "matching_verb:/matching_path" var verbLimits = rules.Where(r => $"{identity.HttpVerb}:{identity.Path}".IsUrlMatch(r.Endpoint, _options.EnableRegexRuleMatching)); limits.AddRange(verbLimits); } else { // ignore endpoint rules and search for global rules only var genericLimits = rules.Where(r => r.Endpoint == "*"); limits.AddRange(genericLimits); } // get the most restrictive limit for each period limits = limits.GroupBy(l => l.Period).Select(l => l.OrderBy(x => x.Limit)).Select(l => l.First()).ToList(); }

    2.否则 精确匹配 普通规则中 EndPoint 等于 * 

    IP和ClientID中的Rules

    所有的通用规则和自定义规则都会生效,精确匹配的Endpoint 最好设置的规则比 *规则范围小
    如果有和通用规则 Period 相等的规则,则优先使用此处的

    public static bool IsUrlMatch(this string source, string value, bool useRegex)
    {
        if (useRegex)
        {
            return IsRegexMatch(source, value);
        }
        return source.IsWildCardMatch(value);
    }
    
    public static bool IsWildCardMatch(this string source, string value)
    {
        return source != null && value != null && source.ToLowerInvariant().IsMatch(value.ToLowerInvariant());
    }
    
    public static bool IsMatch(this string value, string pattern, char singleWildcard = '?', char multipleWildcard = '*')
    {
    
        int[] inputPosStack = new int[(value.Length + 1) * (pattern.Length + 1)];   // Stack containing input positions that should be tested for further matching
        int[] patternPosStack = new int[inputPosStack.Length];                      // Stack containing pattern positions that should be tested for further matching
        int stackPos = -1;                                                          // Points to last occupied entry in stack; -1 indicates that stack is empty
        bool[,] pointTested = new bool[value.Length + 1, pattern.Length + 1];       // Each true value indicates that input position vs. pattern position has been tested
    
        int inputPos = 0;   // Position in input matched up to the first multiple wildcard in pattern
        int patternPos = 0; // Position in pattern matched up to the first multiple wildcard in pattern
    
        //if (pattern == null)
        //    pattern = string.Empty;
    
        // Match beginning of the string until first multiple wildcard in pattern
        while (inputPos < value.Length && patternPos < pattern.Length && pattern[patternPos] != multipleWildcard && (value[inputPos] == pattern[patternPos] || pattern[patternPos] == singleWildcard))
        {
            inputPos++;
            patternPos++;
        }
    
        // Push this position to stack if it points to end of pattern or to a general wildcard character
        if (patternPos == pattern.Length || pattern[patternPos] == multipleWildcard)
        {
            pointTested[inputPos, patternPos] = true;
            inputPosStack[++stackPos] = inputPos;
            patternPosStack[stackPos] = patternPos;
        }
    
        bool matched = false;
    
        // Repeat matching until either string is matched against the pattern or no more parts remain on stack to test
        while (stackPos >= 0 && !matched)
        {
            inputPos = inputPosStack[stackPos];         // Pop input and pattern positions from stack
            patternPos = patternPosStack[stackPos--];   // Matching will succeed if rest of the input string matches rest of the pattern
    
            if (inputPos == value.Length && patternPos == pattern.Length)
                matched = true;     // Reached end of both pattern and input string, hence matching is successful
            else if (patternPos == pattern.Length - 1)
                matched = true;     // Current pattern character is multiple wildcard and it will match all the remaining characters in the input string
            else
            {
                // First character in next pattern block is guaranteed to be multiple wildcard
                // So skip it and search for all matches in value string until next multiple wildcard character is reached in pattern
    
                for (int curInputStart = inputPos; curInputStart < value.Length; curInputStart++)
                {
    
                    int curInputPos = curInputStart;
                    int curPatternPos = patternPos + 1;
    
                    while (curInputPos < value.Length && curPatternPos < pattern.Length && pattern[curPatternPos] != multipleWildcard &&
                           (value[curInputPos] == pattern[curPatternPos] || pattern[curPatternPos] == singleWildcard))
                    {
                        curInputPos++;
                        curPatternPos++;
                    }
    
                    // If we have reached next multiple wildcard character in pattern without breaking the matching sequence, then we have another candidate for full match
                    // This candidate should be pushed to stack for further processing
                    // At the same time, pair (input position, pattern position) will be marked as tested, so that it will not be pushed to stack later again
                    if (((curPatternPos == pattern.Length && curInputPos == value.Length) || (curPatternPos < pattern.Length && pattern[curPatternPos] == multipleWildcard))
                        && !pointTested[curInputPos, curPatternPos])
                    {
                        pointTested[curInputPos, curPatternPos] = true;
                        inputPosStack[++stackPos] = curInputPos;
                        patternPosStack[stackPos] = curPatternPos;
                    }
                }
            }
        }
    
        return matched;
    }

    动态修改规则

    在Main 方法中添加如下代码

            var host=hostBuilder.Build()
    
                #region RateLimit 很关键,动态修改规则
                using (var scope = host.Services.CreateScope())
                {
                    // get the ClientPolicyStore instance
                    var clientPolicyStore = scope.ServiceProvider.GetRequiredService<IClientPolicyStore>();
                    // seed Client data from appsettings
                    _ = clientPolicyStore.SeedAsync();
    
                    // get the IpPolicyStore instance
                    var ipPolicyStore = scope.ServiceProvider.GetRequiredService<IIpPolicyStore>();
                    // seed IP data from appsettings
                    _ = ipPolicyStore.SeedAsync();
                }
                #endregion
    
                host.Run();    
    

      

  • 相关阅读:
    准备学习FLEX目前心理状态篇
    Jeffrey Richter 大师 ,这次交流收获不少。
    Scrum框架 转贴
    换工作中......
    以后多参加些论坛,交流交流思想。
    机会在哪?
    2011年要比2010年更加努力!!!
    2012,处理考验我的一年,2013,继续学习快速成长的一年
    终于买了iPad,激动。。。。
    CSP认证
  • 原文地址:https://www.cnblogs.com/huawublog/p/13528367.html
Copyright © 2020-2023  润新知