提供基于IP的冷却时间的便携方式?

时间:2015-06-30 12:59:27

标签: php mysql ip-address

我在网络服务器上运行了一个PHP API前端。这个特定的PHP程序需要分发,因此它应该尽可能便携。

我想要实现的功能是IP冷却时间段,这意味着相同的IP每秒最多只能请求API两次,这意味着至少延迟500ms。

我想到的方法是将IP存储在MySQL数据库中,以及最新的请求时间戳。我得到了IP:

if (getenv('REMOTE_ADDR'))
    $ipaddress = getenv('REMOTE_ADDR');

但是有些服务器可能没有MySQL数据库,或者用户无法安装此数据库。另一个问题是清理数据库。

是否有更便携的临时存储IP方式(牢记IPv6)?

如何自动清除超过500毫秒的IP,对性能影响最小?

另外:我没有兴趣查看存储的IP,这只是延迟。

1 个答案:

答案 0 :(得分:0)

这就是我现在使用文件解决它的方法。

程序

  1. 获取客户端IP并对其进行哈希处理(以防止文件读取)。
  2. 打开IP文件并扫描每一行
  3. 将当前记录的时间与当前时间进行比较
  4. 如果差异大于设置超时goto 5.,否则为7。
  5. 如果IP与客户端匹配,则创建更新记录,否则
  6. drop record。
  7. 如果IP与客户端匹配,则提供失败消息,否则复制记录。
  8. 示例代码

    <?php
    
    $sIPHash    = md5($_SERVER[REMOTE_ADDR]);
    $iSecDelay  = 10;
    $sPath      = "bucket.cache";
    $bReqAllow  = false;
    $iWait      = -1;
    $sContent   = "";
    
    if ($nFileHandle = fopen($sPath, "c+")) {
        flock($nFileHandle, LOCK_EX);
        $iCurLine = 0;
        while (($sCurLine = fgets($nFileHandle, 4096)) !== FALSE) {
            $iCurLine++;
            $bIsIPRec = strpos($sCurLine, $sIPHash);
            $iLastReq = strtok($sCurLine, '|');
            // this record expired anyway:
            if ( (time() - $iLastReq) > $iSecDelay ) {
                // is it also our IP?
                if ($bIsIPRec !== FALSE) {
                    $sContent .= time()."|".$sIPHash.PHP_EOL;
                    $bReqAllow = true;
                }
            } else {
                if ($bIsIPRec !== FALSE) $iWait = ($iSecDelay-(time()-$iLastReq));
                $sContent .= $sCurLine.PHP_EOL;
            }
        }
    }
    
    if ($iWait == -1 && $bReqAllow == false) {
        // no record yet, create one
        $sContent .= time()."|".$sIPHash.PHP_EOL;
        echo "Request from new user successful!";
    } elseif ($bReqAllow == true) {
        echo "Request from old user successful!";
    } else {
        echo "Request failed! Wait " . $iWait . " seconds!";
    }
    
    ftruncate($nFileHandle, 0);
    rewind($nFileHandle);
    fwrite($nFileHandle, $sContent);
    flock($nFileHandle, LOCK_UN);
    fclose($nFileHandle);
    ?>
    

    说明

    新用户

    如果IP哈希不匹配任何记录,则会创建新记录。注意:如果您无权执行此操作,则访问可能会失败。

    <强>内存

    如果您期望获得更多流量,请一起切换到this等数据库解决方案。

    冗余代码

    &#34;但是minxomat&#34;,你可能会说,&#34;现在每个客户端遍历整个文件!&#34;。是的,的确,这就是我想要的解决方案。这样,每个客户端都负责清理整个文件。即便如此,性能影响仍然很低,因为如果每个客户端都在清理,文件大小将保持在绝对最小值。如果这种方式不适合你,请改变这一点。