限制用户对服务的请求次数(Web,WebApi)

通过对缓存的操作进行请求次数的限制

环境:.NET 6.0

准备

开始

创建全局限制配置文件

Limit.json(文件名字可以为其的)

{
    // IP限流配置
    "IpRateLimiting": {
        // 例如:设置每分钟5次访问限流
        // 当False时:每个接口都加入计数,不管你访问哪个接口,只要在一分钟内累计够5次,将禁止访问。
        // 当True 时:当一分钟请求了5次GetData接口,则该接口将在时间段内禁止访问,但是还可以访问PostData()5次,总得来说是每个接口都有5次在这一分钟,互不干扰。
        "EnableEndpointRateLimiting": true,
        // 如果StackBlockedRequests设置为false,拒绝的API调用不会添加到调用次数计数器上。比如:如果客户端每秒发出3个请求并且您设置了每秒一个调用的限制,
        // 则每分钟或每天计数器等其他限制将仅记录第一个调用,即成功的API调用。如果您希望被拒绝的API调用计入其他时间的显示(分钟,小时等),则必须设置
        "StackBlockedRequests": false,
        // 在RealIpHeader使用时,你的Kestrel服务器背后是一个反向代理,如果你的代理服务器使用不同的页眉然后提取客户端IP X-Real-IP使用此选项来设置它。
        "RealIpHeader": "X-Real-IP",
        // 将ClientIdHeader被用于提取白名单的客户端ID。如果此标头中存在客户端ID并且与ClientWhitelist中指定的值匹配,则不应用速率限制。
        "ClientIdHeader": "X-ClientId",
        // IP白名单:支持Ipv4和Ipv6
        "IpWhitelist": [],
        // 端点白名单
        "EndpointWhitelist": [],
        // 客户端白名单
        "ClientWhitelist": [],
        "QuotaExceededResponse": {
            "Content": "{{\"code\":429,\"type\":\"error\",\"message\":\"访问过于频繁,请稍后重试!\",\"result\":null,\"extras\":null}}",
            "ContentType": "application/json",
            "StatusCode": 429
        },
        // 返回状态码
        "HttpStatusCode": 429,
        // API规则,结尾一定要带*
        "GeneralRules": [
            // 1秒钟只能调用1次
            {
                "Endpoint": "*",
                "Period": "1s",
                "Limit": 10
            },
            // 1分钟只能调用100次
            {
                "Endpoint": "*",
                "Period": "1m",
                "Limit": 1000
            },
            // 1小时只能调用1000
            {
                "Endpoint": "*",
                "Period": "1h",
                "Limit": 10000
            },
            // 1天只能调用10000次
            {
                "Endpoint": "*",
                "Period": "1d",
                "Limit": 1000000
            }
        ]
    },
    "IpRateLimitPolicies": {
        "IpRules": [
            {
                "Ip": "XXX.XXX.XXX.XXX",
                "Rules": [
                    {
                        "Endpoint": "*",
                        "Period": "1s",
                        "Limit": 10
                    },
                    {
                        "Endpoint": "*",
                        "Period": "1m",
                        "Limit": 1000
                    }
                ]
            }
        ]
    },
    // 客户端限流配置
    "ClientRateLimiting": {
        "EnableEndpointRateLimiting": true,
        "ClientIdHeader": "X-ClientId",
        "EndpointWhitelist": [],
        "ClientWhitelist": [],
        "QuotaExceededResponse": {
            "Content": "{{\"code\":429,\"type\":\"error\",\"message\":\"访问人数过多,请稍后重试!\",\"result\":null,\"extras\":null}}",
            "ContentType": "application/json",
            "StatusCode": 429
        },
        "HttpStatusCode": 429,
        "GeneralRules": [
            {
                "Endpoint": "*",
                "Period": "1s",
                "Limit": 10
            },
            {
                "Endpoint": "*",
                "Period": "1m",
                "Limit": 1000
            }
        ]
    },
    "ClientRateLimitPolicies": {
        "ClientRules": [
            {
                "ClientId": "xxx-xxx",
                "Rules": [
                    {
                        "Endpoint": "*",
                        "Period": "1s",
                        "Limit": 10
                    },
                    {
                        "Endpoint": "*",
                        "Period": "1m",
                        "Limit": 1000
                    }
                ]
            }
        ]
    }
}

文件属性设置

fileProperty

修改Program.cs

using AspNetCoreRateLimit;
using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

//--------------------------尽量靠前,对应Limit.json的内容---------------------------------------//

// 将json添加到配置中
builder.Configuration.AddJsonFile("Limit.json");

// ip限制

// ip速率限制
builder.Services.Configure<IpRateLimitOptions>(builder.Configuration.GetSection("IpRateLimiting"));

//IP 速率限制策略
builder.Services.Configure<IpRateLimitPolicies>(builder.Configuration.GetSection("IpRateLimitPolicies"));

// 客户端限制

// Client速率限制
builder.Services.Configure<ClientRateLimitOptions>(builder.Configuration.GetSection("ClientRateLimiting"));

// Client 速率限制策略
builder.Services.Configure<ClientRateLimitPolicies>(builder.Configuration.GetSection("ClientRateLimitPolicies"));
//--------------------------尽量靠前,对应Limit.json的内容---------------------------------------//

builder.Services.AddControllers();

builder.Services.AddEndpointsApiExplorer();

// swagger服务
builder.Services.AddSwaggerGen();

// 缓存服务
builder.Services.AddMemoryCache();

// 将AspNetCoreRateLimit配置到缓存控制中
builder.Services.AddInMemoryRateLimiting();

// 配置单例服务(默认即可)
builder.Services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

//--------------------------限流组件(在跨域之后)---------------------------------------//
// ip限流
app.UseIpRateLimiting();

// client限流
app.UseClientRateLimiting();
//--------------------------限流组件(在跨域之后)---------------------------------------//
app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

启动程序

正常访问

访问默认的获取天气接口

返回Body如下:

/WeatherForecast

返回Header如下:
出现红色方框内的数据则限制请求成功

Header

请求限制

以触发10秒内10次的限制进行测试

第11次将会被限制返回数据

11Request

返回的限制信息

429

该功能将会对全局进行请求限制,可以通过配置json文件跳过部分接口的限制

最后修改:2023 年 08 月 15 日
如果觉得我的文章对你有用,请随意赞赏