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