Решение проблемы двойного представления
Я хотел бы видеть, как веб-разработчики избегают проблемы с двойной отправкой. Поэтому в основном мое понимание проблемы заключается в следующем:
Двойная передача происходит, когда нетерпеливый пользователь несколько раз представляет форму, вызывая проблемы. Эта проблема может быть исправлена JavaScript (в частности, сценарии jQuery), которые отключают кнопку отправки после отправки формы - слабость этого заключается в том, что у клиентов отключен JavaScript.
Существуют также методы обнаружения на стороне сервера.
Итак, мои вопросы:
Как люди преодолевают двойное подчинение?
Каков пример реальной жизни проблемы, вызванной двойными представлениями?
Настраиваются ли в каких-либо веб-приложениях два встроенных инструмента представления?
Ответы
Ответ 1
Если вы работаете со сценариями на стороне сервера Java, а также с помощью struts 2, вы ссылаетесь на эту ссылку, которая говорит об использовании токена.
http://www.xinotes.org/notes/note/369/
Маркер должен быть сгенерирован и сохранен в сеансе для первоначальной рендеринга страницы, когда запрос отправляется вместе с токеном в первый раз, в действии struts запускается поток с именем потока в качестве идентификатора маркера и выполняется логика клиент запросил, когда клиент снова отправит один и тот же запрос, проверьте, продолжает ли поток (thread.getcurrentthread() прерывается), если он еще запущен, а затем отправьте перенаправление клиента 503.
Посмотрите на ExecuteAndWaitInterceptor struts 2code, логика этого в сочетании с токеном поможет быстро щелкнуть
Ответ 2
Реальная ситуация: размещение ставок на веб-сайте ставок. Пользователи дважды кликнут и сделают две ставки. Нехорошо! Проверка Javascript была недостаточной для предотвращения этого.
Решение:
-
Создать UUID/GUID скрытый ввод в форме с использованием серверного языка сценариев, который отображает форму.
-
При отправке формы немедленно добавьте это в таблицу базы данных, называемую UniqueSubmissions
(например). Затем продолжайте обработку.
-
Каждый последующий запрос с тем же UUID/GUID будет отклонен, если он найден в таблице UniqueSubmissions
.
Это сработало для нас. Надеюсь, что поможет ответить на ваш вопрос!
Ответ 3
Используйте redirect-after-post или иногда называемый PRG (post/redirect/получить)
Короче говоря, когда пользователь отправляет форму, вы выполняете переадресацию на стороне клиента (после употребления почтовых данных) на страницу ответа (успеха).
Ответ 4
Реальный пример жизни - это ответ, который будет опубликован дважды;-).
Если вы не хотите полагаться на какой-либо аспект клиентской стороны (javascript или даже куки), вы можете рассчитать хеш MD5 данных, возможно, путем добавления информации, такой как исходный IP-адрес и используемый браузер, и отклонить сообщения которые имеют одинаковый хэш.
Ответ 5
Структура web2py имеет встроенную защиту против представления двойной формы. Он хранит одноразовый токен в сеансе, а также в скрытом поле в форме, и они должны соответствовать при отправке или представление отклонено. Этот метод также защищает от CSRF (подделка с использованием межсайтового запроса).
Ответ 6
Если форма имеет намерение предоставить интерфейс для сохранения некоторых данных в dbms сервера, вы можете использовать специальное поле для проверки, которое является обязательным для представленных данных. Проверьте, соответствует ли представленная версия совпадению с последней версией данных в базе данных (или информацией о новом фрагменте данных), может предоставить вам хороший контроль над тем, что делать, если сделано несколько подарок в последовательности.
Ответ 7
Используя инфраструктуру web-приложений struts, мы можем решить эту проблему следующим образом:
У Struts есть 3 метода для token, saveToken(), isTokenValid() and resetToken()
.
saveToken()
- сгенерировать ключ маркера и сохранить атрибут request/session.
isTokenValid()
- проверять поданный ключ токена на 1 хранилище в запросе/сеансе.
resetToken()
- reset ключ токена.
Как это работает:
1) При загрузке формы вызывает saveToken()
класс действия для создания и сохранения ключа маркера. Struts будет хранить сгенерированный ключ в запросе/сеансе. Если токен успешно создан, когда источник просмотра в браузере вы увидите что-то похожее на следующее, ключ токена сохраняется как скрытое поле:
<form action="myaction.do" method="post">
<input type="hidden"
name="<%= Constants.TOKEN_KEY %>"
value="<%= session.getAttribute(Action.TRANSACTION_TOKEN_KEY) %>" >
2) После отправки формы вызывает isTokenValid()
в классе действий, он будет проверять переданный ключ токена (скрытое поле) с ключом маркера, сохраненным ранее на запрос/сеанс. Если совпадение, оно вернет true.
public final ActionForward perform(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
saveToken(request);
if (!tokenIsValid(request)) {
//forward to error page saying "your transaction is already being processed"
} else {
//process action
//forward to jsp
}
// Reset token after transaction success.
resetToken(request);
}
ссылка