一、简介
AspNetCoreRateLimit是一个ASP.NET核心速率限制解决方案,旨在根据IP地址或客户端ID控制客户端可以向Web API或MVC应用程序发出的请求的速率。AspNetCoreRateLimit包包含一个IpRateLimitMiddleware和一个ClientRateLimitMiddleware,对于每个中间件,您可以为不同的方案设置多个限制,例如允许IP或客户端在一段时间间隔内进行最大数量的调用,如每秒15分钟等。您可以定义这些限制来处理对API的所有请求,或者您可以将限制范围扩大到每个API URL或HTTP谓词和路径。
二、使用
在nuget包管理中搜索AspNetCoreRateLimit,选择对应的版本。
ConfigureServices方法添加如下代码
services.Configure<IpRateLimitOptions>(Configuration.GetSection("IpRateLimiting"));
services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>();
services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
配置文件
"IpRateLimiting": {
//例如设置了5次每分钟访问限流。当False时:项目中每个接口都加入计数,不管你访问哪个接口,只要在一分钟内累计够5次,将禁止访问。
//True:当一分钟请求了5次GetData接口,则该接口将在时间段内禁止访问,但是还可以访问PostData()5次,总得来说是每个接口都有5次在这一分钟,互不干扰。
"EnableEndpointRateLimiting": true,
//如果StackBlockedRequests设置为false,拒绝的API调用不会添加到调用次数计数器上。比如:如果客户端每秒发出3个请求并且您设置了每秒一个调用的限制,
//则每分钟或每天计数器等其他限制将仅记录第一个调用,即成功的API调用。如果您希望被拒绝的API调用计入其他时间的显示(分钟,小时等),则必须设置
//StackBlockedRequests为true。
"StackBlockedRequests": false,
//在RealIpHeader使用时,你的Kestrel 服务器背后是一个反向代理,如果你的代理服务器使用不同的页眉然后提取客户端IP X-Real-IP使用此选项来设置它。
"RealIpHeader": "X-Real-IP",
//将ClientIdHeader被用于提取白名单的客户端ID。如果此标头中存在客户端ID并且与ClientWhitelist中指定的值匹配,则不应用速率限制。
"ClientIdHeader": "X-ClientId",
//IP白名单:支持Ip v4和v6
"IpWhitelist": [],
//端点白名单
"EndpointWhitelist": [ "get:/api/xxx", "*:/api/yyy" ],
//客户端白名单
"ClientWhitelist": [ "dev-client-1", "dev-client-2" ],
"QuotaExceededResponse": {
"Content": "{{\"status\":429,\"msg\":\"访问过于频繁,请稍后重试\",\"success\":false}}",
"ContentType": "application/json",
"StatusCode": 429
},
//返回状态码
"HttpStatusCode": 429,
//api规则,结尾一定要带*
"GeneralRules": [
{
//端点路径
"Endpoint": "*",
//时间段,格式:{数字}{单位};可使用单位:s, m, h, d
"Period": "1s",
//限制
"Limit": 2
},
//15分钟只能调用100次
{
"Endpoint": "*",
"Period": "15m",
"Limit": 100
},
//12H只能调用1000
{
"Endpoint": "*",
"Period": "12h",
"Limit": 1000
},
//7天只能调用10000次
{
"Endpoint": "*",
"Period": "7d",
"Limit": 10000
}
]
}
三、测试
// GET api/values/5
[HttpGet("{id}")]
public string Get(int id)
{
return "value";
}
"ClientRateLimiting": {
"EnableEndpointRateLimiting": true,
"ClientIdHeader": "X-ClientId",
"HttpStatusCode": 429,
"EndpointWhitelist": [ "*:/api/values", "delete:/api/clients", "get:/" ],
"ClientWhitelist": [ "cl-key-a", "cl-key-b" ],
"GeneralRules": [
{
"Endpoint": "*",
"Period": "1s",
"Limit": 2
},
{
"Endpoint": "*",
"Period": "1m",
"Limit": 5
},
{
"Endpoint": "post:/api/clients",
"Period": "5m",
"Limit": 3
},
{
"Endpoint": "get:/api/user/get-info",
"Period": "1m",
"Limit": 3,
"QuotaExceededResponse": {
"Content": "{{ \"name\": \"\" , \"error\": \"Get user information api interface quota exceeded. Maximum allowed: {0} per {1}. Please try again in {2} second(s).\" }}",
"ContentType": "application/json"
}
}
]
},