我正在尝试创建一个网络调查问卷,但我不希望相同的人使用相同的ip在一小时内多次提交,我使用php,我认为我需要使用$_SERVER['REMOTE_ADDR']
获取客户端ip并存储在会话或数据库中,然后使用它来比较新的ip,我不确定它是否正确,也不知道如何在php中准确实现这一点,有人能帮助我吗,提前感谢!
调查提交时间:
/*
Tracking table structure:
`id` INT(11) unsigned NOT NULL AUTO_INCREMENT
`client_ip` VARCHAR(15) NOT NULL
`submitted_time` DATETIME NOT NULL
*/
$query = "SELECT count(`id`) AS 'count'
FROM `tracking_table`
WHERE
`client_ip` = '".mysqli_real_escape_string($link, $_SERVER['REMOTE_ADDR'])."'
AND `submitted_time` > '".date('Y-m-d H:i:s',strtotime('-1 hour'))."'
LIMIT 1";
$result = mysqli_fetch_assoc(mysqli_query($link, $query));
if ($result['count'] > 0) {
echo "You have already submitted within the last hour";
exit;
}
// process survey here
$query = "INSERT INTO `tracking_table`
(`client_ip`, `submitted_time`)
VALUES
('".mysqli_real_escape_string($link, $_SERVER['REMOTE_ADDR'])."', ".date('Y-m-d H:i:s').")";
mysqli_query($link, $query);
然而,您可能会发现这不是一个好的需求——在许多有效的情况下,多个用户可能使用相同的IP地址(例如,学生宿舍)。设置此限制可能会阻止有效的提交。
编辑
下面是一个关于如何使用cookie执行此操作的基本概要(考虑到下面讨论的限制)。
我们的cookie系统处理一对值。ckv_1
将保存上次提交调查的时间戳。ckv_2
将持有基于时间戳和盐的哈希值,以阻止人们与饼干乱搞。显然,如果两个cookie都被删除,我们将无法检测到它,但至少这提供了某种验证:
function get_cookie_hash ($timestamp, $salt) {
return md5("Extra random static string; TS: $timestamp; Salt: $salt; Extra random static string.");
}
$cookieSalt = 'Th1si54rAnd0MsTr1nG!';
// If at least one of the cookies was returned, validate the request
if (!empty($_COOKIE['ckv_1']) || !empty($_COOKIE['ckv_2'])) {
$valid = FALSE;
do { // Wrapped in a do-while to allow us to break out easily
// Make sure both value are set
if (empty($_COOKIE['ckv_1']) || empty($_COOKIE['ckv_2'])) break;
// Get old timestamp as integer
$oldTS = hexdec($_COOKIE['ckv_1']);
// Make sure timestamp is more than one hour old, and the hash cookie matches it
if ($oldTS > (time() - 3600) || $_COOKIE['ckv_2'] != get_cookie_hash($oldTS, $cookieSalt)) break;
// OK if you get here
$valid = TRUE;
} while (FALSE);
if (!$valid) {
echo "Sorry - you cannot submit a survey more than once in an hour.";
exit;
}
}
// process survey here
// Set the tracking cookies after processing (but before any output!)
// We'll set them as HTTP only to help prevent XSS-type attacks
$cookieTime = time();
setcookie('ckv_1', dechex($cookieTime), 7200, '', '', FALSE, TRUE);
setcookie('ckv_2', get_cookie_hash($cookieTime, $cookieSalt), 7200, '', '', FALSE, TRUE);
使用数据库存储投票的ip和时间戳,然后在记录投票时(或者更好;当显示调查结果(告诉用户他已经投票了)时,检查数据库中用户的IP ($_SERVER['REMOTE_ADDR'])是否已经在数据库中,时间戳是否小于一小时。如果是,就不允许他投票,否则就允许。
你可以把你的检查包在一个类中,然后当你的动作需要这个功能时使用它:
class IPChecker
{
public function storeIP($ip)
{
# save $ip with now() and context (if available)
# in your database
...
}
public function isBlocked($ip)
{
# test if $ip by now() and context (if available)
# is in your database
...
# return true / false;
}
}
$ipchecker = new IPChecker();
# on form submit:
$ip = $_SERVER['REMOTE_ADDR'];
if ($ipchecker->isBlocked($ip))
{
# blocked
...
}
else
{
# good
$ipchecker->storeIP($ip);
...
}
REMOTE_ADDR
确实给您一个IP地址。但是:
- 在许多公司(尤其是大公司),传出的流量通过代理或防火墙,这使得整个公司-或至少整个位置-看起来来自几个IP地址。一个IP地址很容易代表一万人。
- 一些isp使用透明代理来节省带宽。通常,它只对客户端透明,因此整个ISP(或至少区域)将来自多个ip。
- 手机经常被分配新的IP地址比每小时更频繁,当你还没有投票的时候被告知你已经投票了,这将是相当烦人的。
- IPv6打开了一个全新的问题。隐私扩展的目的是破坏你正在做的事情。他们会的。
所以,这里是REMOTE_ADDR
的一个更准确的描述:一个地址,作为完整TCP会话地址(服务器,服务器端口,远程地址,远程端口)的一部分,允许您发送作为该会话一部分的数据包。它可能是也可能不是实际客户端的地址(通常不是),可能是也可能不是请求对请求的匹配,可能是也可能不是由许多其他人共享的。
将$_SERVER['REMOTE_ADDR']
与上次提交调查的时间戳一起存储在数据库表中。表可能有两个列,如IPAddress(varchar 100), TimeStamp(int)
。在PHP代码中
<?php
//query the $_SERVER['REMOTE_ADDR'] in database and get timestamp, if found compare it with current time stamp, difference should be greater than an hour
if($diff > 3600)
{
print "You are not allowed to post your survey more than once in an hour"
exit;
}
//Your page code
?>