Существует ли библиотека для предотвращения дублирования представлений форм для django? - PullRequest
18 голосов
/ 26 января 2010

Я пытаюсь найти способ запретить пользователям двойную отправку моих форм. У меня есть JavaScript, который отключает кнопку отправки, но есть случайный пользователь, который находит способ для двойной отправки.

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

В моей идеальной библиотеке блок кода будет выглядеть примерно так:

try:
    with acquire_lock({'field1':'abc', 'field2':'def'}) as lock:
        response = #do some credit card processing
        lock.response = response
except SubmissionWasDuplicate, e:
    response = e.response

Таблица блокировки будет выглядеть примерно так:

duplicate_submission_locks

  • submission_hash # MD5 представленных аргументов
  • ответ # маринованные данные
  • create_at # используется для очистки этой таблицы
  • lock_expired # логическое значение, если срок действия блокировки истек

Кто-нибудь знает, существует ли это уже? Его не сложно написать, поэтому, если он не существует, я могу написать сам.

Ответы [ 5 ]

11 голосов
/ 28 января 2010

Вы можете использовать сеанс для хранения хеша

import hashlib

def contact(request):
    if request.method == 'POST':
        form = MyForm(request.POST)
        #join all the fields in one string
        hashstring=hashlib.sha1(fieldsstring)
        if request.session.get('sesionform')!=hashstring:
            if form.is_valid() :                                         
                request.session['sesionform'] = hashstring
                #do some stuff...
                return HttpResponseRedirect('/thanks/') # Redirect after POST  
        else
           raise SubmissionWasDuplicate("duplicate")
    else:
        form = MyForm() 

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

6 голосов
/ 26 января 2010

Одним из простых решений этой проблемы является добавление уникального хэша в каждую форму. Тогда вы можете иметь подвижный стол текущих форм. Когда форма отправлена ​​или хэш слишком устарел, вы можете удалить его из таблицы и отклонить любую форму, для которой в таблице нет соответствующего хеша.

HTTPRedirect - правильный способ сделать это, как упоминалось ранее.

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

4 голосов
/ 26 января 2010

Честно говоря, ваша лучшая ставка (легкая и полезная практика) - выдать HTTPRedirect () на страницу благодарности, и если страница благодарности совпадает с формой, это нормально. Вы все еще можете сделать это.

3 голосов
/ 04 февраля 2010

Ответ Кристиана Дамиана - действительно отличное предложение. Я просто подумал о небольшом изменении этой темы, но у него может быть больше накладных расходов.

Вы можете попробовать реализовать что-то, что используется в django-pneon для BaseHandler объектов, - это метод с именем exists(), который проверяет, находится ли то, что вы отправляете, уже в базе данных.

Из handler.py (BaseHandler):

def exists(self, **kwargs):
    if not self.has_model():
        raise NotImplementedError

    try:
        self.model.objects.get(**kwargs)
        return True
    except self.model.DoesNotExist:
        return False

Итак, давайте сделаем так, чтобы функция называлась request_exists() вместо метода:

if form.is_valid()
    if request_exists(request):
        # gracefully reject dupe submission
    else:
        # do stuff to save the request
        ...
        # and ALWAYS redirect after a POST!!
        return HttpResponseRedirect('/thanks/') 
2 голосов
/ 27 января 2010

Всегда полезно использовать метод redirect-after-post. Это предотвращает случайную повторную отправку пользователем формы с помощью функции обновления из браузера. Это также полезно, даже когда вы используете метод хеширования. Это потому, что без перенаправления после POST, в случае нажатия кнопки Back / Refresh, пользователь увидит сообщение с вопросом о повторной отправке формы, что может ее запутать.

Если вы выполняете GET-перенаправление после каждого POST, то нажатие Back / Refresh не будет отображать это странное (для обычного пользователя) сообщение. Так что для полной защиты используйте Hash + redirect-after-post.

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