最新要闻
- 能用到安卓17 三星承诺Galaxy S23系统升级4代、5年安全更新
- 交管部门:等红灯时玩手机也属分心驾驶
- 焦点播报:三星Galaxy S23系列创预售新纪录 官方送福利:存储容量免费升杯
- 世界动态:成本压力让用户扛!苹果利润正下降:iPhone 15或被迫涨价
- 情人节到了 ChatGPT忙着写情书!全球30%男性想用AI写情书
- 环球快看点丨男子情人节前点歌:外卖员上门唱一曲《老婆辛苦了》 妻子破防
- 世界今亮点!手机汽车深度互联:魅族新专利可用汽车呼吸灯提示手机信息
- 全球今热点:《满江红》周边下架:设计公司3人参保
- 奇瑞艾瑞泽8遭车主集体投诉:A柱漏风 车速超60km/h车内呼呼呼
- 曝马斯克有意45亿英镑收购曼联 卡塔尔财团也准备要约
- 《满江红》周边取消众筹:产品设计创意与网友理解存在偏差
- 蓝海市场不再!2022中国游戏产业报告发布:收入、用户规模下降明显
- 养生必备 青海正宗特优级头茬红枸杞500克18.9元大促
- 重点聚焦!从全屏广告到订阅付费 互联网模式为收割“韭菜”群魔乱舞
- 天天百事通!少林寺宣布与百度合作:接入百度版ChatGPT“文心一言”
- 当前视讯!美国18轮货车与一列火车相撞:致16节车厢出轨
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
当前快播:白嫖一个WebAPI限流解决方案
什么是API限流:
API 限流是限制用户在一定时间内 API 请求数量的过程。应用程序编程接口 (API) 充当用户和软件应用程序之间的网关。例如,当用户单击社交媒体上的发布按钮时,点击该按钮会触发 API 调用。此 API 与社交媒体应用程序的网络服务器进行交互,并执行发布操作。此用户可以是人,也可以是其他软件应用程序。
【资料图】
为什么要限流:
API 是组织最大的资产之一。API 可帮助网站或移动应用程序的用户完成任务。随着用户数量的增加,网站或移动应用程序开始出现性能下降的迹象。因此,拥有更好连接或更快界面的用户可能会获得比其他用户更好的体验。API 限流是一种巧妙的解决方案,可帮助组织确保其 API 的合理使用。
API 限流还有助于抵御拒绝服务 (DoS) 攻击,在 DoS 攻击中,恶意用户发送大量请求以使网站或移动应用程序崩溃。随着在线用户数量的增加,企业需要实施 API 限流机制,以确保公平使用、数据安全并防止恶意攻击。
API限流的原理:
虽然 API 限流有多种算法,但以下是所有 API 限流算法的基本步骤:
1.客户端/用户调用与网络服务或应用程序交互的 API。
2.API 限流逻辑会检查当前请求是否超过允许的 API 调用次数。
3.如果请求在限制范围内,API 将照常执行并完成用户的任务。
4.如果请求超出限制,API 会向用户返回错误响应。
5.用户必须等待预先约定的时间段,或者付费才能进行更多的 API 调用。
这里有篇文章介绍很全面,可以看一看《API 限流技术探索与实践》
这个限流方案也是在百度收集整理而来,我这里采取的是滑动算法:
我们需要准备几个类:
1.ApiAuthorize类
ApiAuthorize继承于IAuthorizationFilter(授权过滤器),和IAuthorizationFilter相同的还有其他三种过滤器,合起来称为四大过滤器,
另外三个分别是IResourceFilter资源过滤器(缓存接口的数据),IActionFilter动作过滤器(记录操作日志),IExceptionFilter(错误过滤器)
IAuthorizationFilter
public class CtmAuthorizationFilterAttribute : Attribute, IAuthorizationFilter{ public void OnAuthorization(AuthorizationFilterContext context) { // context.HttpContext.User.Claims context.HttpContext.Items["User"] = "HuangMing"; System.Console.WriteLine("OnAuthorization"); }}View Code
IResourceFilter
//Program.cs中注册缓存:builder.Services.AddSingletonView Code();builder.Services.AddSingleton ();var app = builder.Build();public class CtmResourceFilterAttribute : Attribute, IResourceFilter{ private readonly IMemoryCache _cache; public CtmResourceFilterAttribute(IMemoryCache cache) { this._cache = cache; } public void OnResourceExecuted(ResourceExecutedContext context) { var path = context.HttpContext.Request.Path.ToString(); if (context.Result != null) { var value = (context.Result as ObjectResult).Value.ToString(); _cache.Set(path, value,TimeSpan.FromHours(1)); } } public void OnResourceExecuting(ResourceExecutingContext context) { var path = context.HttpContext.Request.Path.ToString(); var hasValue = _cache.TryGetValue(path, out object value); if (hasValue) { context.Result = new ContentResult { Content = value.ToString() }; } }}
IActionFilter
public class CtmActionFilterAttribute : Attribute, IActionFilter{ public void OnActionExecuted(ActionExecutedContext context) { } public void OnActionExecuting(ActionExecutingContext context) { //从serviceProvider中获取Logger服务 var logger = context.HttpContext.RequestServices.GetServiceView Code>(); //获取路由地址 var path = context.HttpContext.Request.Path; //从RouteData字典中获取控制器名称 var controller = context.RouteData.Values["controller"]; //从RouteData字典中获取动作名称 var action = context.RouteData.Values["action"]; //从ActionArguments中获取接口参数 var arguments = string.Join(",", context.ActionArguments); logger.LogInformation($"访问的路由:{path},控制器是{controller},行为是{action},参数是{arguments}"); }} //当过滤器中需要使用依赖注入时,在使用属性标注时,需要使用如下方式:1.属性标注[TypeFilter(typeof(CtmActionFilterAttribute))] 2.从容器中获取服务var logger = context.HttpContext.RequestServices.GetService >();
IActionFilter
public class CtmExceptionFilterAttribute : Attribute, IExceptionFilter{ public void OnException(ExceptionContext context) { context.Result = new ContentResult{ Content =context.Exception.Message }; }}View Code
现在编写自己的项目代码
ApiAuthorize
public class ApiAuthorize : IAuthorizationFilter { public async void OnAuthorization(AuthorizationFilterContext context) { if (context.Filters.Contains(new MyNoAuthentication())) { return; } #region 用户请求限流 { string ip = context.HttpContext.Connection.RemoteIpAddress.ToString(); var cotrollaction = context.ActionDescriptor; string action = cotrollaction.RouteValues["action"].ToString(); string controller = cotrollaction.RouteValues["controller"].ToString(); if (string.IsNullOrWhiteSpace(ip) || string.IsNullOrWhiteSpace(controller) || string.IsNullOrWhiteSpace(action)) { context.Result = new JsonResult("系统正忙,请稍微再试!"); return; } ip = ip + ":" + controller + ":" + action; IPCacheInfoModel ipModel = IPCacheHelper.GetIPLimitInfo(ip); if (!ipModel.IsVisit) { context.Result = new JsonResult("系统正忙,请稍微再试!"); return; } string ACting = controller + ":" + action; IPCacheInfoModel ipModel2 = IPCacheHelper.GetIPLimitInfo(ACting); } #endregion #endregion } }View Code
然后编写 MyAuthentication类
MyAuthentication
///View Code/// 构造引用/// public class MyAuthentication : Attribute, IFilterMetadata { } public class MyNoAuthentication : Attribute, IFilterMetadata { }
以上两个可以做限流也能做鉴权,数据签名认证等
如果需要限流,我们还需要三个类:
IPActionFilterAttribute 信息返回类
using System;using System.Collections.Generic;using System.Net;using System.Net.Http;using System.Threading.Tasks;using System.Web.Http.Controllers;using System.Web.Http.Filters;namespace EvaluationSystem.XLAction{ ///View Code/// 限制单个IP短时间内访问次数 /// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] public class IPActionFilterAttribute : ActionFilterAttribute { ////// 限制单个IP短时间内访问次数 /// /// public override void OnActionExecuting(HttpActionContext actionContext) { string ip = actionContext.Request.ToString(); IPCacheInfoModel ipModel = IPCacheHelper.GetIPLimitInfo(ip); if (!ipModel.IsVisit) { // Logger.Warn(string.Format("IP【{0}】被限制了【{1}】次数", ipModel.IP, ipModel.Limit)); actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.BadRequest, "系统正忙,请稍微再试。"); return; } base.OnActionExecuting(actionContext); } }}
IPCacheHelper 请求记录类
using EvaluationSystem.HelpTool;using EvaluationSystem.HelpTool.GetSYSValue;using System;using System.Collections.Generic;namespace EvaluationSystem.XLAction{ ///View Code/// 限制单个IP访问次数 /// public class IPCacheHelper { ////// IP缓存集合 /// private static ListdataList = new List (); private static object lockObj = new object(); //SQLHelp ht = new SQLHelp(); public static string maxTimes1 = GetConfig.GetConfiguration("XLAction:maxTimes"); public static string partSecond1 = GetConfig.GetConfiguration("XLAction:partSecond"); /// /// 一段时间内,最大请求次数,必须大于等于1 /// private static int maxTimes = Convert.ToInt32(string.IsNullOrWhiteSpace(maxTimes1)? "0":maxTimes1); ////// 一段时间长度(单位秒),必须大于等于1 /// private static int partSecond = Convert.ToInt32(string.IsNullOrWhiteSpace(partSecond1) ? "0" : partSecond1); ////// 请求被拒绝是否加入请求次数 /// private static bool isFailAddIn = false; static IPCacheHelper() { } ////// 设置时间,默认maxTimes=3, partSecond=30 /// /// 最大请求次数 /// 请求单位时间 public static void SetTime(int _maxTimes, int _partSecond) { maxTimes = _maxTimes; partSecond = _partSecond; } ////// 检测一段时间内,IP的请求次数是否可以继续请求和使用 /// /// ip ///public static bool CheckIsAble(string ip) { lock (lockObj) { var item = dataList.Find(p => p.IP == ip); if (item == null) { item = new IPCacheInfoModel(); item.IP = ip; item.ReqTime.Add(DateTime.Now); dataList.Add(item); return true; } else { if (item.ReqTime.Count > maxTimes) { item.ReqTime.RemoveAt(0); } var nowTime = DateTime.Now; if (isFailAddIn) { #region 请求被拒绝也需要加入当次请求 item.ReqTime.Add(nowTime); if (item.ReqTime.Count >= maxTimes) { if (item.ReqTime[0].AddSeconds(partSecond) > nowTime) { return false; } else { return true; } } else { return true; } #endregion } else { #region 请求被拒绝就不需要加入当次请求了 if (item.ReqTime.Count >= maxTimes) { if (item.ReqTime[0].AddSeconds(partSecond) > nowTime) { return false; } else { item.ReqTime.Add(nowTime); return true; } } else { item.ReqTime.Add(nowTime); return true; } #endregion } } } } /// /// 检测一段时间内,IP的请求次数是否可以继续请求和使用 /// /// ip ///public static IPCacheInfoModel GetIPLimitInfo(string ip) { lock (lockObj) { var item = dataList.Find(p => p.IP == ip); if (item == null) //IP开始访问 { item = new IPCacheInfoModel(); item.IP = ip; item.ReqTime.Add(DateTime.Now); dataList.Add(item); item.IsVisit = true; //可以继续访问 return item; } else { if (item.ReqTime.Count > maxTimes) { item.ReqTime.RemoveAt(0); } var nowTime = DateTime.Now; if (isFailAddIn) { #region 请求被拒绝也需要加入当次请求 item.ReqTime.Add(nowTime); if (item.ReqTime.Count >= maxTimes) { if (item.ReqTime[0].AddSeconds(partSecond) > nowTime) { item.Limit++; //限制次数+1 item.IsVisit = false;//不能继续访问 return item; } else { item.IsVisit = true; //可以继续访问 return item; //单个IP30秒内 没有多次访问 } } else { item.IsVisit = true; //可以继续访问 return item; //单个IP访问次数没有达到max次数 } #endregion } else { #region 请求被拒绝就不需要加入当次请求了 if (item.ReqTime.Count >= maxTimes) { if (item.ReqTime[0].AddSeconds(partSecond) > nowTime) { item.Limit++; //限制次数+1 item.IsVisit = false;//不能继续访问 return item; } else { item.ReqTime.Add(nowTime); item.IsVisit = true; //可以继续访问 return item; } } else { item.ReqTime.Add(nowTime); item.IsVisit = true; //可以继续访问 return item; } #endregion } } } } }}
IPCacheInfoModel 实体类
using System;using System.Collections.Generic;namespace EvaluationSystem.XLAction{ public class IPCacheInfoModel { ///View Code/// IP /// public string IP { get; set; } ////// 限制次数 /// public int Limit { get; set; } ////// 是否可以访问 /// public bool IsVisit { get; set; } ////// 访问时间 /// private ListreqTime = new List (); /// /// 访问时间 /// public ListReqTime { get { return this.reqTime; } set { this.reqTime = value; } } }}
时间按秒算 private static int maxTimes ;请求次数 private static int partSecond ;
为了方便控制,不去修改我们的API程序,可以将这两个信息配置进appsettings.json文件里面
"XLAction": {//请求限流 秒钟一次 "maxTimes": "1", "partSecond": "1" }
为了获取appsettings.json来买你的信息,我们需要一个方法拿到json里面的信息
GetConfiguration
public class GetConfig { public static string GetConfiguration(string configKey) { var builder = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json"); var config = builder.Build(); if (configKey.Contains(":")) { return config.GetSection(configKey).Value;//获取分级参数值 } else { return config[configKey];//获取直级参数值 } //youdianwenti w xiangxiang } }View Code
以上工作准备完全后,在我们的Startup里面修改加入以下代码
如果有ConfigureServices类,添加如下
//注册guolv services.AddControllers(o => { o.Filters.Add
如果不是 如下添加
builder.Services.AddMvc(options => options.Filters.Add(new AuthorizeFilter()));
//注册guolvbuilder.Services.AddControllers(o =>{ o.Filters.Add
然后就大功告成
现在直接看结果
接着频繁操作
该方案来自网络加以修改,如有侵权,请联系删除
当前快播:白嫖一个WebAPI限流解决方案
音乐 APP 用户争夺战,火山引擎 VeDI 助力用户体验升级!
能用到安卓17 三星承诺Galaxy S23系统升级4代、5年安全更新
交管部门:等红灯时玩手机也属分心驾驶
焦点播报:三星Galaxy S23系列创预售新纪录 官方送福利:存储容量免费升杯
世界动态:成本压力让用户扛!苹果利润正下降:iPhone 15或被迫涨价
情人节到了 ChatGPT忙着写情书!全球30%男性想用AI写情书
环球快看点丨男子情人节前点歌:外卖员上门唱一曲《老婆辛苦了》 妻子破防
世界今亮点!手机汽车深度互联:魅族新专利可用汽车呼吸灯提示手机信息
全球今热点:《满江红》周边下架:设计公司3人参保
奇瑞艾瑞泽8遭车主集体投诉:A柱漏风 车速超60km/h车内呼呼呼
曝马斯克有意45亿英镑收购曼联 卡塔尔财团也准备要约
快资讯丨下载某乎专栏文章并存为markdown
当前播报:ChatGPT写代码水平惊艳到我,很性感但有点危险
记录--前端实现登录拼图验证
《满江红》周边取消众筹:产品设计创意与网友理解存在偏差
蓝海市场不再!2022中国游戏产业报告发布:收入、用户规模下降明显
养生必备 青海正宗特优级头茬红枸杞500克18.9元大促
重点聚焦!从全屏广告到订阅付费 互联网模式为收割“韭菜”群魔乱舞
天天百事通!少林寺宣布与百度合作:接入百度版ChatGPT“文心一言”
什么是Python装饰器?
焦点要闻:kubeadm的部署+Dashboard+以及连接私有仓库 Harbor
linux 基础(9)背景工作管理
从一次有趣的漏洞分析到一个有趣的PHP后门
当前动态:9 种跨域方式实现原理
观天下!特定领域知识图谱融合方案:学以致用-问题匹配鲁棒性评测比赛验证【四】
全球视点!除了ChatGPT,还能用什么计划管理软件提高效率?
旋转数组中的最小数字
今亮点!高效节能 | 智慧灯杆综合管理解决方案
全球百事通!各个编程语言的优缺点,你适合哪种?
当前视讯!美国18轮货车与一列火车相撞:致16节车厢出轨
23999元起 雷蛇新款灵刃18上架:可选RTX 4060/4070
全球滚动:老人直播间相亲多起来了 成不成就在三五分钟:网络红娘介绍对象
天天新资讯:上市三天狂揽1.5万订单 比亚迪秦PLUS DM-i有多火:店内水泄不通
苹果iOS 16.3.1修复多个错误:但Bug依旧存在
为SQL Server配置连接加密
天天短讯!什么是卷积
陕西现聚落遗址 西周墓葬有43个殉人!国内迄今最多
环球资讯:周黑鸭业绩大降超90% 绝味等也难过:不断涨价 年轻人越来越吃不起鸭脖
杰克琼斯1.8折大促:卫衣/针织衫79元起、牛仔裤119元起发车
世界动态:UP主欲沿大运河从杭州划船到北京 5公里后就被拦截
二维数组中的查找
全球信息:数学知识1.4
关于工具软件:Apipost和Apifox哪个更好用看这篇就够了
全球最资讯丨浪漫之极!杭州地铁口等地现玫瑰瀑布:情人节鲜花卖到1200元
全球快报:业务与研发一体化最佳突破口在何处?
快讯:Unity 转小游戏
环球热讯:基于开源IM即时通讯框架MobileIMSDK:RainbowChat v8.4版已发布
世界快播:Linux输入设备驱动
微资讯!壮观!马斯克星链卫星驶过西班牙夜空:宛若空中列车
【世界聚看点】小学生满分作文跑题老师含泪打5分:把“悔”看成“梅”
环球热资讯!特斯拉京东旗舰店开业:269元的U盘上架
首发16.2元:《仙剑奇侠传7》DLC《人间如梦》正式上线
ChatGPT版必应发飙!怒斥人类:放尊重些
天天快播:IM通讯协议专题学习(九):手把手教你如何在iOS上从零使用Protobuf
ChatGPT注册试用过程分享
全球观察:响应式圣经:10W字,实现Spring响应式编程自由
全球短讯!Unicorn 初探
7万起售 五菱缤果内饰官图发布:同级无敌手
世界上最轻VR头显面世:仅重127克 5K分辨率
环球新消息丨苹果汽车奇瑞造?“果链一哥”立讯与奇瑞签署合作 联手造车
当前动态:法拉第未来:预计FF 91将于4月底交付 但有个前提
不用第三方插件了:微软计划为Edge加入鼠标手势功能
qq空间主人寄语怎么删除?qq空间主人寄语大集合
开学的歌曲有哪些?开学的趣事作文模板
熟悉的人是什么意思?关于我最熟悉的人作文合集
皮脂腺分泌旺盛是什么原因?皮脂腺分泌旺盛怎么解决?
代表月亮消灭你是什么意思?代表月亮消灭你是谁的经典台词?
天天亮点!【AI】PTP时钟同步在智能驾驶系统里的重要性
天天微资讯!去掉Element 中el-input type=number时尾部上下箭头、禁用鼠标滚动
世界热点评!数组中找出只出现一次的两个数字
剑灵活力值在哪里显示?剑灵活力值怎么恢复?
ie图标不见了是怎么回事?ie图标不见了怎么恢复?
闪存和硬盘哪个重要?闪存和硬盘有什么区别?
料理机是干什么用的?料理机品牌十大排名
光纤路由器怎么设置?光纤路由器和宽带路由器一样吗?
速看:口味地道 丰富配料!渣渣灰南昌拌粉好价:4.9元/盒
全球新资讯:129元!小米2C1A三口GaN充电器上架:最高67W 兼容65W PD
天天信息:3秒俱乐部成员!极氪X官图公布:2750mm轴距百变魔方空间
63岁老人喝隔夜牛肉汤:结果住进ICU
黑龙江上空现不明飞行物速度极快 网友脑洞大开:LED风筝?
今日报丨程序员健康最佳作息表,建议收藏!!
必知必会的设计原则——合成复用原则
腾讯云企业网盘正式入驻数字工具箱
每日关注!软件开发入门教程网之Bootstrap4 信息提示框
【天天报资讯】适用于您企业的本地密码管理器丨Passwork产品介绍
瞧不起ChatGPT?苹果联合创始人:永远取代不了人类
【天天播资讯】热狗车三元催化被盗
宁德时代赴美建厂 官方回应:属实!福特出地出厂房
天天微头条丨丰田考斯特绝佳替代品 红旗全新中巴亮相:3.0T能坐23人
世界视讯!情人节前夕 东极岛海誓山盟石碑碎了 网友:承受太多誓言
百事通!RTX 4060桌面显卡被砍得面目全非:说好的万人迷呢?
匠人精神也不行!日本制造加速下滑:破产企业数量激增 汽车、电子业空心化
当前动态:情人节的垃圾桶成了“致富秘笈”?能捡到鲜花蛋糕等:网友戏称拆“爱情盲盒”
拒绝刹车失灵等污名化!美国还特斯拉清白:2年前车祸是司机醉酒超速
今日热议:微信情人节限定状态上线!撒狗粮/吃狗粮专属状态你选谁?
ChatGPT:Are You Ok是卢伟冰唱的 雷军不是专业歌手
世界新消息丨读Java实战(第二版)笔记09_函数式的思考
【当前独家】今天情人节 微信可以发520元红包 律师提醒:分手可能要不回
当前聚焦:曝马斯克有意45亿镑收购曼联:去年曾现身世界杯看球