using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

namespace Zero
{
    public static class CcAttackDefense
    {
        static string[] whiteIpList = {
            "127.0.0.1",
            "0.0.0.0",
            "::0"
        };
        static Dictionary<string, DateTime> blackIpList = new Dictionary<string, DateTime>();
        static object _locker = new object();
        static Dictionary<string, List<DateTime>> ipDic = new Dictionary<string, List<DateTime>>();
        static CcAttackDefense()
        {
            //检测黑名单过期IP
            new Thread(() =>
            {
                while (true)
                {
                    string[] blackIpKeys = blackIpList.Keys.ToArray();
                    for (int i = 0; i < blackIpKeys.Length; i++)
                    {
                        string key = blackIpKeys[i];
                        var dateTime = blackIpList[key];
                        if (DateTime.Now > dateTime)
                        {
                            lock (_locker)
                            {
                                blackIpList.Remove(key);
                            }
                        }
                    }
                    Thread.CurrentThread.Join(500);
                }
            })
            { IsBackground = true }.Start();
        }
        
        /// <summary>
        /// CC攻击防御
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        public static bool Detect(string ip)
        {
            //是否存在白名单
            if (whiteIpList.Contains(ip))
                return true;
            //存在黑名单
            if (blackIpList.ContainsKey(ip))
                return false;
            //判断列表中是否有这个IP
            if (ipDic.ContainsKey(ip))
            {
                ipDic[ip].Add(DateTime.Now);
            }
            else
            {
                ipDic.Add(ip, new List<DateTime>() { DateTime.Now });
            }
            //判断当前IP访问记录少于3条不用验证
            List<DateTime> dateTimes = ipDic[ip];
            if (dateTimes.Count <= 3)
                return true;
            //计算时间
            var minTime = dateTimes[0];
            var maxTime = dateTimes[dateTimes.Count - 1];
            TimeSpan timeSpan = maxTime - minTime;
            if (timeSpan.TotalMilliseconds <= 1000) //1千毫秒 = 1秒
            {
                //添加到黑名单中,设置为1天时间
                lock (_locker)
                {
                    blackIpList.Add(ip, DateTime.Now.AddDays(1));
                }
                return false;
            }
            //删除这个IP记录
            ipDic.Remove(ip);
            return true;
        }
    }
}


实现方式有不足的地方欢迎留言