2011-01-06 2 views
12

Я придумал технику, чтобы предотвратить повторную подачу формы, возвращая/переместив или обновив страницу. И я подумал о том, чтобы судить об этом здесь, я уже тестировал образец не в производственной среде, какие недостатки вы можете идентифицировать?Предотвращение повторных представлений формы

Обратите внимание, что мне хорошо известно использование форм-токенов, которые защитят вас от атак CSRF и не будут добавлены в следующие шаги.

-Generate Форма ID для каждой формы, и использовать его как скрытое поле в форме:

$formid = microtime(true)*10000; 

- На форме представить:

  • Validate из данных

  • Рассчитать хэш данных полей формы

    $allvals = ''; 
    foreach($_POST as $k=>$v){ 
        $allvals .= $v; 
    } 
    $formHash = sha1($allvals); 
    
  • Подтвердить форму хеша по сравнению с ранее сохраненными хэшами. значение сеанса привязывается к каждой форме переменной $ formid.

    $allowAction = true; 
    if(isset($_SESSION['formHash'][$_POST['formid']]) && ($_SESSION['formHash'][$_POST['formid']] == $formHash)){ 
        $allowAction = false; 
    } 
    
  • Если форма hash не была найдена, значит, это первая форма, представленная или данные формы изменены.
  • Если данные сохраняются (в базу данных, например), сохранить форму хэш сессии:

    $_SESSION['formHash'][$_POST['formid']] = $formHash; 
    

Полная версия кода: http://thebusy.me/2011/01/06/preventing-duplicate-form-submissions/

+0

Рассмотрим сравнительный анализ хеш-фрагмента против '$ formHash = sha1 (serialize ($ _ POST));'. Это тоже ключи хеширования, которые могут или не могут быть полезными. – Dan

+0

Возможно, связано/dup, http://stackoverflow.com/questions/4614052/how-to-prevent-multiple-form-submission-on-multiple-clicks-in-php/4614310#4614310 – user562374

+0

Возможный дубликат http://stackoverflow.com/questions/218907/how-to-handle-multiple-submissions-server-side –

ответ

7

Более простой способ добиться того, что вы хотите использовать перенаправление на submit. После обработки запроса POST вы перенаправляете, возможно, даже на ту же страницу. Это общий шаблон, называемый «Перенаправление после POST» или POST/Redirect/GET.

Например:

<?php 
if($_POST) { 
    // do something 

    // now redirect 
    header("Location: " . $_SERVER["REQUEST_URI"]); 
    exit; 
} 
?> 

<html> ... 
<form method="post" action=""> ... </form> 

, устанавливая действие в «», то он будет представлять себе, в какой момент, если ($ _ POST) блок кода будет проверять, чтобы верно и обрабатывать форму, а затем перенаправить назад к себе.

Конечно, вы, вероятно, хотите перенаправить на другую страницу, на которой отображается ответ «Ваша форма была отправлена» или поместить форму на другую страницу, и HTML-код этой страницы будет ответом.

Преимущество этого метода в том, что, когда вы нажимаете кнопку «Назад», он выполняет запрос GET, чтобы форма не была повторно отправлена.

В Firefox он фактически берет на себя представление из истории браузера, поэтому, когда пользователи просматривают веб-страницы, а затем отбрасывают назад, вместо того, чтобы видеть страницу «спасибо», они видят страницу формы.

+0

да, я читал об этом, и я буду использовать его для будущих проектов. проблема в моих текущих сайтах, я использую токены формы, и я не хочу менять структуру кода, перенаправляя на другие страницы. Спасибо @ newz2000 – isogashii

+1

, вы даже можете сделать еще один шаг, чтобы дать вам сообщение благодарности. Настройка 2 divs, одна с формой и одна с благодарственным сообщением. Затем установите знак div для отображения: none в css. Верните перенаправление назад в formpage.php? Thankyou = 1 if ($ _GET ['thankyou'] == 1) {css, чтобы сделать div формы div none, и установите благодарность за отображение: block} – MSD

+5

должны быть объединены с токенами формы, чтобы быть надежными. Если пользователь обновляется или повторно отправляется во время выполнения запроса POST, вы получаете дубликат запроса. – bcoughlan

1

Похоже, вы слишком усложняетесь.Мой любимый способ, потому что он также предотвращает некоторые сессии для домкрата хаков в то же время, как описано здесь:

http://www.spotlesswebdesign.com/blog.php?id=11

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

+2

благодарю вас за ответ, но в сообщении говорится: «Важно, чтобы ваша логика обработки формы произошла до того, как вы установите новый идентификатор экземпляра страницы сеанса, чтобы это работало , хотя есть способы обойти это ». Попробуйте открыть две страницы одновременно, отправка первого не будет работать, потому что при открытии второй страницы создается новый идентификатор страницы, это слабость этой техники. Но вы можете использовать массив сгенерированных идентификаторов страниц и проверять их, а также удалить тот, который соответствует массиву. – isogashii

+0

Хорошая точка. Массив - отличная идея. – dqhendricks

+0

@isogashii Я изменил статью, чтобы отразить метод на основе массива. – dqhendricks

-1

Оба вышеупомянутых решения хороши, но немного коротки.

Как насчет остановки дальнейших вставок в ближайшие несколько минут от того же пользователя с возможными незначительными изменениями в данных?

Это можно сделать, поставив хэш-файл md5 в файл cookie на компьютере пользователя и сохранив копию в базе данных - таким образом любая дальнейшая попытка с той же машины в течение указанного времени может быть проигнорирована и остановлена ​​от вставки в базы данных.

Возможно, кто-то может прокомментировать действительность и эффективность моего предложения, или я лаяю неправильное дерево ???

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