0

所以我一直在编写这个东西,它允许用户每 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.
}
4

1 回答 1

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::DB(可选)
  • 梨::MDB(可选)
  • PEAR::MDB2(可选)
于 2012-05-16T12:16:35.577 回答