【发布时间】:2015-08-20 14:43:48
【问题描述】:
我正在研究一个课程,其目的是限制用户在任何 30 秒内只能发出 10 个请求。它利用文件来维护 IP 地址、上次请求时间。以及他们尝试的次数。问题是,无论我尝试什么,我都无法获得文件大小。我尝试过使用clearstatcache(),并尝试使用我在 PHP 手册的 filesize() 页面上的 cmets 中找到的函数。
这是代码,处于当前调试状态。
// 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 .= "\n";
}
$str = rtrim($str, '\n');
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("\n",$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;
}
}
我怎样才能得到真正的文件大小?我在 PHP 5.2 上。
【问题讨论】:
-
统计缓存是每个进程的。脚本的每次命中都是一个单独的进程,因此清除统计缓存没有意义,除非您在同一脚本进程中多次执行基于统计的操作。
-
@MarcB,我知道,但是,afaik,它也不会伤害任何东西,而且我越来越绝望,所以我想我会试一试。
-
请注意,IP 从来都不是识别单个用户的有效方式。例如考虑到几乎每部手机都是 NAT 网关。这意味着您将大量用户视为一个人,并将他们限制为一个群体,而不是个人。
-
离题,但我强烈建议您尽快升级您的 PHP 版本。 PHP 5.2 已经过时多年。现在甚至 5.3 也已报废;仍然实际支持的最旧版本是 5.4,即使这样也将很快结束支持。坚持使用这样的旧版本,实际上可以保证您的网站存在重大安全漏洞。
-
@Simba 不幸的是我没有那种程度的控制。希望我能。 :(