简体   繁体   中英

same ip can't submit more than once within an hour time

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

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

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.

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

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM