0

そこで私は、ユーザーが 24 時間ごとに 1 回ボタンをクリックできるようにし、その間はブロックするようにプログラミングしました。具体的な例は、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 ビット整数はありませんね。

投票を保存する他のテーブルは残しておきますが、それはこの質問の範囲内ではないと思います。

だから私の問題は...ランダムです。たとえば、何日も連続して投票できなかった人もいます。また、1 日に 1 回だけ急増(数百件)したこともあります。このスクリプトには、それが実際にユーザーによるクリックであったかどうかを検証するという点で、まだセキュリティが設定されていないため、これはボットの作業であると考えられます (そして、すべてがボットによって実行される可能性があるため、無意味です。それを難し​​くすること)。

今日投票したばかりで、もう一度やり直しました。プログラムは、もう一度投票できると言っていました... 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...

要件と依存関係:

  • PHP5
  • PEAR::例外
  • PEAR::DB (オプション)
  • PEAR::MDB (オプション)
  • PEAR::MDB2 (オプション)
于 2012-05-16T12:16:35.577 に答える