Как предотвратить двойную / повторную отправку форм в CakePHP? - PullRequest
4 голосов
/ 16 марта 2009

Я обнаружил, что компонент безопасности в CakePHP помогает предотвратить CSRF, добавляя токены как скрытые значения в формы.

Что мне было интересно, если так или иначе было предотвращено дублирование представления формы с использованием этого компонента или какого-либо другого компонента / помощника?

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

спасибо

Ответы [ 7 ]

2 голосов
/ 15 июля 2014

@ DoctorFox уже ответил на него csrfUseOnce = true, но это бросит вас в черные дыры, которыми вы все еще должны управлять. Итак, полное решение для меня:

class YourAppController extends AppController {

    public $helpers = array('Html', 'Form');
    public $components = array('Security');

    public function beforeFilter() {
        $this->Security->csrfUseOnce = true;
        $this->Security->blackHoleCallback = 'blackhole';
    } 

    public function blackhole($type) {
        $this->redirect(array('action' => 'index'));
    }

Если перенаправление отсутствует, вы по-прежнему открыты для двойной отправки формы.

Ссылка: Компонент безопасности CakePHP

2 голосов
/ 07 апреля 2016

Я поместил событие onClick, которое отключает кнопку следующим образом:

<?= $this->Form->button('Salvar', [
                    'value' =>'Submit', 
                    'onClick' => 'form.submit();this.disabled=true'
]) 
?>
2 голосов
/ 06 апреля 2012

В CakePHP 2.x есть компонент в компоненте безопасности, который позволяет вам выбирать либо использовать один и тот же токен до истечения срока его действия, либо один раз. Поместите это в ваши контроллеры методом beforeFilter:

$this->Security->csrfUseOnce = true;

Найти больше информации здесь

2 голосов
/ 17 марта 2009

Вы можете реализовать в Cake те же вещи, что и раньше.

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

Я бы порекомендовал сделать это в методе save (..) вашей модели, поэтому вам не нужно беспокоиться о его добавлении в нескольких местах кода.

1 голос
/ 16 августа 2013

Просто сделайте PRG Pattern .. Это очень просто, верно ?! Ну, по крайней мере, так говорят все, но никто не дает четкого ответа! У меня ушла неделя поиска и копания, а потом «Новичок» решил что-то сделать самостоятельно! Вот один из способов сделать это в cakephp (я использую 2.0.5):

Независимо от кода здесь логика в шагах:
1- набор данных
2- подтвердить (НЕ создавать () еще)
3- записать $ this-> request-> data в переменную сеанса
4 - перенаправить на действие saveData

Внутри действия saveData:
5 - прочитать и сохранить переменную сеанса
6- УДАЛИТЬ переменную сеанса
7- создать ()
8- сохранить данные в модель
9- перенаправление

Вот пример того, как может выглядеть ваш код.
** Внимание: " ourController " и " ourModel "

public function add() {
        if ($this->request->is('post')) {
            if (isset($this->request->data)) {
                $this->ourModel->set($this->request->data);
                if ($this->ourModel->validates()) {
                    $this->Session->write('myData', $this->request->data);
                    $this->redirect(array('controller' => 'ourController', 
                                           'action' => 'saveData',
                                           'ourModel' //optional but recommended
                                          )
                                    );
                } else {
                    $this->Session->setFlash('ourModel could not be saved.');
                     }
          }
.....//the rest of add() function
}

Тогда вы должны быть перенаправлены (при проверке) на эту функцию, которая перенаправляет вас снова на индексирование или на то, куда вас ведет логика!

public function saveData($model) {
        $myData = $this->Session->read('myData');
        $this->Session->delete('myData'); //extremely important
        $this->$model->create();
        if ($this->$model->save($myData)) 
               // or $myData[$model] if you are dealing with multiple models
              {
              $this->Session->setFlash(__($model.' have been saved successfully'));
              $this->redirect(array('controller' => 'ourController',
                                    'action' => 'index'
                                    )
                               );
            } 
        } else{
            $this->Session->setFlash(__($model.' could not be saved'));
        }
        }
    }

Может сработать простое перенаправление, но в большинстве случаев вы хотите перенаправить в другое представление (например, в другую форму или в индексное представление)

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

0 голосов
/ 10 февраля 2012

Компонент Security должен работать, кроме того, вы также можете сбросить данные сразу после публикации:

unset($this->data['yourModel']);
0 голосов
/ 17 марта 2009

Не знаю о торте, но постарайтесь не отображать содержимое в запросе POST, сделайте само перенаправление. Двойной пост будет решен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...