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 = ; /// <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在一定时间内访问次数的更多相关文章
- Web Api 2(Cors)Ajax跨域访问
支持Ajax跨域访问ASP.NET Web Api 2(Cors)的简单示例教程演示 随着深入使用ASP.NET Web Api,我们可能会在项目中考虑将前端的业务分得更细.比如前端项目使用Ang ...
- 分ip统计网站访问次数
package web.listener; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; ...
- Filter和Listener的应用——分IP统计网站访问次数
一:分析 统计工作需要在所有资源执行前进行,所以需要放在filter中 这个拦截器仅仅进行统计工作,不进行拦截,所以请求必须继续传递下去 用Map<String,integer>来保存数据 ...
- ASP.NET Web API使用示例
原文地址:https://blog.csdn.net/chinacsharper/article/details/21333311 上篇博客讲解rest服务开发时,曾经提到过asp.net mvc中的 ...
- 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#访问,代码如下:[没有问题,返回正确] ...
- Web API应用架构在Winform混合框架中的应用(4)--利用代码生成工具快速开发整套应用
前面几篇介绍了Web API的基础信息,以及如何基于混合框架的方式在WInform界面里面整合了Web API的接入方式,虽然我们看似调用过程比较复杂,但是基于整个框架的支持和考虑,我们提供了代码生成 ...
- ASP.NET MVC Web API使用示例
上篇博客讲解rest服务开发时,曾经提到过asp.net mvc中的rest api,由于篇幅原因,没有在上篇博客中进行讲解,这里专门拿出来进行讨论.还是一样引用上次的案例,用asp.net mvc提 ...
- Xamarin.Android 调用Web Api(通过ListView展示远程获取的数据)
xamarin.android如何调用sqlserver 数据库呢(或者其他的),很多新手都会有这个疑问.xamarin.android调用远程数据主要有两种方式: 在Android中保存数据或调用数 ...
- 前端使用AngularJS的$resource,后端ASP.NET Web API,实现增删改查
AngularJS中的$resource服务相比$http服务更适合与RESTful服务进行交互.本篇后端使用ASP.NET Web API, 前端使用$resource,实现增删改查. 本系列包括: ...
随机推荐
- 十、EnterpriseFrameWork框架的分层架构及意义(控制器、业务对象、实体、Dao之间关系)
本章内容主要包括两个方面,一.是框架分层(控制器.业务对象.实体.Dao)的详细说明,二.是对比常用三层结构的区别和优势: 本文要点: 1.框架中的各个分层详细说明 2.对比常用三层结构的区别和优势 ...
- 【eoe 6】ActionBar的使用
一. Action Bar 一般位于屏幕顶部,包括四个可操作区域: 应用图标或LOGO区域,用于视图控制的Spinner下拉菜单或TAB控件区域, Action button(也称为Action It ...
- Visual Studio 2015开发Android App启动调试始终无法完成应用部署的解决方案
创建一个Android App项目后,直接启动调试发现Visual Studio Emulator for Android已成功运行,但应用始终处于Build中(等待时间超过1小时),并未如预期通过a ...
- NoSql---MongoDB基本操作
MongoDB 最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语 言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引.最后由于 MongoDB 可以支 ...
- SNF开发平台WinForm之七-单据打印和使用说明-SNF快速开发平台3.3-Spring.Net.Framework
8.1运行效果: 8.2开发实现: 1. 先要创建.grf报表模版,指定数据列.存储位置:Reports\Template文件夹下 2. 之后在程序当中查出数据,之后把数据和打印模版 传入方法进行 ...
- SmartDoc(YUIDoc) 注释编写
上面介绍了JS文档和Demo生成工具SmartDoc,本篇开始介绍一下注释的编写.SmartDoc使用的是YUIDoc的引擎,所以的注释规则都一样,先简单介绍下YUIDoc的注释编写. 编写注释是一个 ...
- 二叉查找树(二)之 C++的实现
概要 上一章介绍了"二叉查找树的相关理论知识,并通过C语言实现了二叉查找树".这一章给出二叉查找树的C++版本.这里不再对树的相关概念进行介绍,若遇到不明白的概念,可以在上一章查找 ...
- [Design Patterns] 1. Primary concept & term - UML
It's time to review design patterns, especially when I reach the turning-point of my career. That's ...
- [转载]SharePoint 2013测试环境安装配置指南
软件版本 Windows Server 2012 标准版 SQL Server 2012 标准版 SharePoint Server 2013 企业版 Office Web Apps 2013 备注: ...
- [C] static和extern的作用
static: 当用于函数定义或者代码块之外的变量声明时,static关键字用于修改标识符的链接属性,从external改为internal. 当用于代码块内部的变量声明时,static关键字用于修改 ...