2016-09-07 2 views
1

Я написал сценарий для защиты своей формы с помощью токена сеанса; однако мой скрипт не работает, если я пытаюсь проверить поля формы перед проверкой маркера. Кто-нибудь поможет мне выяснить, что не так с моим сценарием, пожалуйста?Защитить форму с помощью токена сеанса

<?php 
      session_start(); 
      class TOKEN { 
      public static function generate() { 
       return $_SESSION['token'] = base64_encode(openssl_random_pseudo_bytes(15)); 
      } 
      public static function check($token) { 
       if (isset($_SESSION['token']) && $token === $_SESSION['token']) { 
       unset($_SESSION['token']); 
       return true; 
       } 
       return false; 
      } 
      } 
     ?> 
     <?php 
      $display_form = FALSE; 
      if (isset($_POST['submit'])) { 
      $username = $_POST['username']; 
      $userpass = $_POST['userpass']; 

      if (strlen($username) < 4) { 
       $error_name = 'required'; 
       $display_form = true; 
       $validation_error = true; 
      } 
      if (strlen($userpass) < 8) { 
       $error_pass = 'required'; 
       $display_form = true; 
       $validation_error = true; 
      } 
      if (!$validation_error) { 
       if (TOKEN::check($_POST['token'])) { 
       echo 'process form'; 
       } else { 
       echo 'invalid security token'; 
       } 
      } 
      } else { 
      $display_form = TRUE; 
      } 
     ?> 
     <!DOCTYPE html> 
     <html lang="en"> 
     <head> 
      <meta charset="UTF-8"> 
      <title>Title</title> 
     </head> 
     <body> 
     <?php 
      if ($display_form == true) { 
     ?> 
     <form method="post" action="<?php echo htmlspecialchars($_SERVER['REQUEST_URI']); ?>"> 
      <input type="hidden" name="token" value="<?php echo TOKEN::generate(); ?>"> 
      <input type="text" name="username" id="" placeholder="username"> 
      <?php echo $error_name; ?> 
      <br> 
      <input type="password" name="userpass" id="" placeholder="Password"> 
      <?php echo $error_pass; ?> 
      <br> 
      <input type="submit" name="submit" value="Sign in"> 
     </form> 
     </body> 
     </html> 
     <?php 
     } 
     ?> 
+0

Проверяли ли Вы генерируемой HTML? Вы проверили '$ _POST'? –

+0

Да, я сделал, и токен сгенерирован в html. Если я отправлю форму без каких-либо ошибок, она будет работать. Но если требуется одно или оба поля, и я исправляю проверку полей, а затем отправляю форму, она отображает недействительный токен безопасности. – Bootflux

ответ

0

Этот код очень трудно прочитать. Я не могу сказать, когда начинаются и заканчиваются утверждения. Также прекратите использовать классы для всего. Используйте процедурное программирование, как большой мальчик.

Ваша проблема проста. $validation_error не был инициализирован во внешней области. Это означает, что он не был сохранен между статусами.

Чтобы исправить это просто добавить $validation_error = false на внешней области:

... 
$display_form = FALSE; 
$validation_error = false; // right here 
      if (isset($_POST['submit'])) { 
      $username = $_POST['username']; 
      $userpass = $_POST['userpass']; 
      ... 
0

Я полагаю, что проблема здесь заключается в следующем.

  1. У вас есть маркер в виде и лексема сессии. Они равны.
  2. Когда вы заполняете форму с ошибками - ваша форма загружается снова. Но! На сеансе у вас есть предыдущий токен, из пункта 1, а в форме у вас есть новый токен.
  3. Вы снова отправляете и проверяете разные жетоны.

Таким образом, решение является unset лексем всегда, независимо от того, вы не имеете неправильные или правильные значения в форме.

Update:

Я предполагаю, что это должно быть что-то вроде:

if (!$validation_error) { 
    // here token will be removed in `TOKEN::check` 
    if (TOKEN::check($_POST['token'])) { 
    echo 'process form'; 
    } else { 
    echo 'invalid security token'; 
    } 
} else { 
    // remove token implicitly 
    TOKEN::remove(); 
} 

И в TOKEN:

public static function check($token) { 
    $result = false; 

    if (isset($_SESSION['token'])) { 
    if ($token === $_SESSION['token']) { 
     $result = true; 
    } 
    // if token set - remove it 
    self::remove(); 
    } 

    return $result; 
} 

public static function remove() { 
    unset($_SESSION['token']); 
} 
+0

u_mulder, вы абсолютно правы, это то, что происходит, не могли бы вы рассказать мне, где мне нужно включить неактивный токен? и это то, что я должен: unset ($) SESSION ['token']); – Bootflux

+0

Отметьте обновленный ответ. –

+0

По-прежнему недействительный токен безопасности после применения вашего решения выше – Bootflux

Смежные вопросы