Библиотека для предотвращения дубликата формируются, представления существуют для django?

Я пытаюсь найти способ предотвратить пользователей от двойного представления мои формы. У меня есть 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 отправленных аргументов
  • ответ # соленые данные
  • created_at # используемый для развертки этой таблицы
  • lock_expired # булевская переменная, имеющая значение, истекла ли блокировка

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

18
задан Danra 31 October 2016 в 15:59
поделиться

5 ответов

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

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

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

6
ответ дан 30 November 2019 в 08:27
поделиться

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

4
ответ дан 30 November 2019 в 08:27
поделиться

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

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 сеанса) Пользователь не может заново сохранить данные, которыми истекает сеанс, кстати. Я предполагаю, что существует что-то, кто идентифицирует пользователя, который отправляет данные

11
ответ дан 30 November 2019 в 08:27
поделиться

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

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

2
ответ дан 30 November 2019 в 08:27
поделиться

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

Вы можете попробовать реализовать что-то, что используется в django-поршне для объектов 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/') 
3
ответ дан 30 November 2019 в 08:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: