.NetCore——AspNetCoreRateLimit简单使用
.NetCore——AspNetCoreRateLimit简单使用
一、介绍
在做项目的时候给到需求对接口进行限流,防止恶意刷接口。在网上找了资料使用了AspNetCoreRateLimit限流中间件,在这我分享一下我的一些 总结与解读 。。。。 接下来我们就开启限流之路
二、安装
我们先安装AspNetCoreRateLimit
在NuGet或 Install-Package AspNetCoreRateLimit 命令安装
三、配置
先注册服务
public void ConfigureServices(IServiceCollection services) { // needed to load configuration from appsettings.json services.AddOptions(); // needed to store rate limit counters and ip rules services.AddMemoryCache(); //load general configuration from appsettings.json services.Configure<IpRateLimitOptions>(Configuration.GetSection("IpRateLimiting")); //load ip rules from appsettings.json services.Configure<IpRateLimitPolicies>(Configuration.GetSection("IpRateLimitPolicies")); // inject counter and rules stores services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>(); services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>(); // Add framework services. services.AddMvc(); // https://github.com/aspnet/Hosting/issues/793 // the IHttpContextAccessor service is not registered by default. // the clientId/clientIp resolvers use it. services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); // configuration (resolvers, counter key builders) services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>(); }
在官方文档中写的是要先注册这个中间件然后在注册其他的组件。
注册服务的时候,一定要有下面这两个否则会不生效
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
然后在添加中间件
在此处这个 app.UseIpRateLimiting(); 一定要放在mvc的前边 不然的话 不会生效的。 此处由于我自己 重写了插件本身的一些方法,所以此处是 app.UseMiddleware<IP.CustomizationLimitMiddleware>().UseIpRateLimiting(); 这样的,如果重写的类(CustomizationLimitMiddleware)不放在这里 重写的也是不会生效的
这些配置好以后呢 开始配置限制规范
"IpRateLimiting": { "EnableEndpointRateLimiting": true, "StackBlockedRequests": false, "RealIpHeader": "X-Real-IP", "ClientIdHeader": "X-ClientId", "IpWhitelist": null, "EndpointWhitelist": null, "HttpStatusCode": 429, "QuotaExceededResponse": { "Content": "{{ \"message\": \"Too many requests,Please try again in {2} second(s).\", \"code\": 429,\"data \":\"\"}}", "ContentType": "application/json" }, "GeneralRules": [ { "Endpoint": "*", "Period": "1s", "Limit": 1 } ] },
在appsettings.json文件里面填入这段代码
此处的IpRateLimiting节点是注册服务里面读取的IpRateLimiting
下面咱们开始了解一下里面的参数吧
EnableEndpointRateLimiting:当为True的时候 例如设置了5次每分钟访问限流,当你getData()5次过后禁止访问,但是还可以访问postData()5次,总得来说是每个接口都有5次在这一分钟,互不干扰。
当为False的时候 每个接口都加入计数,不管你访问哪个接口 只要在一分钟内累计够5次 将禁止访问
StackBlockedRequests:设置为false,则拒绝的呼叫不会添加到油门计数器。如果客户每秒发出3个请求,而您设置的限制为每秒一个呼叫,则其他限制(例如每分钟或每天)将仅记录第一个呼叫,而该呼叫未被阻止。如果您希望被拒绝的请求计入其他限制,则必须设置StackBlockedRequests为true
RealIpHeader:使用时,你的红隼服务器背后是一个反向代理,如果你的代理服务器使用不同的页眉然后提取客户端IP X-Real-IP使用此选项来设置它
ClientIdHeader :被用于提取白名单的客户端ID。如果此标头中存在客户端ID,并且与ClientWhitelist中指定的值匹配,则不应用速率限制
- 这里 ClientIdHeader的ID限制 跟 IP限制都是一样的 细节处有些许不同
services.Configure<ClientRateLimitOptions>(Configuration.GetSection("ClientRateLimiting")); //load client rules from appsettings.json services.Configure<ClientRateLimitPolicies>(Configuration.GetSection("ClientRateLimitPolicies"));
- IP注册服务的时候是 IpRateLimiting 和 IpRateLimitPolicies ,现在ID注册服务替换成 ClientRateLimiting 和 ClientRateLimitPolicies
- RateLimiting 结尾的节点是用来初始化自定义的一些设置
- RateLimitPolicies 结尾的节点是用来单独定义白名单里面的 覆盖特定客户
IpWhitelist 和 ClientWhitelist 这两个都是用来设置白名单的 区别在与前者通过IP设置 后者通过请求ID设置
"IpWhitelist": [ "::1","::10" ],
"ClientWhitelist ":[" dev-id-1 ", "dev-id-2 " ],
HttpStatusCode:用来设置返回状态码
QuotaExceededResponse:设置返回提示信息
GeneralRules:在这里设置你的限制条件,可以设置多种条件,可以针对IP、接口
下面这个是全部 每秒最多访问一次
{ "Endpoint": "*",//端点 "Period": "1s",//周期 s秒 m分钟 h时 d天 "Limit": 1 //次数 }
还有具体到控制器、方法、请求方式 下面依次贴几个例子
控制:
{ "Endpoint":"*:api/values", "Period":"1s", "Limit":1 }
Endpoint 现在的值 values控制器里面的所有方法
"get:api/values" //values控制器下所有的Get请求 get改成post的话就是所有的Post请求
我在控制器里面 改的路由是这样的
我自己测试的时候这个没法具体到控制器与哪种请求 只能具体到方法 应该是我后边设置了/[action]的问题
在开发中的时候一定要注意这里!!!
下面是ID的设置方式
{ "ClientId": "client-id-1", "Rules": [ { "Endpoint": "*", "Period": "1s", "Limit": 10 }, { "Endpoint": "*", "Period": "15m", "Limit": 200 } ] },
根据自己的需求设置了 这些以后就Ok了!
四、扩展
在注册服务的时候可以这样写 把读取appsetting.json文件中的 IpRateLimiting 节点替换,然后这样写。
以 RateLimitPolicies 结尾的 IP 和 ID 的节点这样写也是可以的
后台方法重写
这个Class是用于重写的插件本身的一些方法,在上边添加中间件的时候,简单的有提过。因为我在项目开发的时候 需要将请求频繁的IP存储到数据库进行记录,所以我用到了 ReturnQuotaExceededResponse() 这个方法, 只要插件识别到 请求过于频繁就会走这个方法。
在这个方法中可以定义返回的信息,在这里设置过后 会替换掉初始的时候设置的值,也可以在这个方法里得到请求过于频繁的IP。
ResolveIdentity() 这个看的文档说是可以自定义拦截逻辑的 我也没有用到 就重写了一下试试 。
这里面还有记录Log的方法可以重写
注意!坑!!!
你在官方文档复制了这个class里面的code会报错
现在贴出我写的,改了点东西,已经不报错,而且暂时还没有问题
public class CustomizationLimitMiddleware : IpRateLimitMiddleware { private readonly IpRateLimitOptions _options; private readonly IIpPolicyStore _ipPolicyStore; public CustomizationLimitMiddleware(RequestDelegate next, IOptions<IpRateLimitOptions> options, IRateLimitCounterStore counterStore, IIpPolicyStore policyStore, IRateLimitConfiguration config, ILogger<IpRateLimitMiddleware> logger, IIpAddressParser ipParser = null) : base(next, options, counterStore, policyStore, config, logger) { _options = options.Value; _ipPolicyStore = policyStore; } /// <summary> ///重写的此方法 可以自定义逻辑 暂时搁置 /// </summary> /// <param name="httpContext"></param> /// <returns></returns> public override ClientRequestIdentity ResolveIdentity(HttpContext httpContext) { var clientId = "anon"; if (httpContext.Request.Headers.Keys.Contains(_options.ClientIdHeader, StringComparer.CurrentCultureIgnoreCase)) { clientId = httpContext.Request.Headers[_options.ClientIdHeader].First(); } return new ClientRequestIdentity { Path = httpContext.Request.Path.ToString().ToLowerInvariant(), HttpVerb = httpContext.Request.Method.ToLowerInvariant(), ClientId = clientId }; } /// <summary> /// 当请求过于频繁时 接口重写 /// </summary> /// <param name="httpContext"></param> /// <param name="rule"></param> /// <param name="retryAfter"></param> /// <returns></returns> public override Task ReturnQuotaExceededResponse(HttpContext httpContext, RateLimitRule rule, string retryAfter) { var message = string.Format("{{ \"message\": \"请求过于频繁,请在{2}秒后在重新尝试.\", \"code\": 429,\"data \":\"\"}}", rule.Limit, rule.Period, retryAfter); if (!_options.DisableRateLimitHeaders) { httpContext.Response.Headers["Retry-After"] = retryAfter; } httpContext.Response.StatusCode = _options.QuotaExceededResponse?.StatusCode ?? _options.HttpStatusCode; httpContext.Response.ContentType = _options.QuotaExceededResponse?.ContentType ?? "text/plain"; return httpContext.Response.WriteAsync(message); } }
插件开发者Demo、文档直通车: 请坐好,即将起飞!
好了!就到此结束了!
希望在这条不归路上,越走越远!
- 点赞 1
- 收藏
- 分享
- 文章举报
- ASP.NET Core WebApi AspNetCoreRateLimit 限流中间件学习
- AspnetCore WebApi使用Swagger简单入门
- 在ASP.NET中使用AJAX的简单方法
- ASP.NET使用确认对话框得简单方法
- ASP.NET AJAX 无刷新显示时间 Timer控件简单使用
- ASP 技巧一则之 简化创建关闭记录集对象并创建使用简单的MSSQL存储过程 By shawl.qiu
- Asp.Net使用POST方法最简单的实现
- array grid的简单使用.根据官方示例改写(asp.net).json数据格式.
- asp.net MVC + linq to Entity简单教程(五)linq to Entity中join的使用以及子查询
- asp.net 2.0 FileUpload控件的简单使用
- 在ASP.NET中使用AJAX的简单方法
- ASP.NET中存储过程的简单使用
- 简单实用的分页控件 AspNetPager.dll 下载地址、使用方法、含有代码示例
- ASP.NET报表简单使用示例-asp.net关注
- ASP.NET jQuery 食谱11 (通过使用jQuery validation插件简单实现用户登录页面验证功能)
- ASP.NET WebForm 分页控件 AspNetPager 使用的简单示例
- ASP.NET AJAX中 复杂数据类型使用简单实例
- asp.net中水晶报表的简单使用
- 使用ASP.NET实现Friendly URL的最简单方法
- 使用C# Builder建一个简单的ASP.NET应用程序