IPHitsLimit

  1 <?php
  2 /**
  3  * @file     IPHitsLimit.php
  4  * @version 1.0
  5  * @author   guoxiaosong <>
  6  * @date     2012-11-14
  7  * @brief    Limit ip frequency.
  8  */
  9 class IPHitsLimit
 10 {
 11     const INDEX_DAY = 0;
 12     const INDEX_HOUR = 1;
 13     const INDEX_MINUTE = 2;
 14     const INDEX_SECOND = 3;
 15     // MemCahe link
 16     private $_memCache;
 17     // 1 day
 18     private $_expiredTime = 86400;
 19     private $_ipWhiteLists = array();
 20     private $_ipBlackLists = array();
 21 
 22     /**
 23      * Constructor.
 24      *
 25      * @param   boolean     $init   Initialize the shm or not.
 26      */
 27     function __construct()
 28     {
 29         $this->_memCache = new MemCache;
 30         $this->_memCache->pconnect(KOPU_MEMCACHED_HOST, KOPU_MEMCACHED_PORT);
 31 
 32         $this->init();
 33     }
 34 
 35     /**
 36      * Initialize the shm.
 37      *
 38      */
 39     function init()
 40     {
 41         $this->_expiredTime = KOPU_IPHITS_EXPIRED_TIME;
 42         $this->_ipWhiteLists = Yii::app()->params->ipwhitelists;
 43         $this->_ipBlackLists = Yii::app()->params->ipblacklists;
 44     }
 45 
 46     /**
 47      * Check whether to limit $ip.
 48      *
 49      * @param   string $ip         The ip to check.
 50      * @return int                 0: no limit, 1: limit it.
 51      */
 52 
 53     public function check($ip)
 54     {
 55         $return = $this->_check($ip);
 56         if ($return == 1) {
 57             Yii::log($ip, CLogger::LEVEL_INFO, 'IPHitsLimit');
 58         }
 59         return $return;
 60     }
 61 
 62     private function _check($ip)
 63     {
 64         if (!($key = $this->_checkIP($ip)) || $this->_checkIPBlackList($ip)) {
 65             return 1;
 66         }
 67 
 68         if ($this->_checkIPWhiteList($ip)) {
 69             return 0;
 70         }
 71 
 72         $info = $this->_memCache->get($key);
 73         $time = time();
 74         if (empty($info)) {// new record
 75             $info = array(
 76                 'time' => $time, 
 77                 'count' => array(1, 1, 1, 1), 
 78                 'ip' => $ip, 
 79             );
 80             $this->_memCache->set($key, $info, MEMCACHE_COMPRESSED, $this->_expiredTime);
 81             return 0;
 82         } else {
 83             $countTimeMap = $this->countTimeMap();
 84             $info['count'] = $this->_addCount($info['count']);
 85             if ($this->_campareTime($time, $info['time'], 'day')) {
 86                 // IP hits up to day limits.
 87                 if ($info['count'][self::INDEX_DAY] > $countTimeMap[self::INDEX_DAY]) {
 88                     $info['time'] = $time;
 89                     $this->_memCache->set($key, $info);
 90                     return 1;
 91                 }
 92 
 93                 if ($this->_campareTime($time, $info['time'], 'hour')) {
 94                     // Ip hits up to hour limits.
 95                     if ($info['count'][self::INDEX_HOUR] > $countTimeMap[self::INDEX_HOUR]) {
 96                         $info['time'] = $time;
 97                         $this->_memCache->set($key, $info);
 98                         return 1;
 99                     }
100 
101                     if ($this->_campareTime($time, $info['time'], 'minute')) {
102                         // Ip hits up to minute limits
103                         if ($info['count'][self::INDEX_MINUTE] > $countTimeMap[self::INDEX_MINUTE]) {
104                             $info['time'] = $time;
105                             $this->_memCache->set($key, $info);
106                             return 1;
107                         }
108 
109                         if ($this->_campareTime($time, $info['time'], 'second')) {
110                             //Ip hits up to second limits.
111                             if ($info['count'][self::INDEX_SECOND] > $countTimeMap[self::INDEX_SECOND]) {
112                                 $info['time'] = $time;
113                                 $this->_memCache->set($key, $info);
114                                 return 1;
115                             }
116                         } else {
117                             $info['count'][self::INDEX_SECOND] = 1;
118                         }
119                     } else {
120                         $info['count'][self::INDEX_MINUTE] = 1;
121                         $info['count'][self::INDEX_SECOND] = 1;
122                     }
123                 } else {
124                     // new hour need to reset day,minute,second count.
125                     $info['count'][self::INDEX_HOUR] = 1;
126                     $info['count'][self::INDEX_MINUTE] = 1;
127                     $info['count'][self::INDEX_SECOND] = 1;
128                 }
129             } else {
130                 // new day need to reset all count.
131                 $info['count'] = array(1, 1, 1, 1);
132             }
133             $info['time'] = $time;
134             $this->_memCache->set($key, $info);
135             return 0;
136         }
137 
138     }
139 
140     /**
141      * @return array
142      * key(seconds)
143      * value(limits)
144      */
145     function countTimeMap()
146     {
147         return array(
148             self::INDEX_DAY => KOPU_IPHITS_PER_DAY,
149             self::INDEX_HOUR => KOPU_IPHITS_PER_HOUR,
150             self::INDEX_MINUTE => KOPU_IPHITS_PER_MINUTE,
151             self::INDEX_SECOND => KOPU_IPHITS_PER_SECOND
152         );
153     }
154 
155     /**
156      * Print ip info in shm.
157      *
158      * @param   string $ip         The ip.
159      */
160     function dump($ip)
161     {
162         $key = ip2long($ip);
163         if ($key == -1 || $key === FALSE) {// Invalid IP
164             return;
165         }
166         $info = $this->_memCache->get($key);
167         print_r($info);
168         return $info;
169     }
170 
171     /**
172      * @return mixed
173      */
174     private function _addCount(array $count, $key = NULL)
175     {
176         if ($key == NULL || !isset($count[$key])) {
177             foreach ($count as &$v) {
178                 $v++;
179             }
180             return $count;
181         } else {
182             $count[$key]++;
183             return $count;
184         }
185     }
186 
187     private function _campareTime($t1, $t2, $type = 'day')
188     {
189         switch($type) {
190             case 'day' :
191                 return (date('Y-m-d', $t1) == date('Y-m-d', $t2));
192                 break;
193             case 'hour' :
194                 return (date('Y-m-d H:00:00', $t1) == date('Y-m-d H:00:00', $t2));
195                 break;
196             case 'minute' :
197                 return (date('Y-m-d H:i:00', $t1) == date('Y-m-d H:i:00', $t2));
198                 break;
199             case 'second' :
200                 return $t1 == $t2;
201                 break;
202             default :
203                 return false;
204                 break;
205         }
206     }
207 
208     private function _checkIP($ip)
209     {
210         if (empty($ip)) {
211             return false;
212         }
213         $key = ip2long($ip);
214         if ($key == -1 || $key === FALSE) {// Invalid IP
215             return false;
216         }
217         return $key;
218     }
219 
220     private function _checkIPWhiteList($ip)
221     {
222         return $this->isIpMatched($ip, $this->_ipWhiteLists);
223     }
224 
225     private function _checkIPBlackList($ip)
226     {
227         return $this->isIpMatched($ip, $this->_ipBlackLists);
228     }
229 
230     /**
231      * @param string $ip the IP address
232      * @return boolean whether the rule applies to the IP address
233      */
234     protected function isIpMatched($ip, $ips)
235     {
236         if(empty($ips))
237             return false;
238         foreach($ips as $rule)
239         {
240             if($rule==='*' || $rule===$ip || (($pos=strpos($rule,'*'))!==false && !strncmp($ip,$rule,$pos)))
241                 return true;
242         }
243         return false;
244     }
245 
246 }
247 ?>

 

posted on 2013-01-09 10:21  技术员  阅读(170)  评论(0编辑  收藏  举报

导航