Nick
Nick

Reputation: 25

How to limit use on a form or restrict access

I have a basic register form for a game I have and basically it's extremely novice and it allows users to make as many accounts as they please. I've searched around but couldn't really find any specific answer.

I basically need a way to either limit use of the form or limit account creation to 1 per IP.

Here is the basic form code:

<?php

/*if($_SERVER['REMOTE_ADDR'] != '::1') {
    $inRegister = true;
    include 'index.php';
    die();
  } */

  if(isset($_GET['username'])) {
    function sendBack($func_value) {
      $func_data = array('false' => 'REGISTER', 'fail' => 'DATABASE_ERROR', 'true' => 'USERNAME_TAKEN');
      include "Pages/{$func_data[$func_value]}.page.php";
    }

    include 'checkName.php';
    die();
  }

  from ;include 'settings.php' ;uses ;{
    $pMin = PLAYER_MINLEN;
    $pMax = PLAYER_MAXLEN;
    $pChr = PLAYER_MAXLEN;

    $aMin = PASSWORD_MINLEN;
    $aMax = PASSWORD_MAXLEN;

    $eMin = EMAIL_MINLEN;
    $eMax = EMAIL_MAXLEN;
  };

?>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1' />

    <title>CpBroadcast: Club Penguin Private Server Registration</title>

    <link type='text/css' href='CSS/ui-lightness/jquery-ui-1.8.2.custom.css' rel='stylesheet' />  
    <link type='text/css' href='CSS/register.css' rel='stylesheet' />  

    <script type='text/javascript' src='JS/MD5.js'></script>
    <script type='text/javascript' src='JS/jquery-1.4.2.min.js'></script>

    <script type='text/javascript' src='JS/jquery-ui-1.8.2.custom.min.js'></script>

    <script type='text/javascript'>

      function LTrim(value) {
        var re = /\s*((\S+\s*)*)/;
        return value.replace(re, "$1");
      }

      function RTrim(value) {
        var re = /((\s*\S+)*)\s*/;
        return value.replace(re, "$1");
      }

      function trim(value) {
        return LTrim(RTrim(value));
      }

      var moderatorTimer = 0;
      var isLoggedIn = false;
      var suggestValues = {
        playerName:   'Playername',
        passwordA:    '',
        passwordB:    '',
        emailAddress: '[email protected]',
        recommended:  'Who told you about this?'
      };

      var states = {
        noticePasswords:  0,
        noticePlayerName: 0,
        noticeEMail:      0
      };

      function updateStatus(classString, messageString) {
        $('#statusBar').removeClass('ui-state-error');
        $('#statusBar').removeClass('ui-state-highlight');
        $('#statusBar').addClass(classString);

        var iconString = classString == 'ui-state-error' ? 'ui-icon-alert' : 'ui-icon-info';
        $('#statusBar').html('<p><span class="ui-icon ' + iconString + '" style="float: left; margin-right: .3em;"></span>' + messageString + '</p>');
      }

      function showLoader(message) {
        $('#content').html('<div align=\'center\'><img src=\'Images/Loader.gif\' /><br />' + message + '</div>');
      }

      function loadContent(url, container) {
        url = url.split('?');
        data = url[1];
        url = url[0];
        $.ajax({
          url: url,
          data: data,
          success: function(data) {
            $(container).html(data);
          }
        });
      }

      function updateNotice(fieldID, fieldData, fieldMessage) {
        states[fieldID] = Number(fieldData == 'fieldNoticeFail');
        fieldID = '#' + fieldID;

        $(fieldID).removeClass('fieldNoticeOkay');
        $(fieldID).removeClass('fieldNoticeFail');

        $(fieldID).addClass(fieldData);

        $(fieldID).html(fieldMessage);
      }

      $(function() {
        $('#playerName, #recommended').keyup(function() {
          var playerName = this.value;
          var noticeID = this.id == 'playerName' ? 'noticePlayerName' : 'noticeEMail';

          if(playerName.length == 0)
           if(this.id == 'recommended') return updateNotice(noticeID, 'fieldNoticeOkay', 'You don\'t have to edit that Field, but it\'s recommended!');
           else return updateNotice(noticeID, 'fieldNoticeFail', 'Please enter a Username!');

          if(playerName.length < 3) return updateNotice(noticeID, 'fieldNoticeFail', 'The PlayerName is too short! 3 Chars at Minimum!');
          if(playerName.length > 12) return updateNotice(noticeID, 'fieldNoticeFail', 'The PlayerName is too long! 12 Chars at Maximum!');

          var count = 0;
          for(var i = 0; i < playerName.length; ++i) if((chr = playerName.charCodeAt(i)) && (chr > 64 && chr < 91 || chr > 96 && chr < 123)) ++count;
          if(!count) return updateNotice(noticeID, 'fieldNoticeFail', 'Woah, you need to at least have one letter in your name.');

          return updateNotice(noticeID, 'fieldNoticeOkay', 'Your player name is okay, and very creative! :)');
        }).trigger('keyup').blur(function() {
          if(states.noticePlayerName) return;
          $.ajax({
            url:  'checkName.php',
            data: 'username=' + this.value,
            success: function(data) {
              if(data == 'true')  return updateNotice('noticePlayerName', 'fieldNoticeFail', 'We are sorry, a member has already taken that name.');
              if(data == 'fail')  return updateNotice('noticePlayerName', 'fieldNoticeFail', 'Wow, it seems we have lost database connection. Please look at our blog for updates.');
              if(data == 'false') return updateNotice('noticePlayerName', 'fieldNoticeOkay', 'I like that playername! Lucky for you, it is available!');
              alert(
               ['Debug TraceBack',
                ' at CpBroadcast',
                '  at Register.php',
                '   at AJAX.success Callback',
                '    called with Parameter',
                '    #0: [' + typeof(data) + '] ' + data,
                '     at checkName.php?username=...',
                '',
                ''].join("\n"));
              return updateNotice('noticePlayerName', 'fieldNoticeFail', 'Something is wrong!');
            }
          });
        });
        $('#passwordA, #passwordB').keyup(function() {

          this.value = trim(this.value);
          if(this.value.length == 0)
           if(this.id == 'passwordB' && $('#passwordA').val().length != 0) return updateNotice('noticePasswords', 'fieldNoticeFail', 'You have to repeat the Password!');
           else return updateNotice('noticePasswords', 'fieldNoticeFail', 'You have to enter a Password!');

          if(this.id == 'passwordB' && $('#passwordA').val() != $('#passwordB').val())
           return updateNotice('noticePasswords', 'fieldNoticeFail', 'The Passwords don\'t match!');

          if(this.value.length < 6) return updateNotice('noticePasswords', 'fieldNoticeFail', 'The Password is too short! 6 Chars at Minimum!');
          if(this.value.length > 32) return updateNotice('noticePasswords', 'fieldNoticeFail', 'The Password is too long! 32 Chars at Maximum!');

          if($('#passwordB').val().length == 0) return updateNotice('noticePasswords', 'fieldNoticeFail', 'You have to repeat the Password!');
          if(this.id == 'passwordA' && $('#passwordA').val() != $('#passwordB').val())
           return updateNotice('noticePasswords', 'fieldNoticeFail', 'The Passwords don\'t match!');

          return updateNotice('noticePasswords', 'fieldNoticeOkay', 'The Passwords are okay :)');
        }).trigger('keyup');
        $('#emailAddress').keyup(function() {
          this.value = trim(this.value);

          var email = this.value;

          if(email.length < 6) return updateNotice('noticeEMail', 'fieldNoticeFail', 'The EMail Address is too short! 6 Chars at Minimum!');
          if(email.length > 128) return updateNotice('noticeEMail', 'fieldNoticeFail', 'The EMail Address is too long! 128 Chars at Maximum!');

          if(email.split('@').length != 2) return updateNotice('noticeEMail', 'fieldNoticeFail', 'The EMail Address is invalid! It has to contain exactly <b>one</b> @!');
          if(email.split('@')[1].split('.').length < 2) return updateNotice('noticeEMail', 'fieldNoticeFail', 'The EMail Address is invalid! The Domain is wrong!');

          var emailName   = email.split('@')[0];
          var emailDomain = email.split('@')[1].split('.');
          var emailTLD    = emailDomain.pop();
          emailDomain = emailDomain.join('.');

          if(emailName.length < 1)   return updateNotice('noticeEMail', 'fieldNoticeFail', 'You have to specify a Username in the EMail Address!');
          if(emailDomain.length < 1) return updateNotice('noticeEMail', 'fieldNoticeFail', 'You have to specify a Domain in the EMail Address!');
          if(emailTLD.length < 2)    return updateNotice('noticeEMail', 'fieldNoticeFail', 'You have to specify a valid TLD in the EMail Address!');

          return updateNotice('noticeEMail', 'fieldNoticeOkay', 'The EMail is okay :)');
        }).trigger('keyup');
        $('document').ready(function() {
          updateStatus('ui-state-highlight', '<strong>Welcome!</strong> To register for CpBroadcast, click the "Register" button!');

          for(var i in suggestValues) $('#' + i).addClass('suggestBox');
          $('.suggestBox').focus(function() {
            if(this.value == suggestValues[this.id]) this.value = '';
            this.style.color = '#000000';
          });
          $('.suggestBox').blur(function() {
            if(this.value == '') this.value = suggestValues[this.id];
            if(this.value == suggestValues[this.id]) this.style.color = '#DADADA';
          });
          $('.suggestBox').trigger('blur');
        });
        $('#registerBox').dialog({
          modal:    true,
          autoOpen: false,
          width:    320,
          beforeclose: function() { updateStatus('ui-state-highlight', '<strong>Welcome!</strong> Registration aborted!'); },
          buttons: {
            'Submit': function() {
              var sum = 0;
              for(var i in states) sum += states[i];

              if(sum) {
                var s = sum == 1 ? '' : 's';
                var is = sum == 1 ? 'is' : 'are';
                var error = 'There ' + is + ' still ' + sum + ' Mistake' + s + ' in the Regristration Form!';

                return (updateStatus('ui-state-error', '<strong>Regristration failed:</strong> ' + error) | alert(error)) && false;
              } else {
                $(this).dialog('close');
                $(this).dialog('close');
                updateStatus('ui-state-highlight', '<strong>Status:</strong> Sending Regristration...');
                loadContent('register.php?' +
                'username=' + $('#playerName').val() +
                '&password=' + $('#passwordA').val() +
                '&email=' + $('#emailAddress').val() +
                '&color=' + $('#color').val(), '#content');
              }
            }, 
            'Cancel': function() {
              $(this).dialog('close'); 
            } 
          }
        });
        $('#registerLink').click(function() {
          $('#registerBox').dialog('open');
          return false;
        });
        $('#registerLink, ul#icons li').hover(
          function() { $(this).addClass('ui-state-hover'); }, 
          function() { $(this).removeClass('ui-state-hover'); }
        );        
      });

    </script> 
  </head>
  <body>
    <div class='ui-widget'><div id='statusBar' class='ui-corner-all'></div></div>
    <div align='right'><a href='#' id='registerLink' class='ui-state-default ui-corner-all'><span class='ui-icon ui-icon-newwin'></span>Register</a></div>
    <div id='registerBox' title='Register for CpBroadcast'>
      <div id='noticePlayerName' class='fieldNotice'></div>
      <input type='text' id='playerName' maxlength='<?= $pMax ?>' /><br />
      <div id='noticePasswords' class='fieldNotice'></div>
      <input type='password' id='passwordA' maxlength='<?= $aMax ?>' /><br />
      <input type='password' id='passwordB' maxlength='<?= $aMax ?>' /><br />
      <div id='noticeEMail' class='fieldNotice'></div>
      <input type='text' id='emailAddress' maxlength='<?= $eMax ?>' /><br />
      <input type='text' id='recommended'  maxlength='<?= $pMax ?>'  /><br />
      <div class='fieldNotice'>If you don't pick a Color, we will surprise you by picking one randomly!</div>
      <select id='color'>
        <option value='0'>Pick a Color</option>
        <option value='1'>Blue</option>
        <option value='2'>Green</option>
        <option value='3'>Pink</option>
        <option value='4'>Black</option>
        <option value='5'>Red</option>
        <option value='6'>Orange</option>
        <option value='7'>Yellow</option>
        <option value='8'>Dark Purple</option>
        <option value='9'>Brown</option>
        <option value='10'>Peach</option>
        <option value='11'>Dark Green</option>
        <option value='12'>Light Blue</option>
        <option value='13'>Lime Green</option>
        <option value='15'>Aqua</option>
      </select>
    </div>
    <div id='content' class='ui-corner-all'>
    <?php
    ?>
      Welcome to CpBroadcast, an amazing and powerful Club Penguin Private Server! We're glad you decided to register for our server, and we hope you have a good stay here.<br>
<a href="http://www.cpbroadcast.com/h4-club-penguin-private-server-2011">Click here to play!</a><br>
<a href="http://www.cpbroadcast.com/t3480-how-to-register">How to register</a>
<center><script type="text/javascript"><!--
google_ad_client = "ca-pub-5148796547228631";
/* CPB 1 */
google_ad_slot = "9834355448";
google_ad_width = 250;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></center>
    </div>
  </body>
</html>

When the registration is successful, it sends to this form:

<?php

  function updateStatus($func_classString, $func_messageString) {
    ?><script type="text/javascript">
      updateStatus("<?= $func_classString ?>", "<?= $func_messageString ?>");
    </script><?php
  }

  $password = $_GET['password'];
  $username = trim($_GET['username']);
  $email    = trim($_GET['email']);
  $color    = (integer) $_GET['color'];
  if($color < 1 || $color > 15) $color = rand(1, 15);
  if(strlen($username) < PLAYER_MINLEN) die('Username Too Short');

  $uppername = strtoupper($username);
  if(str_replace(str_split('ABCDEFGHIJKLMNOPQRSTUVWXYZ'), '', $uppername) == $uppername) die('Username Error');


  //if(!Utils::CheckString('0123456789ABCDEF', 32, 32, $password)) die('Password Error');
  if(!Utils::CheckString(PLAYER_CHARS,PLAYER_MINLEN,PLAYER_MAXLEN, $username))  die('Username Error');
  if(!Utils::CheckString(EMAIL_CHARS,EMAIL_MINLEN,EMAIL_MAXLEN, $email)) die('Email Error');

  $query = sprintf("SELECT * FROM `accs` WHERE `name` = '%s'",
  mysql_real_escape_string($username));
 $checkuser = mysql_query($query);
$username_exist = mysql_num_rows($checkuser);
if($username_exist > 0){
    die("Name Taken!");
}

$player = array(
        'email' => $email,
        'registerIP' => $_SERVER['REMOTE_ADDR'],
        'registertime' => time(),
        'color' => $color,
        'head'  => 0,
        'face'  => 0,
        'neck'  => 0,
        'body'  => 0,
        'hands' => 0,
        'feet'  => 0,
        'pin'   => 413,
        'photo' => 0,
        'items' => array(1, 444),
        'coins' => 50000,
        'isModerator'   =>  false,
        'isBanned_' => false,
        'buddies' => array(),
        'ignore' => array(),
        'stamps' => array(),
        'stampColor' => 1,
        'stampHighlight' => 1,
        'stampPattern' => -1,
        'stampIcon' => 1,
        'stampIcon' => 1,
        'igloo' => 1,
        'music' => 0,
        'floor' => 0,
        'furniture' => array(),
        'roomFurniture' => "",
        'mood' => "I am new to CpBroadcast",
);


$query = sprintf("INSERT INTO  `accs` (`ID`,`name`,`crumbs`,`password`)
 VALUES ('NULL', '%s', '%s', '%s');",
 mysql_real_escape_string($username),
 mysql_real_escape_string(serialize($player)),
 mysql_real_escape_string(md5($password)));
 mysql_query($query) or die("Player DB Error: " .mysql_error());
 // Get Last ID
 $playerID = mysql_insert_id(); ?>
<p><strong>You've been registered succesfully</strong><br />
Thank you for signing up at CpBroadcast!<br /></p>
<a href="http://www.cpbroadcast.com/h4-club-penguin-private-server-2011">Click here to play!</a> 
<br />
<a href="http://www.cpbroadcast.com/t3480-how-to-register">How to register</a> <br />
<p><small>In case you were wondering, your PlayerID is <strong><?= $playerID ?></strong></small> :)</p>

<?php updateStatus('ui-state-highlight', '<strong>CpBroadcast Registration Done:</strong> Successful!'); ?>

Here is the result: http://cpcsy.co.cc/register/

The form basically responds if a user tries to use a taken username or email. I would like this to work for IP addresses as well.

Anything I can add to add a little more security and decrease spam accounts.

Upvotes: 2

Views: 1833

Answers (3)

ChrisLively
ChrisLively

Reputation: 88072

Limiting on 1 per IP is NOT the way to go. There are lots of users using the exact same IP address due to proxy servers. This is just going to piss your real users off. Also, most internet users are DHCP'd, which means their IP address changes on a regular basis. If you block by IP, it's temporary at best and means the next person to get that address will be unable to play. You might not see many collisions, but it is a possibility.

There are three common ways around this:

  1. Before an account can be "activated", send them an email. Verify in your code that email addresses can't be duplicated.
  2. Add a simple captcha. This will eliminate a lot of bots.
  3. Ignore the problem completely.

The third option here isn't tongue in cheek, it's a real response. A lot of people like running multiple accounts within a given game. It's generally a tactical thing that can lead to increased stickiness of that person. Meaning, they'll keep coming back.

It really boils down to why you are developing this game. Are you hoping to make money off of it? If so, how? If it's through paid subscription, then the more accounts a person has the more you make off of them. Same for in app purchases. If it's through advertising, then the more they are in the game (regardless of account chosen), the more opportunities you have to make something off of them.

In short, take a look at a couple things. What advantage does a person get when they create multiple accounts? Second, is this advantage really unacceptable? If no, then ignore it. If yes, then determine how to rebalance the game by removing that advantage and the problem will go away.

Upvotes: 3

Parris Varney
Parris Varney

Reputation: 11478

Without reading through all of you code, I'd select a count of transactions WHERE registerIP = $_SERVER['REMOTE_ADDR'] if you get anything other than 0, someone at that IP has already signed up.

Also, check out MySQL's INET_ATON() function for storing those IPs

Quick code to do this:

Before your insert query, add something like this:

$result = mysql_query("SELECT COUNT(*) FROM accs WHERE registerIP = '{$_SERVER['REMOTE_ADDR']}'"); 
$count = mysql_fetch_row($result); 

if (!empty($count[0])) die('Your IP has already been used');

But like others have said, you'll probably have better results using a different mechanism for restricting accounts.

Upvotes: 0

Galen
Galen

Reputation: 30170

Do not use the users IP. This means that me and my roommate can't signup because we both have the same IP.

The best way to do this is to require an email address during signup. When someone signs up, send an email with an activation link and make their account inactive until they click it. They can still create multiple emails to get around this, but most people are lazy and won't do that.

Upvotes: 2

Related Questions