zoukankan      html  css  js  c++  java
  • web api 限制单个IP在一定时间内访问次数

    ps:下面实例是每隔30秒访问次数不超过3次

    1、Filter:

    using Infrastructure.Log;
    using Infrastructure.Web;
    using Lemon.Stats.Model;
    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 Lemon.Stats.Apis
    {
        /// <summary>
        /// 限制单个IP短时间内访问次数
        /// </summary>
        [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
        public class IPActionFilterAttribute : ActionFilterAttribute
        {
            /// <summary>
            /// 限制单个IP短时间内访问次数
            /// </summary>
            /// <param name="actionContext"></param>
            public override void OnActionExecuting(HttpActionContext actionContext)
            {
                string ip = HttpHelper.GetClientIp(actionContext.Request);
                //var isValid = IPCacheHelper.CheckIsAble(ip);
                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);
            }
    
        }
    }

    2、IPCacheHelper:

    using Lemon.Stats.Model;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Lemon.Stats.Apis
    {
        /// <summary>
        /// 限制单个IP访问次数
        /// </summary>
        public class IPCacheHelper
        {
             /// <summary>         
            /// IP缓存集合          
            /// </summary>       
            private static List<IPCacheInfoModel> dataList = new List<IPCacheInfoModel>();
    
            private static object lockObj = new object();
    
            /// <summary>        
            /// 一段时间内,最大请求次数,必须大于等于1
            ///</summary> 
            private static int maxTimes = 3;
    
            /// <summary>  
            /// 一段时间长度(单位秒),必须大于等于1     
            /// </summary>
            private static int partSecond = 30;
    
            /// <summary>  
            /// 请求被拒绝是否加入请求次数    
            /// </summary>  
            private static bool isFailAddIn = false;
    
            static IPCacheHelper()
            { 
            
            }
    
            /// <summary>      
            /// 设置时间,默认maxTimes=3, partSecond=30         
            /// </summary>        
            /// <param name="_maxTimes">最大请求次数</param>        
            /// <param name="_partSecond">请求单位时间</param>         
            public static void SetTime(int _maxTimes, int _partSecond)
            {
                maxTimes = _maxTimes;
                partSecond = _partSecond;
            }
    
            /// <summary>    
            /// 检测一段时间内,IP的请求次数是否可以继续请求和使用  
            /// </summary>        
            /// <param name="ip">ip</param>   
            /// <returns></returns>       
            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
                        }
                    }
                }
            }
    
    
            /// <summary>    
            /// 检测一段时间内,IP的请求次数是否可以继续请求和使用  
            /// </summary>        
            /// <param name="ip">ip</param>   
            /// <returns></returns>       
            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
                        }
                    }
                }
            }
        }
    }

    3、IPCacheInfoModel:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Lemon.Stats.Model
    {
        public class IPCacheInfoModel
        {
            /// <summary>
            /// IP 
            /// </summary>
            public string IP { get; set; }
    
            /// <summary>
            /// 限制次数
            /// </summary>
            public int Limit { get; set; }
    
            /// <summary>
            /// 是否可以访问
            /// </summary>
            public bool IsVisit { get; set; }
    
            /// <summary>
            /// 访问时间
            /// </summary>
            private List<DateTime> reqTime = new List<DateTime>();
            
            /// <summary>
            /// 访问时间
            /// </summary>
            public List<DateTime> ReqTime
            {
                get { return this.reqTime; }
                set { this.reqTime = value; }
            }
        }
    }

    4、Action:

    /// <summary>
        /// IP,PV(VV),UV,注册用户点击量统计
        /// 先执行IPActionFilter过滤器,再执行ChannelActionFilter过滤器
        /// 先执行后面的过滤器,再执行前面的过滤器,执行方式倒序执行顺序
        /// </summary>
        [ChannelActionFilter, IPActionFilter, RoutePrefix("Stats")]
        public class StatsController : ApiController
        {
    
            /// <summary>
            /// 每次页面点击都统计数据,直接由客户端调用
            /// Header中加入SecretKey,AppKey,UniqueKey
            /// </summary>
            /// <returns></returns>
            [HttpGet, Route("")]
            public async Task Get()
            {
             
            }
       }
  • 相关阅读:
    windows10家庭版安装docker踩坑解决记录
    sequelize Getters, Setters & Virtuals
    sequelize模型增删改查询(基础)Model Querying
    sequelize数据库模型关联文档详解
    Nginx配置实现下载文件
    Linux常用命令记录
    nodejs后台如何请求第三方接口request-promise简介及其废弃后的替代方案推荐got、axios
    新版本chrome浏览器(80版本以后)带来的跨域请求cookie丢失问题
    谷歌浏览器 Cookie 的 SameSite 属性 (转)
    JavaScript Image对象 整理
  • 原文地址:https://www.cnblogs.com/zoro-zero/p/6208213.html
Copyright © 2011-2022 走看看