防止相同的IP执行24小时的操作

时间:2012-05-16 12:13:39

标签: php mysql

所以我一直在编写这样的东西,允许用户每24小时点击一次按钮,并在此期间被阻止这样做。具体的例子是一个投票脚本,它应该只允许每24小时投票一次(虽然用户可以再次投票给同一件事)。

所以我所做的是在MySql中创建一个timelimit表

CREATE  TABLE IF NOT EXISTS `timelimit` (
  `ipaddress` VARCHAR(50) NOT NULL ,
  `ipdate` DATETIME NOT NULL ,
  PRIMARY KEY (`ipaddress`) )
ENGINE = MyIsam;

IP地址是一个字符串,因为我太懒了,无法将其转换为正确的整数格式,它也应该允许IPv6地址。还有没有128位整数,是吗?

我会离开另一张保存投票的桌子,我不认为这是在这个问题的范围内。

所以我的问题是...随机。例如,有些人不能连续几天投票。我们也在一天内看到了一个快速增加(几百个)。我们假设这是机器人的工作,因为这个脚本在验证实际上是否是用户的点击方面还没有任何安全性(这是毫无意义的,因为一切都可以由机器人完成。只是一个问题让它更难)。

我今天刚刚投票并再次尝试,该计划告诉我,我可以再次投票... 0小时59分钟...它应该是23小时59分钟!

这里出了点问题,我不能把手指放在上面。一点都没有!

$oneday = 86400;
$ip = trim($_SERVER['REMOTE_ADDR']);
require_once "config.php";
$conn = mysql_connect($mysql_host, $mysql_user, $mysql_pass);
mysql_select_db($mysql_db);
//I apologize for still using mysql_
if (!$conn) {
    die("Connection error!");
}

mysql_query("SET time_zone='+0:00';"); // This helped me fix some issues because the field is DateTime

$res = mysql_query("SELECT COUNT(*) FROM `timelimit` WHERE ipdate <= DATE_ADD(NOW(), INTERVAL 1 DAY) AND `ipaddress` = '$ip';"); 
/* supposed to count if there is any entry corresponding 
   to the IP address wihich is in the blocked timeframe. 
   Could be the source of an error, but I can't put my finger on it... */

if (mysql_result($res,0) > 0)   {
    $res2 = mysql_query("SELECT UNIX_TIMESTAMP(ipdate) as ipdate FROM timelimit WHERE ipaddress = '$ip';");
    $lastvote = mysql_result($res2, 0, "ipdate");
    $nextvote = $lastvote + $oneday;
    $timebetween = time() - $lastvote;
    $timetonext = $nextvote - time();
        //Some calculations done for the sake of output.
    die("You can only vote once a day. You can vote again in " . date("H", $timetonext) . " hours and " . date("i", $timetonext) . " minutes");
} else {
    if (isset($_REQUEST['postid'])) {
        $postid = $_REQUEST['postid'];
        $postid = mysql_real_escape_string($postid);

        if (!is_numeric($postid)) {
            die("post id not valid");
        } //The input would be sanitized by now (I hope?)

                //VOTE IS VALID
                //*SNIP* voting logic (increases the counter with an UPDATE table SET votes = votes + 1)
                //Done with the voting, time limit logic again:

        mysql_query("DELETE FROM `timelimit` WHERE ipaddress = '$ip';");
        mysql_query("INSERT INTO `timelimit` (`ipaddress`, `ipdate`) VALUES ('$ip', UTC_TIMESTAMP);"); 
// Could probably be combined into an INSERT and ON EXIST UPDATE query.
}

1 个答案:

答案 0 :(得分:1)

使用PEAR FloodControl它会为您完成所有事情。

取自http://www.tozalakyan.com/fc/index.php#db

的示例
CREATE TABLE fc_logs (
    unique_id varchar(32) NOT NULL,
    data text NOT NULL,
    access int UNSIGNED NOT NULL,
    PRIMARY KEY (unique_id)
)

require_once 'HTTP/FloodControl.php';
try {
    $ip = HTTP_FloodControl::getUserIP();
} catch (HTTP_FloodControl_Exception $e) {
    die($e);
}
try {
    $fc =& new HTTP_FloodControl();
    $fc->setContainer('MDB2', array(
        'dsn' => 'mysql://username:password@localhost/dbname',
        'table' => 'fc_logs',
        'autooptimize' => true
    ));
    $limits = array (
        86400 => 10       // maximum 10 requests in 24 h
    );
    if (!$fc->check($limits, $ip)) {
        die('Too many requests. Please try later.');
    }
} catch (HTTP_FloodControl_Exception $e) {
    die($e);
}
// Your code...

要求和依赖关系:

  • PHP 5
  • PEAR ::异常
  • PEAR :: DB(可选)
  • PEAR :: MDB(可选)
  • PEAR :: MDB2(可选)