using System;
using System.Collections;
using System.Data;
using System.ServiceModel;
using System.ServiceModel.Channels;
namespace CSFrameworkV5.Core.SystemSecurity
{
///
/// 用于检测非法攻击WCF的接口,用户连续访问的次数超过指定值抛出异常中断操作
///
public static class AttackRecorder
{
//限制指定时间范围内,当前用户可以访问服务端的次数
//此值不能太大,否则缓存表记录数较多,记录最后10次访问记录
private const int LAST_VISIT_COUNT = 20;
//与 LAST_VISIT_COUNT参数配合使用,比如限制用户3秒内只能访问30次后台的接口
//时间间隔(秒),大于此参数值,可能存在恶意攻击行为
private const int LIMIT_SECONDS = 5;
//记录访客IP信息及访问记录
private static Hashtable _VisitorList;
static AttackRecorder()
{
_VisitorList = new Hashtable();
}
///
/// 建立访问记录表
///
///
private static DataTable CreataTable()
{
var dt = new DataTable();
dt.Columns.Add("IP", typeof(string)); //IP地址
dt.Columns.Add("VisitTime", typeof(DateTime)); //访问时间
return dt;
}
///
/// 取当前用户的IP(客户端)
///
///
public static string ClientIP
{
get
{
try
{
var context = OperationContext.Current;
var properties = context.IncomingMessageProperties;
var endpoint =
properties[RemoteEndpointMessageProperty.Name] as
RemoteEndpointMessageProperty;
return endpoint.Address;
}
catch
{
return "无法获取IP";
}
}
}
private static DateTime ToDateTimeEx(object o)
{
if (null == o) return DateTime.MinValue;
try
{
var dt = Convert.ToDateTime(o.ToStringEx());
if (dt < DateTime.Parse("1900-01-01"))
return DateTime.Parse("1900-01-01");
else
return dt;
}
catch
{
return DateTime.MinValue;
}
}
///
/// 检查用户访问量,如有恶意攻击行为抛出异常
///
public static void IsAttack()
{
var IP = ClientIP; //取客户端IP
if (_VisitorList.ContainsKey(IP)) //有登记访客
{
var dt = _VisitorList[IP] as DataTable;
dt.Rows.Add(new object[] { IP, DateTime.Now }); //增加访问记录
//按时间倒序排列,取当前用户最后N次的访问记录
var rs = dt.Select("IP='" + IP + "'", "VisitTime DESC");
if (rs.Length >= LAST_VISIT_COUNT)
{
var maxTime = ToDateTimeEx(rs[0]["VisitTime"]); //最近一次访问时间
var minTime =
ToDateTimeEx(rs[LAST_VISIT_COUNT - 1]["VisitTime"]);
var ts = maxTime - minTime;
if (ts.TotalSeconds < LIMIT_SECONDS) //在指定时间内访问次数大于系统参数
{
throw new Exception("您的访问频率太高了,请休息下!");
}
else
{
//删除小于指定时间的访问记录
var filter = "IP='" + IP + "' AND VisitTime<'" +
minTime.ToString("yyyy-MM-dd HH:mm:ss") +
"'";
rs = dt.Select(filter);
for (var i = 0; i <= rs.Length - 1; i++)
dt.Rows.Remove(rs[i]);
dt.AcceptChanges();
}
}
}
else //第一次访问服务端,记录IP及访问时间
{
var dt = CreataTable();
dt.Rows.Add(new object[] { IP, DateTime.Now }); //增加访问记录
dt.AcceptChanges();
_VisitorList.Add(IP, dt);
}
}
}
}