У меня есть базовая форма регистрации для игры, которая у меня есть, и в основном она для новичков, и она позволяет пользователям создавать столько учетных записей, сколько им заблагорассудится. Я искал, но не нашел конкретного ответа.

Мне в основном нужен способ либо ограничить использование формы, либо ограничить создание учетной записи до 1 на IP.

Вот основной код формы:

<?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@Address.com',
        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>

После успешной регистрации он отправляет в эту форму:

<?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!'); ?>

Вот результат: http://cpcsy.co.cc/register/

Форма в основном отвечает, если пользователь пытается использовать взятое имя пользователя или адрес электронной почты. Я бы хотел, чтобы это работало и для IP-адресов.

Все, что я могу добавить, чтобы немного повысить безопасность и уменьшить количество спам-аккаунтов.

2
Nick 25 Авг 2011 в 20:10

3 ответа

Лучший ответ

Ограничение по 1 на IP - НЕ лучший вариант. Многие пользователи используют один и тот же IP-адрес из-за прокси-серверов. Это просто разозлит ваших настоящих пользователей. Кроме того, большинство интернет-пользователей используют DHCP, что означает, что их IP-адреса регулярно меняются. Если вы блокируете по IP-адресу, это в лучшем случае временное явление и означает, что следующий человек, получивший этот адрес, не сможет играть. Вы можете не увидеть много столкновений, но это возможно.

Есть три распространенных способа обойти это:

  1. Прежде чем учетная запись может быть «активирована», отправьте им электронное письмо. Убедитесь, что в вашем коде нельзя дублировать адреса электронной почты.
  2. Добавьте простую капчу. Это избавит от множества ботов.
  3. Полностью игнорируйте проблему.

Третий вариант здесь не в шутку, это реальный ответ. Многим людям нравится иметь несколько учетных записей в одной игре. Как правило, это тактический прием, который может сделать человека более липким. Значит, они будут возвращаться.

Это действительно сводится к тому, зачем вы разрабатываете эту игру. Вы надеетесь на этом заработать? Если да, то как? Если это через платную подписку, то чем больше у человека аккаунтов, тем больше вы на них зарабатываете. То же самое для покупок в приложении. Если это происходит через рекламу, то чем больше их в игре (независимо от выбранной учетной записи), тем больше у вас возможностей что-то использовать.

Короче говоря, взгляните на пару вещей. Какое преимущество получает человек, когда он создает несколько учетных записей? Во-вторых, действительно ли это преимущество неприемлемо? Если нет, проигнорируйте это. Если да, то определите, как перебалансировать игру, убрав это преимущество, и проблема исчезнет.

3
NotMe 25 Авг 2011 в 16:59

Не используйте IP пользователей. Это означает, что я и мой сосед не можем зарегистрироваться, потому что у нас один и тот же IP-адрес.

Лучший способ сделать это - запросить адрес электронной почты при регистрации. Когда кто-то зарегистрируется, отправьте электронное письмо со ссылкой для активации и сделайте его учетную запись неактивной, пока он не нажмет на нее. Они все еще могут создать несколько писем, чтобы обойти это, но большинство людей ленивы и не будут этого делать.

2
Galen 25 Авг 2011 в 16:22

Не читая весь ваш код, я бы выбрал количество транзакций WHERE registerIP = $_SERVER['REMOTE_ADDR'], если вы получите что-либо, кроме 0, кто-то с этим IP уже зарегистрировался.

Также проверьте MySQL INET_ATON () функция для хранения этих IP-адресов

Быстрый код для этого:

Перед вашим запросом на вставку добавьте что-то вроде этого:

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

Но, как говорили другие, у вас, вероятно, будут лучшие результаты, если использовать другой механизм ограничения учетных записей.

0
Parris Varney 25 Авг 2011 в 16:32