web api 限制單個IP在必定時間內訪問次數

ps:下面實例是每隔30秒訪問次數不超過3次緩存

一、Filter:async

 

複製代碼

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);
        }

    }
}

複製代碼

 

 

二、IPCacheHelper:ide

 

複製代碼

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
                    }
                }
            }
        }
    }
}

複製代碼

 

 

三、IPCacheInfoModel:this

 

複製代碼

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; }
        }
    }
}

複製代碼

 

四、Action:spa

 

複製代碼

/// <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()
        {
         
        }
   }
相關文章
相關標籤/搜索