Octobercms — защита CSRF в форме для предотвращения многократной отправки

У меня есть компонент с формой, а затем код для обработки отправки. Проблема в том, что если я спамлю кнопку, она отправит форму несколько раз. Решением этого было бы добавление отключенного состояния через Javascript, чтобы пользователь не мог этого сделать.

Из соображений безопасности я не хочу, чтобы это происходило вообще, и предотвращало серверную сторону. У меня есть токен и в конфиге включен CSRF

'enableCsrfProtection' => true,

Вот моя форма

{{ form_open({ request: 'onSubmit' }) }}

            <div class="form-group">
                <label class="control-label" for="subject_name">Subject's name</label>
                <input id="subject_name" name="subject_name" type="text" placeholder="" class="form-control input-md" required="">

            </div>

            <div class="form-group">
                <label class="control-label">Postcode</label>
                <input id="postcode"  name="postcode" class="form-control input-md" type="text" required>
            </div>

            <div class="form-group">
                <button id="submit" type="submit" value="submit" class="btn btn-lg btn-gold pull-right"><i class="fa fa-lock"></i> Request Job</button>
            </div>

 </form>

и в сгенерированном html

Обработчик/Сессия/Токен

<input name="_handler" type="hidden" value="onSubmit">
<input name="_session_key" type="hidden" value="7Eg9bK4pcT2NOgWwUS0UFUckjkSMRC1UDBkBhPwO">
<input name="_token" type="hidden" value="00nbkK3EAo2I8WGWSh85qkMjHYig6aldrd3oe8HZ">

Затем в моем коде компонентов

public function onSubmit()
{

    $name = post('subject_name');
    $postcode = post('postcode');

    if (Session::token() != Input::get('_token')) 
    { 

        /* Invalid token */ 
        return print('Token invalid');

    }

    $job = new Job;
    $job = $job->name = $name;
    $job = $job->postcode = $postcode;
    $job->save();

}

Тем не менее, я спамлю кнопку отправки, и она будет выполняться несколько раз. Как я могу добавить возможность выполнять только один раз?


person ServerSideSkittles    schedule 21.08.2019    source источник
comment
Защита CSRF не имеет ничего общего с множественной отправкой. Если вы просто хотите остановить несколько отправок, просто установите значение сеанса, например: Session::set('form_posted', true); в конце метода, а затем добавьте в начале проверку, которая проверяет, установлено ли оно или нет. Если он установлен, ничего не делайте.   -  person Magnus Eriksson    schedule 21.08.2019
comment
@MagnusEriksson Ну, не совсем, если бы я мог принудительно использовать новый токен для каждого запроса. Что вы предлагаете мне сделать, чтобы остановить его отправку несколько раз?   -  person ServerSideSkittles    schedule 21.08.2019
comment
Я не сторонник обновления токенов при каждом запросе, так как это может привести к раздражающим проблемам для пользователей. Пример: пользователь открывает ваш сайт. Затем нажмите на ссылку и откройте ее в новой вкладке. Затем вернитесь на первую вкладку и попробуйте опубликовать форму, но CSRF теперь недействителен, так как вы обновили его на другой вкладке.   -  person Magnus Eriksson    schedule 21.08.2019
comment
@MagnusEriksson хорошая мысль. Будет ли сессия лучшим способом пойти тогда? Просто подумал, что если они захотят отправить еще один запрос в том же сеансе, они не смогут этого сделать. Я просто хочу остановить его выполнение несколько раз в течение минуты или около того. Будет ли это сводиться к установке временной метки?   -  person ServerSideSkittles    schedule 21.08.2019
comment
Это определенно должно сработать. Если сеанс не существует или если временная метка старше x минут, обработайте отправленную информацию, в противном случае верните какое-то сообщение об ошибке или что-то в этом роде. Это не помешает им опубликовать его несколько раз из разных браузеров и/или в режиме инкогнито. Но это более крепкий орешек.   -  person Magnus Eriksson    schedule 21.08.2019


Ответы (2)


Вам нужен загрузчик

https://octobercms.com/docs/ui/loader

<div class="loading-indicator-container">

    <button id="submit" type="submit" value="submit" data-load-indicator="Saving..." class="btn btn-lg btn-gold pull-right"><i class="fa fa-lock"></i> Request Job</button>
</div>
person Tschallacka    schedule 21.08.2019

Есть множество решений того, что вы хотите сделать.

Мое предложение, наиболее красноречивое решение - это перенаправление или обновление ajax. Общайтесь со своими пользователями, заменив форму сообщением «Ваш запрос отправлен. Спасибо». Это не позволит им спамить кнопку отправки.

Вы могли бы сделать что-то с сеансом, как посоветовал Магнус. Не забудьте указать временную метку, чтобы ее можно было удалить через некоторое время.

person Pettis Brandon    schedule 21.08.2019