Правила     Закладки     Карма    Календарь    Журналы    Помощь    Поиск    PDA    Чат   
        СМС-ки
   
Пейджер выключен!
 
Фильтр авторов:    показать 
  скрыть
  Ответ в темуСоздание новой темыСоздание опроса

> Защита формы от повторной отправки подробно
Raymond  
 ۩  [x] Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Новичок
*

Профиль
Группа: Пользователь
Сообщений: 40
Пользователь №: 43562
На форуме: 9 месяцев, 17 дней
Карма:




Ниже идет ряд моих заблуждений по поводу пресечения повторной отправки POST,, которые я для себя записал , гуляя по разным форумам.
Они наверное выглядят смешно, поэтому я и хочу разобраться окончательно.
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


Чувствую себя умственно отсталым, и наверное это не просто так...

Это сообщение отредактировал twin - 7.05.2017 - 19:03
PMПисьмо на e-mail пользователю
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Invis1ble  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме




******

Профиль
Группа: Эксперт
Группа переписки
Сообщений: 11976
Пользователь №: 23195
На форуме: 7 лет, 29 дней
Карма: 436

Трезвый :
7 лет, 11 месяцев, 29 дней


Не понятно, в чем вопрос.
Редирект - классический механизм предотвращения случайной повторной отправки, к тому же простой, как палка. Лично я использую аякс (ибо у меня все формы на аяксе).

Цитата (Raymond @ 7.05.2017 - 18:41)
Мало ли у кого отключен JS

Мало. И если отключен, то это не просто так, и человек знает, что он делает. А если не знает - то ССЗБ.


--------------------
PMПисьмо на e-mail пользователюСайт пользователя
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
depp  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Здесь живет
******

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 396
Пользователь №: 40589
На форуме: 2 года, 8 месяцев, 18 дней
Карма: 22




Цитата (Raymond @ 7.05.2017 - 18:41)
Мало ли у кого отключен JS

вот уже убивает эта фраза в 2017 году. отключен js - проблемы клиента.
тоже уже давно все формы ходят только через аякс. ни разу не было проблем, чтобы у кого-то что-то не работало.
PMПисьмо на e-mail пользователю
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
AllesKlar  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Здесь живет
******

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 3708
Пользователь №: 38635
На форуме: 3 года, 7 месяцев, 26 дней
Карма: 199




Цитата (depp @ 10.05.2017 - 09:24)
отключен js - проблемы клиента.
Впринципе, с этим согласен.

Но улыбнуло вот это:
Цитата (depp @ 10.05.2017 - 09:24)
ни разу не было проблем, чтобы у кого-то что-то не работало.

Из серии: 100% утопающих дельфины толкают к берегу. Потому что те, кого толкали от берега уже не смогли ничего рассказать smile.gif


--------------------
[продано копирайтерам]
PMПисьмо на e-mail пользователю
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
SlavaFr  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Новичок
******

Профиль
Журнал
Группа: Форумчанин
Завсегдатай форума
Сообщений: 1565
Пользователь №: 22453
На форуме: 7 лет, 2 месяца, 21 день
Карма: 105




А что если на странице на которой форма показана сделать :
if(isset($_SESSION['form_is_sendet'])) header('Location: http://куда_угодно.ру');


А в том месте где форма обрабатывается, в случае если всё заполненно правильно
 $_SESSION['form_is_sendet'] =true;



в этом случае клиент не сможет посылать повторно формуляр, пока у него имеется сессия.

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


--------------------
↓↓↓↓↓↓↓↓↓↓
ответ может быть здесь
или в mysql_error();
PMПисьмо на e-mail пользователю
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Valick  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Здесь живет
******

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 5671
Пользователь №: 35718
На форуме: 4 года, 9 месяцев, 3 дня
Карма: 176




Цитата
Если пользователь открыл страницу формы, то у него создался уникальный ключ и приделался к форме. Он заполняет ее, может быть долго и муторно. Затем, не отправляя, по какой-то причине открывает такую же страницу в другой вкладке. Теперь у него обновился ключ сессии, и старый устарел. Он пытается отправить форму, которую заполнял на первой вкладке и получает ошибку

Если пользователь зарегистрирован, то ничего не мешает отправлять один и тот же уникальный ключ, до тех пор пока форма не обработана. Но по большому счёту вы загоняетесь, и путаете (сага о мухах и котлетах) повторную отправку (перезагрузка страницы) с принудительной отправкой (новая вкладка).


--------------------
wmr - R281553014107
PMПисьмо на e-mail пользователю
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
  Быстрый ответ
Информация о Госте
Введите Ваше имя
Кнопки кодов
Для вставки цитаты, выделите нужный текст и
НАЖМИТЕ СЮДА
Введите сообщение
Смайлики
:huh:  :o  ;) 
:P  :D  :lol: 
B)  :rolleyes:  <_< 
:)  :angry:  :( 
:unsure:  :blink:  :ph34r: 
     
Показать всё

Опции сообщения  Включить смайлики?
 Включить подпись?
 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:

Опции темы Ответ в темуСоздание новой темыСоздание опроса