Уникальный формальный токен отключает многозадачность для пользователя

Если я хочу защитить свой сайт и пользователей от атак Cross Site Forgery (CSRF), я могу сгенерировать уникальный токен $token = md5( time() * rand ); на каждой странице, которая имеет форму. Токен отправляется в скрытое поле ввода echo '<input type="hidden" name="token" value="'.$token.'">'; и в то же время хранится в переменной сеанса $_SESSION['token'] = $token; ,

Я проверю, если в любой представленной форме, if($_POST['token'] == $_SESSION['token']) и действуйте соответственно.

Однако некоторые пользователи могут выполнять многозадачность. Это то, что я сейчас делаю сейчас, пока я публикую это.

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

Но если бы я сделал это на своем сайте, это означало просмотр других страниц при составлении сообщения / формы – мой $token был бы регенерирован каждый раз, когда я вытаскиваю другую страницу с моего сайта. Создание скрытого input токена в форме, над которой я работаю, и в конечном итоге вы хотите отправить неверную информацию , потому что она больше не будет соответствовать переменной $_SESSION['token'] , которая была обновлена, когда я посетил другую страницу …

    Любые хорошие идеи, как предотвратить эту проблему, или какие-либо лучшие решения, чтобы остановить CSRF в первую очередь?

    Я хочу разрешить моим пользователям многозадачность и хочу, чтобы их защищали от CSRF …

    Related of "Уникальный формальный токен отключает многозадачность для пользователя"

    У меня была та же проблема с тем, что вы заявляете из-за одиночного CSRF, и его заменяют, если они не отправляют последнюю страницу, но если вы используете массив w / session, он должен решить вашу проблему. Также вы можете включить капчу, я бы рекомендовал Recaptcha от Google.

     session_start(); function createToken(){ $token = sha1(uniqid(mt_rand(), true)); $_SESSION['Tokens']['Token'][] = $token; $_SESSION['Tokens']['Time'][] = time() + (10 * 60); #10 min limit #you can omit/change this if you want to not limit or extend time limit return $token; } function checkToken($token){ clearTokens(); foreach($_SESSION['Tokens']['Token'] as $key => $value){ if($value === $token){ return true; } } return false; } function clearTokens(){ foreach($_SESSION['Tokens']['Time'] as $key => $value){ if($value <= time()){ unset($_SESSION['Tokens']['Token'][$key], $_SESSION['Tokens']['Time'][$key]); #remove last parameter if you aren't using token time limit } } } 

    ваш HTML:

     <input type="hidden" name="token" value="<?php createToken(); ?>"> 

    PHP Token Checker

     if(isset($_POST['token']) && checkToken($_POST['token'])){ #valid token }else{ #create error message saying that they tried to repost data or session token expired } 

    Браузер должен поддерживать правильный идентификатор сеанса даже между вкладками и окнами, идентификатор сеанса должен быть одинаковым. (опасное предположение должно быть проверено на кросс-браузер, чтобы быть уверенным)

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

    так что вы можете проверить что-то вроде этого.

     $tokenCorrect = false; foreach($_SESSION['tokens'] as $token) { if ($token !== $_POST['token']) continue; $tokenCorrect = true; } if ($tokenCorrect == false) { die(); // // Maybe log to database ?? but watch if possible Denial of Service because somebody can write your disk/ shared diskspace full with only making fast requests with a invalid CSRF token }