2015-05-22 2 views
0

У меня есть форма, и я хочу, чтобы она была как можно более безопасной. Поэтому у меня есть эта функция, которая генерирует токен формы.Хранение токена PHP в сеансе, но он постоянно менялся

 function generateFormToken($form) { 

     // generate a token from an unique value 
     $token = hash('sha256', uniqid(microtime())); 
     // Write the generated token to the session variable to check it against the hidden field when the form is sent 
     $_SESSION[$form.'_token'] = (string)$token; 

     return $token; 
    } 

Вот как он активируется:

 if (empty($_POST)){ 
      $newToken = generateFormToken('form1'); 
     } 

Вот функция, я использую, чтобы проверить это:

function verifyFormToken($form) { 

    // check if a session is started and a token is transmitted, if not return an error 
    if(!isset($_SESSION[$form.'_token'])) { 
     return false; 
    } 

    // check if the form is sent with token in it 
    if(!isset($_POST['token'])) { 
     return false; 
    } 

    // compare the tokens against each other if they are still the same 
    if ($_SESSION[$form.'_token'] !== $_POST['token']) { 
     return false; 
    } 

    return true; 
    } 

Мой HTML форма имеет скрытый вход в который я поставил новая переменная токена. Форма отправляется на ту же страницу через form action="#".

Проблема в том, что по какой-то причине, когда обновление страницы, даже если функция не звонит снова, изменения токена в сеансе, но она остается неизменной в форме.

Я действительно потерялся, так как думал, что просят PHP хранить строку в сеансе, она не изменится, когда страница обновится в этих условиях, но она продолжает давать мне другой ответ. Я пытался позвонить die() до того, как он войдет в функцию, чтобы убедиться, что функция не как-то снова загружается в скрипте, но ничего не происходит. Теоретически он не должен обновляться.

Помогите мне пожалуйста.

Вот HTML форма:

<form action="#" method="POST" id="form1"> 
     <label for="firstname">Firstname</label> 
     <input type="text" name="firstname"> 
     <input type="hidden"name="token" value="<?= $newToken; ?>"> 
    </form> 

А вот логика проверки, которую я использую в верхней части моей страницы:

$msg = ""; 
    //If the form has been filled 
    if (!empty($_POST)){ 
     //If the form has been sent from our website 
     if (verifyFormToken('form1') == true){ 
      //TODO CAPTCHA 
      if (1 == 1){ 
       //Everything's fine 
      } 
      else{ 
      $msg = 'Veuillez cocher la case «Je ne suis pas un robot».'; 
      } 
     } 
    //Else, user tried to send data with his own script (Possible XSS attack) 
    else{ 
     $msg = 'Veuillez utiliser le formulaire directement sur notre site Web afin d\'appliquer sur l\'offre d\'emploi'; 
    } 
} 
else{ 
    //If form is not sent, we generate a new token and store it in the user's session 
    $newToken = generateFormToken('form1'); 
} 
if (!empty($msg)){ 
    echo $msg; 
} 
+0

Вы уверены, что функция не работает снова? Вы пробовали 'print_r ($ _ POST)', чтобы убедиться, что он пуст. Попробуйте помещать выражение 'echo' внутри функции, чтобы увидеть, получает ли он каждое обновление. –

+0

100% уверен ..., Я пробовал именно это, и он не ответил на что-то –

+0

, ваш скрытый атрибут не содержит атрибут имени и убедитесь, что на вашем сервере включены короткие теги. –

ответ

0

Обычно, когда $_SESSION маркер меняется, даже если вы установите его правильно, это потому, что вы не установили session_start() должным образом.

Попробуйте посмотреть в начале файла и добавить session_start() там, если вы еще не

+0

9,9 раза из 10, OP возвращается и говорит, что он был запущен. Но ... возможно, вы правы, возможно, вы правы. –

+0

Действительно началось –

+0

посмотри, что я сказал тебе?^ –

0

Следующая была протестирована.

Apache версии: 2.2.29, PHP версия: 5.4.24, версия MySQL: 5.5.42-37.1, Архитектура: x86_64, Операционная система: Linux

form.php

<?php 
include('so-sessions.php'); 

$form = "form1"; // set form id 

// check if form has been submitted 
IF (isset($_POST['token'])) { 

    $msg = ""; // default response 

    // Validate Token 
    IF (VerifyFormToken($form)) { 

     $msg = "Token is valid"; 

    }ELSE{ 

     $msg = "Token is invalid"; 

    } 

    echo("<p>".$msg."</p>"); 

}ELSE{ 
    // form not submitted 

    $token = Set_TokenSession($form); // Set token 

    // debugging 
    echo("<p>Token: ".$token."</p>"); 

    // form 
    echo(' 
    <form action="#" method="post" id="'.$form.'"> 
     <input type="hidden" name="token" value="'.$token.'"> 
     <label for="firstname">First Name: </label><input type="text" name="firstname" /> 
     <input type="submit" name="submit" value="submit" /> 
    </form>'); 

} 
?> 

так sessions.php

<?php 
Function HasSessionStarted() { 

    $result = false; // default to false 

    // Check if session has started 
    IF ((session_status() == PHP_SESSION_NONE) || (session_id() == '')) { 
     $result = true; 
    } 

    return $result; 

} 

Function GenerateFormToken() { 

    // Create token 
    $result = hash('sha256', uniqid(microtime())); 

    return $result; 

} 

Function Set_TokenSession($form) { 

    $new_session = HasSessionStarted(); // Check Session Status 
    $token = GenerateFormToken(); // Create token 

    // If the session hasn't started do so 
    IF ($new_session) { session_start(); } 

    // Unset any pre-set token 
    Unset_TokenSession($form); 

    // Set new session token 
    $_SESSION[$form.'_token'] = $token; 

    // End the current session and store session data 
    IF ($new_session) { session_write_close(); } 

    return $token; 

} 

Function Unset_TokenSession($form) { 

    $new_session = HasSessionStarted(); // Check Session Status 
    IF ($new_session) { session_start(); } 

    // Unset session token 
    IF (isset($_SESSION[$form.'_token'])) { unset($_SESSION[$form.'_token']); } 

    // End the current session and store session data 
    IF ($new_session) { session_write_close(); } 

} 

Function VerifyFormToken($form) { 

    $result = false; // default result to fail 

    $new_session = HasSessionStarted(); // Check Session Status 
    IF ($new_session) { session_start(); } 
    $sesstoken = $_SESSION[$form.'_token']; 
    Unset_TokenSession($form); // Unset the used token 
    IF ($new_session) { session_write_close(); } 

    // debugging 
    #echo("<!-- Tokens (Form/Session) : ".$_POST['token']."/".$sesstoken." -->"); 

    // check if session and post token are not empty 
    IF ((!empty($sesstoken)) && (!empty($_POST['token']))) { 

     // compare the tokens against each other 
     IF ($sesstoken == $_POST['token']) { 
      $result = true; 
     } 

    } 

    return $result; 

} 
?> 
+0

Можете ли вы объяснить это, чтобы люди, посетившие этот вопрос, знали, что происходит? –

+0

Это не работает, к сожалению, такая же ошибка, поскольку я уже начал сеанс в начале моего документа –

+0

@ Fred-ii- .. Лучше? @ Yann Chabot ... Вы обновляете страницу или отправляете форму? – Brian

0

Вы пропустили концовку запятой в коде: <input type="hidden" value="<?= $newToken ?>">. Это ->$newToken;

+0

К сожалению, как я уже сказал, токен во вводе посылает отлично через заголовки POST, это переменная сеанса, которая постоянно изменяется, даже если функция не будет вызвана –