无法获得实际的文件大小

I'm working on a class whose purpose is to restrict users to making only 10 requests within any 30 second period. It utilizes a file to maintain IP addresses, last request time. and the number of tries they've made. The problem is that, no matter what I try, I can't get the filesize. I've tried using clearstatcache(), and I've tried using a function I found in the comments on the filesize() page of the PHP manual.

Here's the code, in it's current debugging state.

// Makes sure user can only try to generate a coupon x number of times over x amount of seconds
class IpChecker{    
    const WAIT_TIME = 30; //seconds until user can try again
    const MAX_TRIES = 10; // maximum tries

    const COUPON_IP = 0;
    const COUPON_TIME = 1;
    const COUPON_TRIES = 2;

    private $ip_data;
    private $path;
    private $fh;
    private $safe;

    public function __construct(){
        clearstatcache();

        $this->path = realpath(dirname(__FILE__))."/ips/.ips";
        $this->fh = fopen($this->path,'w+');
        $this->filesize = $this->realfilesize($this->fh);
        echo "fs: ".$this->filesize; exit;


        $this->getIPs();
        $this->checkIP();
        $this->logRequest();
        fclose($this->fh);
        $this->safe || die(json_encode("You have exhausted all available tries. Please try again later."));
    }

    private function logRequest(){
        $str = "";
        foreach($this->ip_data as $data){
            foreach($data as $col){
                if(self::WAIT_TIME < (time() - $col[self::COUPON_TIME])) $str .= $col."\t";
            }
            $str = rtrim($str, '\t');
            $str .= "
";
        }
        $str = rtrim($str, '
');
        try{
            $fw = fwrite($this->fh, $str) || die(json_encode("Unable to check IP"));
        }catch(Exception $e){
            die(json_encode($e));
        }
    }

    private function checkIP(){     
        $IP = $_SERVER['REMOTE_ADDR'];
        $TIME = time();
        $safe = true;
        $user_logged = false;
        echo "<pre>"; var_dump($this->ip_data); exit;
        foreach($this->ip_data as $key=>$data){
            echo "<prE>"; var_dump($data); exit;
//          if($data[$key][self::COUPON_IP] == $IP){
//              $user_logged = true;
//              if(
//                  (($TIME - $data[$key][self::COUPON_TIME]) < self::WAIT_TIME) ||
//                  (self::MAX_TRIES >= $data[$key][self::COUPON_TRIES])
//              ) $safe = false;
//              $this->ip_data[$key][self::COUPON_TRIES] = $this->ip_data[$key][self::COUPON_TRIES]+1;
//              $this->ip_data[$key][self::COUPON_TIME] = $TIME;
//          }
        }
        if(!$user_logged){
            die("user not logged");
            $this->ip_data[] = array(
                self::COUPON_IP => $IP,
                self::COUPON_TIME => $TIME,
                self::COUPON_TRIES => 1
            );
        }
        $this->safe = $safe;
    }

    private function getIPs(){
        $IP_DATA = array();
        echo file_get_contents($this->path); exit;
        // this always returns 0. 
        $size = filesize($this->path);
        echo "filesize: ".$size; exit;
        if($size){
            $IPs = fread($this->fh,$size);
            $IP_ARR = explode("
",$IPs);
            foreach($IP_ARR as $line) $IP_DATA[] = explode("\t",$line);
        }
        $this->ip_data = $IP_DATA;
    }

    // Copied from the comments in the PHP Manual for filesize()
    public function realfilesize($fp) {
        $return = false;
        if (is_resource($fp)) {
            if (PHP_INT_SIZE < 8) {
                // 32bit
                if (0 === fseek($fp, 0, SEEK_END)) {
                    $return = 0.0;
                    $step = 0x7FFFFFFF;
                    while ($step > 0) {
                        if (0 === fseek($fp, - $step, SEEK_CUR)) {
                            $return += floatval($step);
                        } else {
                            $step >>= 1;
                        }
                    }
                }
            } elseif (0 === fseek($fp, 0, SEEK_END)) {
                // 64bit
                $return = ftell($fp);
            }
        }
        return $return;
    }
}

How can I get the real filesize? I'm on PHP 5.2.

dpwdldgn43486
dpwdldgn43486 奇怪。当您使用error_reporting(E_ALL)时,它会引发一些错误吗?
大约 5 年之前 回复
dstm2014
dstm2014 无论如何,filesize()都返回0。file_get_contents()返回空字符串。file_exists()返回true。is_readable()和is_writable()都返回true。文件本身暂时修改为777并且不为空。
大约 5 年之前 回复
dtmbc1606
dtmbc1606 这是什么意思,你不能使用filesize()来获取文件大小?什么回报而不是预期的大小?它会抛出任何错误吗?
大约 5 年之前 回复
dqn8235
dqn8235 我知道,但这些用户未经过身份验证,其中大多数用户不需要接近最大分配10次尝试的任何地方。这是我最好的选择。
大约 5 年之前 回复
douyanlu7380
douyanlu7380 不幸的是,我没有那种控制水平。希望我能。:(
大约 5 年之前 回复
duanqiao0153
duanqiao0153 关于主题,但我强烈建议您尽快升级您的PHP版本。PHP5.2已经过时多年了。甚至5.3现在已经过了生命周期;实际上仍然支持的最旧版本是5.4,即使这样也会很快终止支持。通过坚持使用这样一个旧版本,您几乎可以保证您的网站存在重大安全漏洞。
大约 5 年之前 回复
doukan4039
doukan4039 并注意到IP从未成为识别单个用户的有效方式。例如考虑到几乎每一部手机都在惊吓NAT网关。这意味着您将大量用户视为一个人并将其限制为一个群体,而不是个人。
大约 5 年之前 回复
dongliao6491
dongliao6491 我意识到,但是afaik,它也不会伤害任何东西,我会变得绝望,所以我想我会试一试。
大约 5 年之前 回复
douwei2825
douwei2825 统计缓存是按进程进行的。脚本中的每个命中都是一个单独的过程,因此除非您在SAME脚本过程中多次执行基于统计的操作,否则清除stat缓存没有意义。
大约 5 年之前 回复

1个回答

I wasn;t able to figure out what was wrong with my code, if anythign, but I worked around it like this:

/**
 * Makes sure user can only access a given page
 * x number of times over x amount of seconds.
 * If multiple instances of this class are used, the $namespace
 * properties for each should be unique.
 * Default wait time is 90 seconds while default request limit
 * is 10 tries.
 * 
 * -+ Usage +-
 * Just create the object with any parameters, no need to assign,
 * just make sure it's initialized at the top of the page:
 * new RequestThrottler;
 * 
 * -+- Parameters -+-
 * null RequestThrottler ( [ string $namespace [, int $WaitTime [, int $MaxTries ] ] ] )
 */
class RequestThrottler{
    // settings
    private static $WAIT_TIME; // seconds until count expires
    private static $MAX_TRIES; // maximum tries

    // used to keep session variables unique
    // in the event that this class is used in multiple places.
    private $namespace;

    // for debugging
    const DBG = false;

    // array index constants
    const _TIME = 0;
    const _TRIES = 1;

    // defines whether or not access is permitted
    private $safe;

    // seconds until reset
    private $secs; 

    /**
     * -+- Constructor -+-
     * @param String $namespace - A unique prefix for SESSION data
     * @param Int $WaitTime - Total seconds before user can try again
     * @param Int $MaxTries - Total tries user can make until their request is denied
     */
    public function __construct($namespace='Throttler', $WaitTime=90, $MaxTries=10){
        // make sure a session is available
        if(!headers_sent() && !isset($_SESSION)) session_start();
        if(!isset($_SESSION)) die(json_encode("No session available"));

        // save settings
        $this->namespace = $namespace;
        self::$MAX_TRIES = $MaxTries;
        self::$WAIT_TIME = $WaitTime;

        // do the footwork
        $this->checkHistory();

        // if set to debug mode, print a short helpful string
        if(self::DBG) die(json_encode(
                "You are ".($this->safe ? 'SAFE' : 'NOT SAFE')."! "
                . "This is try number {$_SESSION[$this->namespace.'_ATTEMPTS'][self::_TRIES]} of ".self::$MAX_TRIES.". "
                . $this->secs." seconds since last attempt. "
                . (self::$WAIT_TIME - $this->secs)." seconds until reset."
            ));

        // if not safe, kill the script, show a message
        $this->safe || die(json_encode("You're going too fast. Please try again in ".(self::$WAIT_TIME - $this->secs)." seconds."));
    }

    /**
     * -+- checkHistory -+-
     * Does the footwork to determine whether
     * or not to throttle the current user/request.
     */
    private function checkHistory(){
        $TIME = time();
        $safe = true;

        // make sure session is iniitialized
        if( !isset($_SESSION[$this->namespace.'_ATTEMPTS']) || 
            !isset($_SESSION[$this->namespace.'_ATTEMPTS'][self::_TRIES]) || 
            !isset($_SESSION[$this->namespace.'_ATTEMPTS'][self::_TIME])   ) 
                $_SESSION[$this->namespace.'_ATTEMPTS'] = array(
                    self::_TIME =>$TIME,
                    self::_TRIES => 1
                );
        else $_SESSION[$this->namespace.'_ATTEMPTS'][self::_TRIES] = 
                $_SESSION[$this->namespace.'_ATTEMPTS'][self::_TRIES]+1;

        // get seconds since last attempt
        $secondSinceLastAttempt = $TIME - $_SESSION[$this->namespace.'_ATTEMPTS'][self::_TIME];

        // reset the counter if the wait time has expired
        if($secondSinceLastAttempt  > self::$WAIT_TIME){
            $_SESSION[$this->namespace.'_ATTEMPTS'][self::_TIME] = $TIME;
            $_SESSION[$this->namespace.'_ATTEMPTS'][self::_TRIES] = 1;
            $secondSinceLastAttempt  = 0;
        }

        // finally, determine if we're safe
        if($_SESSION[$this->namespace.'_ATTEMPTS'][self::_TRIES] >= self::$MAX_TRIES) $safe=false;

        // log this for debugging
        $this->secs = $secondSinceLastAttempt;

        // save the "safe" flag
        $this->safe = $safe;
    }
}
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐