24 小时内阻止同一 IP 执行操作 [英] Preventing the same IP from executing an action for 24 hours
问题描述
所以我一直在编写这个东西,允许用户每 24 小时点击一次按钮,同时被阻止这样做.具体的例子是一个投票脚本,它应该只允许每 24 小时投票一次(尽管用户可以再次投票给同一件事).
So I've been programming this thing that allows a user to click a button once every 24 hours and is blocked to do so in the meantime. The concrete example is a vote script that should only allow a vote every 24 hours (albeit a user can vote for the same thing again).
所以我所做的是在 MySql 中创建一个 timelimit 表
So what I did was create a timelimit table in MySql
CREATE TABLE IF NOT EXISTS `timelimit` (
`ipaddress` VARCHAR(50) NOT NULL ,
`ipdate` DATETIME NOT NULL ,
PRIMARY KEY (`ipaddress`) )
ENGINE = MyIsam;
IP 地址是一个字符串,因为我懒得将它转换为正确的整数格式,而且它也应该允许 IPv6 地址.也没有 128 位整数,是吗?
The IP-address is a string because I was too lazy to convert it to a proper integer format and it should allow for IPv6 addresses, too. Also there's no 128 bit integer, is there?
我会把保存投票的另一张桌子放在外面,我认为它不在这个问题的范围内.
I'll leave the other table that saves the votings out, I don't think it's in the scope of this question.
所以我的问题是……随机.例如,有些人连续几天都不能投票.此外,我们曾经在一天内看到过快速增长(几百个).我们假设这是机器人的工作,因为这个脚本在验证这是否真的是用户的点击方面还没有任何安全性(这是毫无意义的,因为一切都可以由机器人完成.只是一个问题让它变得更难).
So my issue is... random. Some people couldnt vote for days straight, for example. Also we saw a rapid increase (a few hundred) in one day once. We suppose though that was the work of a bot, since this script doesn't yet have any security in terms of verifying if that actually was a click by a user (and it's pointless, because everything can be done by bots. Just a matter of making it harder).
我今天刚刚投票并再次尝试,程序告诉我我可以在...0小时59分钟后再次投票...应该是23小时59分钟!
I just voted today and tried again, the program told me I can vote again in... 0 hours and 59 minutes... It should rather be 23 hours and 59 minutes!
这里出了点问题,我无法解决.完全没有!
Something is so wrong here and I can't put my finger on it. At all!
$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.
}
推荐答案
使用 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(可选)
- PEAR::MDB(可选)
- PEAR::MDB2(可选)
这篇关于24 小时内阻止同一 IP 执行操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!