同一ip在一小时内不能提交多次

发布于 2024-12-19 02:59:13 字数 186 浏览 1 评论 0原文

我正在尝试创建一个网络调查问卷,但我不希望同一个人使用相同的 ip 在一个小时内多次提交它,我正在使用 php,我认为我需要使用 $_SERVER['REMOTE_ADDR'] 获取客户端ip并存储在会话或数据库中,然后用它来比较新ip,我不确定它是否正确,也不知道如何要在 php 中准确实现这一点,任何人都可以帮助我,提前致谢!

I am trying to create a web survey questionaire, but I don't want same people using same ip to submit it more than once within an hour time, I am using php, I assume I need to use
$_SERVER['REMOTE_ADDR'] to get the client ip and store in the session or database and then use it to compare the new ip, I am not sure if it is right and don't know how to exact implement this in php, can anyone help me with it, thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

作妖 2024-12-26 02:59:13

提交调查时:

 /*
   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。显然,如果两个 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);

When survey is submitted:

 /*
   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);

However, you may find that this is not a good requirement - there are many valid situations where multiple users may use the same IP address (such as, for example, student accomodation). You may be preventing valid submissions by imposing this limit.

EDIT

Here is a basic outline of how you might do this with cookies (taking into account the limitations discussed below).

Our cookie system works on a pair of values. ckv_1 will hold the timestamp at which the last survey was submitted. ckv_2 will hold a hash based on the timestamp and a salt, in an effort to stop people from screwing with the cookies. Obviously, if both cookies are deleted, we won't be able to detect it, but at least this provides some sort of validation:

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);
或十年 2024-12-26 02:59:13

使用数据库来存储投票的 IP 和时间戳,然后在记录投票时(或者更好;在显示调查时告诉用户他已经投票了)检查数据库是否用户的 IP ($_SERVER['REMOTE_ADDR'] ) 已在数据库中,并且时间戳小于一小时。如果是,则不允许他投票,否则就允许他投票。

Use a database to store IPs and timestamps of votes, and then when recording the vote (or better yet; when displaying the survey so you tell the user that he already voted) check the database if user's IP ($_SERVER['REMOTE_ADDR']) is already in the DB and if the timestamp is younger than one hour. If it is don't allow him to vote, otherwise do.

就是爱搞怪 2024-12-26 02:59:13

您可以将检查包装在一个类中,然后在您的操作需要以下功能时使用它:

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);
    ...
}

You can wrap your checks in a class and then use it when your action requires the functionality:

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);
    ...
}
中二柚 2024-12-26 02:59:13

REMOTE_ADDR 确实可以为您提供 IP 地址。但是:

  • 在许多公司(尤其是大型公司),传出流量会通过代理或防火墙,这使得整个公司(或至少整个位置)看起来来自几个 IP 地址。一个IP地址很容易代表一万人。
  • 一些 ISP 使用透明代理来节省带宽。通常,它仅对客户端透明,因此整个 ISP(或至少区域)将来自多个 IP。
  • 手机经常会比每小时更频繁地分配新的 IP 地址,并且在您还没有投票时却被告知您已经投票了,这会很烦人。
  • IPv6 打开了一个全新的蠕虫罐头。隐私扩展旨在破坏您正在做的事情。他们会的。

因此,这里是对 REMOTE_ADDR 的更准确描述:作为完整 TCP 会话地址(服务器、服务器端口、远程地址、远程端口)的一部分的地址,可让您发送包含该地址一部分的数据包。所说的会议。它可能是也可能不是实际客户的地址(通常不是),可能与请求之间匹配,也可能不匹配,并且可能会也可能不会被许多其他人共享。

REMOTE_ADDR does indeed get you an IP address. But:

  • At many companies (especially large ones), outgoing traffic goes through proxies or firewalls, which makes the entire company—or at least entire location—appear to come from a few IP addresses. One IP address may easily be 10,000 people.
  • Some ISPs use transparent proxying to save on bandwidth. Often, its only transparent to the client, so an entire ISP (or at least region) will come from several IPs.
  • Cell phones often are assigned new IP addresses more often than every hour, and being told you've already voted when you haven't would be quite annoying.
  • IPv6 opens a whole new can of worms. Privacy extensions are designed to break what you're doing. They will.

So, here is a more accurate description of REMOTE_ADDR: An address that, as part of the full TCP session address (server, server port, remote address, remote port) lets you send a packet that is part of said session. It may or may not be the address of the actual client (usually isn't), may or may not match from request-to-request, and may or may not be shared by numerous other people.

月亮邮递员 2024-12-26 02:59:13

$_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
?>

Store the $_SERVER['REMOTE_ADDR'] in database table with the time stamp it last submitted the survey. The table may have two columns like IPAddress(varchar 100), TimeStamp(int). and in php code

<?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
?>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文