using System;
|
using System.Collections;
|
using System.Data;
|
using System.ServiceModel;
|
using System.ServiceModel.Channels;
|
|
|
namespace CSFrameworkV5.Core.SystemSecurity
|
{
|
/// <summary>
|
/// 用于检测非法攻击WCF的接口,用户连续访问的次数超过指定值抛出异常中断操作
|
/// </summary>
|
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();
|
}
|
|
/// <summary>
|
/// 建立访问记录表
|
/// </summary>
|
/// <returns></returns>
|
private static DataTable CreataTable()
|
{
|
var dt = new DataTable();
|
dt.Columns.Add("IP", typeof(string)); //IP地址
|
dt.Columns.Add("VisitTime", typeof(DateTime)); //访问时间
|
return dt;
|
}
|
|
/// <summary>
|
/// 取当前用户的IP(客户端)
|
/// </summary>
|
/// <returns></returns>
|
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;
|
}
|
}
|
|
|
/// <summary>
|
/// 检查用户访问量,如有恶意攻击行为抛出异常
|
/// </summary>
|
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);
|
}
|
}
|
}
|
}
|