Я пытаюсь найти способ предотвратить пользователей от двойного представления мои формы. У меня есть 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
Кто-либо знает, существует ли это уже? Это, кажется, трудному не пишет, поэтому если это не существует, я могу записать это сам.
Одним из простых решений этой проблемы состоит в том, чтобы добавить уникальную хеш в каждую форму. Тогда вы можете иметь прокатный стол текущих форм. Когда форма представлена, или хеш становится слишком стар, вы можете истечь его из своего стола и отклонить любую форму, которая не имеет соответствующего хеша в вашем столе.
HTTPredirect - это правильный способ сделать это, как упоминалось ранее.
К сожалению, даже собственный администратор Django подвержен проблемам, связанным с этим вопросом. В некоторых случаях структура сценариев по перекрестным сайтам может помочь избежать некоторых из этого, но я боюсь, что текущие производственные версии просто не имеют этого встроенного.
Чтобы быть честным, ваша лучшая ставка (легкая и хорошая практика) - выдать httpredirect () на страницу Спасибо, и если страница Спасибо, что такая же, как форма, все нормально. Вы все еще можете сделать это.
Вы можете использовать сеанс для хранения хэшей
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 сеанса) Пользователь не может заново сохранить данные, которыми истекает сеанс, кстати. Я предполагаю, что существует что-то, кто идентифицирует пользователя, который отправляет данные
Всегда полезно использовать метод перенаправления за постом. Это не позволит пользователю случайно повторно отправить форму, используя функцию обновления из браузера. Это также полезно даже при использовании хэш-метода. Это связано с тем, что без перенаправления после POST, в случае нажатия кнопки Back/Refresh, пользователь увидит сообщение с вопросом о повторной отправке формы, которое может сбить ее с толку.
Если вы сделаете GET перенаправление после каждого POST, то нажатие кнопки Back/Refresh не отобразит это wierd (для обычного пользователя) сообщение. Поэтому для полной защиты используйте Hash+redirect-after-post.
Ответ Кристиана Дамиана - действительно отличное предложение. Я просто подумал о небольшом изменении этой темы, но, возможно, это будет связано с дополнительными накладными расходами.
Вы можете попробовать реализовать что-то, что используется в 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/')