.Net Core结合AspNetCoreRateLimit实现限流
前言
相信使用过WebApiThrottle的童鞋对AspNetCoreRateLimit应该不陌生,AspNetCoreRateLimit是一个ASP.NET Core速率限制的解决方案,旨在控制客户端根据IP地址或客户端ID向Web API或MVC应用发出的请求的速率。AspNetCoreRateLimit包含一个IpRateLimitMiddleware和ClientRateLimitMiddleware,每个中间件可以根据不同的场景配置限制允许IP或客户端,自定义这些限制策略,也可以将限制策略应用在每个API URL或具体的HTTP Method上。
实践
起初是因为新做的项目中,有天查询日志发现,对外的几个公共接口经常被“恶意”调用,考虑到接口安全性问题,增加限流策略。
AspNetCoreRateLimit GayHub:https://github.com/stefanprodan/AspNetCoreRateLimit
根据IP进行限流
通过nuget安装AspNetCoreRateLimit,当前版本是3.0.5,因为实际项目中用的都是分布式缓存,在这里不用内存存储,而是结合Redis进行使用,内存存储直接参考官方的Wiki就可以了。
Install-Package AspNetCoreRateLimit Install-Package Microsoft.Extensions.Caching.Redis
在Startup.ConfigureServices中将服务和其他依赖注入
public void ConfigureServices(IServiceCollection services)
{
#region MVC
services.AddMvc(
options =>
{
options.UseCentralRoutePrefix(new RouteAttribute("api/"));
}
).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
#endregion services.AddDistributedRedisCache(options =>
{
options.Configuration = "127.0.0.1:6379,password=123456,connectTimeout=5000,syncTimeout=10000";
options.InstanceName = "WebRatelimit";
});
//加载配置
services.AddOptions();
//从appsettings.json获取相应配置
services.Configure<IpRateLimitOptions>(Configuration.GetSection("IpRateLimiting")); //注入计数器和规则存储
services.AddSingleton<IIpPolicyStore, DistributedCacheIpPolicyStore>();
services.AddSingleton<IRateLimitCounterStore, DistributedCacheRateLimitCounterStore>(); services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
//配置(计数器密钥生成器)
services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
}
在Startup.Configure启用
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
//启用限流,需在UseMvc前面
app.UseIpRateLimiting();
app.UseMvc();
}
为了不影响appsettings.json的美观吧,可以新建一个RateLimitConfig.json,并Program中启动加载中增加
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>().ConfigureAppConfiguration((host,config)=>
{
config.AddJsonFile($"RateLimitConfig.json", optional: true, reloadOnChange: true);
});
RateLimitConfig.json 配置如下:
{
"IpRateLimiting": {
//false则全局将应用限制,并且仅应用具有作为端点的规则* 。 true则限制将应用于每个端点,如{HTTP_Verb}{PATH}
"EnableEndpointRateLimiting": true,
//false则拒绝的API调用不会添加到调用次数计数器上
"StackBlockedRequests": false,
"RealIpHeader": "X-Real-IP",
"ClientIdHeader": "X-ClientId",
"HttpStatusCode": ,
"QuotaExceededResponse": {
"Content": "{{\"code\":429,\"msg\":\"访问过于频繁,请稍后重试\",\"data\":null}}",
"ContentType": "application/json",
"StatusCode":
},
"IpWhitelist": [ ],
"EndpointWhitelist": [],
"ClientWhitelist": [],
"GeneralRules": [
{
"Endpoint": "*:/api/values/test",
"Period": "5s",
"Limit":
}
]
}
}
重要配置说明:
QuotaExceededResponse 是自定义返回的内容,所以必须设置HttpStatusCode和StatusCode为200。
GeneralRules是具体的策略,根据不同需求配置不同端点即可, Period的单位可以是s, m, h, d,Limint是单位时间内的允许访问的次数;
IpWhitelist是IP白名单,本地调试或者UAT环境,可以加入相应的IP,略过策略的限制;
EndpointWhitelist是端点白名单,如果全局配置了访问策略,设置端点白名单相当于IP白名单一样,略过策略的限制;
其他配置项请参考Wiki:https://github.com/stefanprodan/AspNetCoreRateLimit/wiki/IpRateLimitMiddleware#setup
Fiddler开始测试
测试接口:http://127.0.0.1:5000/api/values/Test
[HttpGet]
public object test()
{
return "ok";
}
调用结果:

调用次数和剩余调用次数在Head可以看到,(吃我一个链接:https://www.cnblogs.com/EminemJK/p/12720691.html)

如果调用超过策略后,调用失败,返回我们自定义的内容

在Redis客户端可以看到策略的一些情况,
其他
通常在项目中,Authorization授权是少不了了,加入限流后,在被限流的接口调用后,限流拦截器使得跨域策略失效,故重写拦截器中间件,继承IpRateLimitMiddleware 即可:
public class IPLimitMiddleware : IpRateLimitMiddleware
{
public IPLimitMiddleware(RequestDelegate next, IOptions<IpRateLimitOptions> options, IRateLimitCounterStore counterStore, IIpPolicyStore policyStore, IRateLimitConfiguration config, ILogger<IpRateLimitMiddleware> logger)
: base(next, options, counterStore, policyStore, config, logger)
{
} public override Task ReturnQuotaExceededResponse(HttpContext httpContext, RateLimitRule rule, string retryAfter)
{
httpContext.Response.Headers.Append("Access-Control-Allow-Origin", "*");
return base.ReturnQuotaExceededResponse(httpContext, rule, retryAfter);
}
}
然后修改Startup.Configure,
//启用限流,需在UseMvc前面
//app.UseIpRateLimiting();
app.UseMiddleware<IPLimitMiddleware>();
app.UseMvc();
特别需要注意的坑是,在其他文章的教程中,他们会写成:
app.UseMiddleware<IPLimitMiddleware>().UseIpRateLimiting();//错误的演示 https://www.cnblogs.com/EminemJK/p/12720691.html
这些写你测试的时候会发现,

X-Rate-Limit-Remaining 递减量会变成2,而正常的递减量应该是1,举栗子,配置如下:
"Endpoint": "*:/api/values/test",
"Period": "3s",
"Limit":
表示3秒内可以访问的次数是一次,当发生调用的时候会直接返回被限制的提示,而不能正常访问接口,原因就是因为调用了两次中间件。
最后
AspNetCoreRateLimit还可以根据客户端ID进行配置策略,具体可以看一下官方的Wiki吧。
.Net Core结合AspNetCoreRateLimit实现限流的更多相关文章
- 重新整理 .net core 实践篇————熔断与限流[三十五]
前言 简单整理一下熔断与限流,跟上一节息息相关. 正文 polly 的策略类型分为两类: 被动策略(异常处理.结果处理) 主动策略(超时处理.断路器.舱壁隔离.缓存) 熔断和限流通过下面主动策略来实现 ...
- 【Dnc.Api.Throttle】适用于.Net Core WebApi接口限流框架
Dnc.Api.Throttle 适用于Dot Net Core的WebApi接口限流框架 使用Dnc.Api.Throttle可以使您轻松实现WebApi接口的限流管理.Dnc.Api.Thr ...
- ASP.NET Core WebApi AspNetCoreRateLimit 限流中间件学习
AspNetCoreRateLimit介绍: AspNetCoreRateLimit是ASP.NET核心速率限制框架,能够对WebApi,Mvc中控制限流,AspNetCoreRateLimit包包含 ...
- .Net Core:限流
一.环境 1.vs2019 2..Net Core 3.1 3.引用 AspNetCoreRateLimit 4.0.1 二.基础使用 1.设置 在Startup文件中配置如下,把配置项都放在前面: ...
- 【.NET Core项目实战-统一认证平台】第七章 网关篇-自定义客户端限流
[.NET Core项目实战-统一认证平台]开篇及目录索引 上篇文章我介绍了如何在网关上增加自定义客户端授权功能,从设计到编码实现,一步一步详细讲解,相信大家也掌握了自定义中间件的开发技巧了,本篇我们 ...
- .Net Core使用Ocelot网关(一) -负载,限流,熔断,Header转换
1.什么是API网关 API网关是微服务架构中的唯一入口,它提供一个单独且统一的API入口用于访问内部一个或多个API.它可以具有身份验证,监控,负载均衡,缓存,请求分片与管理,静态响应处理等.API ...
- .net core使用ocelot---第四篇 限流熔断
简介 .net core使用ocelot---第一篇 简单使用 .net core使用ocelot---第二篇 身份验证 .net core使用ocelot---第三篇 日志记录 前几篇文章我们陆续介 ...
- ASP.NET Core中如何对不同类型的用户进行区别限流
老板提出了一个新需求,从某某天起,免费用户每天只能查询100次,收费用户100W次. 这是一个限流问题,聪明的你也一定想到了如何去做:记录用户每一天的查询次数,然后根据当前用户的类型使用不同的数字做比 ...
- ASP.NET Core中使用令牌桶限流
在限流时一般会限制每秒或每分钟的请求数,简单点一般会采用计数器算法,这种算法实现相对简单,也很高效,但是无法应对瞬时的突发流量. 比如限流每秒100次请求,绝大多数的时间里都不会超过这个数,但是偶尔某 ...
随机推荐
- angular 中嵌套 iframe 报错
错误如下 Error: unsafe value used in a resource URL context at DomSanitizationServiceImpl.sanitize... 解决 ...
- Java基础 - 原码、反码、补码
目录 机器数 真值 原码 反码 补码 为什么使用原码. 反码. 补码 机器数 所有数字在计算机底层都是以二进制形式存在的.它的表现形式叫做机器数,这个数有正负之分,最高位为符号位.0 表示正数, 1 ...
- hdu1226超级密码 bfs
题目链接:http://icpc.njust.edu.cn/Problem/Hdu/1226/ 题目大意是:寻找一个五百位之内的C进制密码,该密码是N的正整数倍,而且只能用给定的数构成密码,求这样的密 ...
- 嘉泽 P2120: 【基础】半质数 题解
原题链接 简要题意: 求区间内能分解为两个质数乘积的数. 欧拉筛先筛素数. 然后再筛答案. 时间复杂度: \(O(n)\). 实际得分:\(100pts\). #pragma GCC optimize ...
- 【Code Force】Round #589 (Div. 2) D、Complete Tripartite
题目链接 大致题意 把一个图分成三块,要求任意两块之间是完全图,块内部没有连线 分析 首先根据块内没有连线可以直接分成两块 假定点1是属于块1的,那么所有与点1连接的点,都不属于块1:反之则是块1的 ...
- MySQL 教程--检视阅读
MySQL 教程--检视阅读 准备:Windows 上安装 MySQL 教程地址,PHP语言基础 教程地址2 教程地址3,有讲数据库的备份和恢复 教程地址4,w3c.china,php基础,扩展阅读 ...
- 从源码和doc揭秘——Java中的Char究竟几个字节,Java与Unicode的关系
#编码与字符编码 (懂编码的建议直接跳过) 在计算机世界中,任何事物都是用二进制图片数字表示的,图片可以编码为JPG,PNG格式的字节流,音频,视频有MP3,MP4格式的字节流.这些JPG,MP3等都 ...
- linux service 例子
在 /etc/init.d/ 中创建新文件 #/bin/sh # 检查第一个参数是什么来执行对应动作 case $1 in start) /usr/local/php/bin/php-cgi -b 1 ...
- iOS hash
一.iOS hash 下图列出 Hash 在 iOS 中的应用分析整理 知乎上的一句话: 算法.数据结构.通信协议.文件系统.驱动等,虽然自己不写那些东西,但是了解其原理对于排错.优化自己的代码有很大 ...
- mabatis入门五 高级结果映射
一.创建测试的表和数据 1.创建表 1CREATE TABLE items ( 2 id INT NOT NULL AUTO_INCREMENT, 3 itemsname VARCHAR(32) NO ...