1
yhj
2024-07-24 5e5d945e91568b973faa27d8ab0bcef99fc4a6c5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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);
            }
        }
    }
}