Они наверное выглядят смешно, поэтому я и хочу разобраться окончательно.
PAMAGITI :))
==================================================================================================== ========
Вот тут https://habrahabr.ru/post/86280/ один человек в самом конце пишет, что можно просто создать на странице формы токен (не уникальный), а в скрипте-обработчике его уничтожить
То есть:
* Страница формы:
$_SESSION['token'] = true;
//html-код формы
* Скрипт-обработчик:
if(isset($_POST['submit'])){
if(isset($_SESSION['token']) && $_SESSION['token'] === true){
//обрабатываем форму
unset($_SESSION['token']);
}
else{
//Выдаем ошибку о повторной отправке
}
}
Это решение не подходит.
Допустим если пользователь отправит форму, попадет на страницу обработчика, останется там. Токен удален , и при обновлении страницы повторная ообработка данных происходить не будет. Вроде все нормально. Но.
Теперь он откроет другую вкладку, попадет на страницу с форммой, тем самым создаст токен опять. Перейдя на страницу обработчика иобновив ее, он сможет отправить данные повторно, т.к. if(isset($_SESSION['token']) && $_SESSION['token'] === true) даст true.
Короче, метод не рабочий.
======================================================
======================================================
Метод 2 - уникальный ключ для формы.
Суть:
- создается переменная сессии или кука с уникальным значением
- к форме добавляется скрытое поле с этим уникальным значением
- в обработчике формы сверяются значения из сессии/куки и из скрытого поля
- если все совпадает, то обновляем сессионное значение/куку и выполняем необходимые процессы. Если нет - выдаем ошибку или что-нибудь по своему вкусу.
Например так:
* Страница с форммой:
<?php
session_start();
$_SESSION['token'] = уникальное значение;
?>
<form method = 'POST' action = 'script.php'>
<input type = 'text' name = 'user_name'/>
<input type = 'hidden' name = 'token' value = '<php echo $_SESSION['token']; ?>' />
<input type = 'submit' name = 'submit'/>
* Скрипт-обработчик:
<?php
session_start();
if(isset($_POST['submit'])){
if($_SESSION['token'] === $_POST['token']){
//обрабатываем форму
$_SESSION['token'] = новое уникальное значение;
}
else{
//Выдаем ошибку о повторной отправке
}
?>
Гарантированная защита . Но есть проблема, и она серьезная:
Если пользователь открыл страницу формы, то у него создался уникальный ключ и приделался к форме. Он заполняет ее, может быть долго и муторно. Затем, не отправляя, по какой-то причине открывает такую же страницу в другой вкладке. Теперь у него обновился ключ сессии, и старый устарел. Он пытается отправить форму, которую заполнял на первой вкладке и получает ошибку,
т.к. токен из формы вкладки 1 не совпадает с новым.
тут https://phpclub.ru/talk/threads/Защита-форм...отправки.83304/
fixxer предлагает (пост N 11) создать массив ключей в сессии.
проблема , как я понял, будет в том, что придется держать в сессии большое количество данных. Особенно если ключи будут длинные
Ну и если количество открытых юзером вкладок страницы с формой превысит лимит размера массива, то форма первой из вкладок все-таки не пройдет проверку.
тут http://phpforum.su/index.php?showtopic=92222&st=0 AllesKlar, предлагает вот что:
if(!empty($_POST)) {
$_SESSION['POST'] = $_POST;
header('location: form_handler.php');
exit;
}
//form_handler.php
if(empty($_SESSION['POST'])) {
exit;
}
$post_data = $_SESSION['POST'];
$_SESSION['POST'] = array();
Минус (наверное) в том, что на время работы обработчика сессия будет забита POST-данными, и если их размер очень большой, то сильно забита.
==================================================================================================== ========
Еще один метод - тупо редирект. Безо всяких ключей и тд.
Суть:
Получаем POST данные в скрипте-обработчике, обрабатываем, а потом делаем редирект на другую страницу. Таким образом, POS-массив очищается и все, проблема решена. Но вот, что пишут тут https://habrahabr.ru/post/86280/#comment_2579959
Если это правда, то способ не очень то надежный. Его надо применять в паре с другим методом, например с уникальным ключом.
==================================================================================================== ========
Пожалуй, самый лег вариант - это отправка формы через ajax. Там вопрос повторной оправки не стоит вообще.
Но это подходит не всегда. Мало ли у кого отключен JS
Чувствую себя умственно отсталым, и наверное это не просто так...