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 = ; /// <summary>
/// 一段时间长度(单位秒),必须大于等于1
/// </summary>
private static int partSecond = ; /// <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();
}
var nowTime = DateTime.Now;
if (isFailAddIn)
{
#region 请求被拒绝也需要加入当次请求
item.ReqTime.Add(nowTime);
if (item.ReqTime.Count >= maxTimes)
{
if (item.ReqTime[].AddSeconds(partSecond) > nowTime)
{
return false;
}
else
{
return true;
}
}
else
{
return true;
}
#endregion
}
else
{
#region 请求被拒绝就不需要加入当次请求了
if (item.ReqTime.Count >= maxTimes)
{
if (item.ReqTime[].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();
}
var nowTime = DateTime.Now;
if (isFailAddIn)
{
#region 请求被拒绝也需要加入当次请求
item.ReqTime.Add(nowTime); if (item.ReqTime.Count >= maxTimes)
{
if (item.ReqTime[].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[].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()
{ }
}

web api 限制单个IP在一定时间内访问次数的更多相关文章

  1. Web Api 2(Cors)Ajax跨域访问

    支持Ajax跨域访问ASP.NET Web Api 2(Cors)的简单示例教程演示   随着深入使用ASP.NET Web Api,我们可能会在项目中考虑将前端的业务分得更细.比如前端项目使用Ang ...

  2. 分ip统计网站访问次数

    package web.listener; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; ...

  3. Filter和Listener的应用——分IP统计网站访问次数

    一:分析 统计工作需要在所有资源执行前进行,所以需要放在filter中 这个拦截器仅仅进行统计工作,不进行拦截,所以请求必须继续传递下去 用Map<String,integer>来保存数据 ...

  4. ASP.NET Web API使用示例

    原文地址:https://blog.csdn.net/chinacsharper/article/details/21333311 上篇博客讲解rest服务开发时,曾经提到过asp.net mvc中的 ...

  5. asp.net mvc 5 web api 关于Requested resource does not support options 问题

    1.用visual studio 2015 建立一个 web api 应用程序.记住这是一个 web api 应用. 2.新建一个web api . 3.用C#访问,代码如下:[没有问题,返回正确] ...

  6. Web API应用架构在Winform混合框架中的应用(4)--利用代码生成工具快速开发整套应用

    前面几篇介绍了Web API的基础信息,以及如何基于混合框架的方式在WInform界面里面整合了Web API的接入方式,虽然我们看似调用过程比较复杂,但是基于整个框架的支持和考虑,我们提供了代码生成 ...

  7. ASP.NET MVC Web API使用示例

    上篇博客讲解rest服务开发时,曾经提到过asp.net mvc中的rest api,由于篇幅原因,没有在上篇博客中进行讲解,这里专门拿出来进行讨论.还是一样引用上次的案例,用asp.net mvc提 ...

  8. Xamarin.Android 调用Web Api(通过ListView展示远程获取的数据)

    xamarin.android如何调用sqlserver 数据库呢(或者其他的),很多新手都会有这个疑问.xamarin.android调用远程数据主要有两种方式: 在Android中保存数据或调用数 ...

  9. 前端使用AngularJS的$resource,后端ASP.NET Web API,实现增删改查

    AngularJS中的$resource服务相比$http服务更适合与RESTful服务进行交互.本篇后端使用ASP.NET Web API, 前端使用$resource,实现增删改查. 本系列包括: ...

随机推荐

  1. c与c++中的extern const的区别和联系

    最近复习c++,发现了这个东西. c语言里面,我们在一个.c文件中用const定义了一个全局变量后,可以在另一个.c文件中用extern const来引用,但在c++中在链接的时候会报undefine ...

  2. 转 -- Linux系列:Ubuntu虚拟机设置固定IP上网(配置IP、网关、DNS、防止resolv.conf被重写)

    原文转自:http://www.cnblogs.com/lanxuezaipiao/p/3613497.html#undefined 虚拟机里设置上网方式为NAT最方便,因为无需手动设置即可上网,但是 ...

  3. 【JAVA】"骗人"的“replaceAll”

    Java String类中有个方法叫:replaceAll,从表面上看,他的意思是把所有的regex替换成replacement. public String replaceAll(String re ...

  4. zepto - toggle

    <input type="text" value="123456789" /> <div id="too_long"> ...

  5. ServiceStack 介绍

    关于ServiceStack ServiceStack 官网介绍: Opensource .NET and Mono REST Web Services framework 什么是 ServiceSt ...

  6. JS思维之路菜鸟也能有大能量(1)--模拟push

    因为本系列文章属于思维类,所以不做基础方法的讲解. 任务:首先我定义了一个变量var arr = [0,1,2,3,4,5];我现在想模拟push方法在这个数组的5后面加东西,我们应该怎么做?给你5分 ...

  7. ES6入门系列一(基础)

    1.let命令 Tips: 块级作用域(只在当前块中有效) 不会变量提升(必须先申明在使用) 让变量独占该块,不再受外部影响 不允许重复声明 总之:let更像我们熟知的静态语言的的变量声明指令 ES6 ...

  8. Spring Remoting: Burlap--转

    原文地址:http://www.studytrails.com/frameworks/spring/spring-remoting-burlap.jsp Concept Overview In the ...

  9. Cocos2d-x SpriteFrameCache的使用

    根据官方文档与其他c++属性实现的类似书中示例: 图中的小人是会动的. 首先使用texturepacker制作出一张拼图,导出plist等文件: plist类似: 3.x的cocos似乎不再鼓励使用什 ...

  10. onhashchange事件,只需要修改hash值即可响应onhashchange事件中的函数(适用于上一题下一题和跳转页面等功能)

    使用实例: 使用onhashchange事件做一个简单的上一页下一页功能,并且当刷新页面时停留在当前页 html: <!DOCTYPE html><html><body& ...