Решение проблемы с двойной отправкой
-
11-10-2019 - |
Вопрос
Я хотел бы посмотреть, как веб-разработчики избегают проблемы двойной отправки.Итак, в основном мое понимание проблемы заключается в следующем:
Двойная отправка происходит, когда нетерпеливый пользователь отправляет форму несколько раз, что вызывает проблемы.Эта проблема может быть исправлена с помощью JavaScript (в частности, скриптов jQuery), которые отключают кнопку отправки после отправки формы - недостатком этого является то, что у клиентов отключен JavaScript.
Существуют также методы обнаружения на стороне сервера.
Итак, мои вопросы таковы:
Как люди преодолевают двойное подчинение?Каков реальный пример проблемы, вызванной двойными отправками?Есть ли в каких-либо фреймворках веб-приложений встроенные инструменты двойной отправки?
Решение
Если вы работаете со сценариями на стороне сервера Java, а также используете Struts 2, вы ссылаетесь на эту ссылку, о которой рассказывается об использовании токена.
http://www.xinotes.org/notes/note/369/
Токен должен быть сгенерирован и сохранен в сеансе для начального визуализации страницы, когда запрос будет представлен вместе с токеном в первый раз, в действии Struts Запустите поток с именем потока в качестве идентификатора токена и запустите логику, что бы ни имело клиент Запрашивается, когда клиент снова отправит один и тот же запрос, проверьте, работает ли поток (Thread.getCurrentThread (). Прекращено), если все еще запускается, отправьте клиент Redirect 503.
Пожалуйста, посмотрите на ExecutEandWaitInterceptor of Struts 2Code, логика этого в сочетании с токеном поможет быстро щелкнуть
Другие советы
Реальная жизненная ситуация: размещение ставок на веб -сайте ставок. Пользователи будут дважды щелкнуть и делать две ставки. Нехорошо! Проверки JavaScript были недостаточно, чтобы предотвратить это.
Решение:
Создавать Uuid/Гидо скрытый ввод в форме с использованием языка сценариев на стороне сервера, который отображает форму.
В подачу формы немедленно добавьте это в таблицу базы данных под названием
UniqueSubmissions
(Например). Затем приступите к обработке.Каждый последующий запрос с одним и тем же UUID/GUID будет отклонен, если найден в
UniqueSubmissions
стол.
Это сработало для нас. Надеюсь, это поможет ответить на ваш вопрос!
Использовать перенаправление-афтетер-пост или иногда вызывается PRG (post/redirect/get)
Короче говоря, когда пользователь публикует форму, вы выполняете перенаправление на стороне клиента (после потребления данных POST) на страницу ответа (успех).
Примером из реальной жизни был бы этот ответ, опубликованный дважды ;-).Если вы не хотите полагаться на какой-либо аспект клиентской части (javascript или даже файлы cookie), вы можете вычислить MD5-хэш отправленных данных, возможно, добавив такую информацию, как IP-адрес источника и используемый браузер, и отклонять сообщения с таким же хэшем.
А web2py Framework есть Встроенная защита против двойной формы подчинения. Он хранит одноразовый токен в сессии, а также в скрытом поле в форме, и они должны соответствовать отправке, или подача отклонена. Этот метод также защищает от CSRF (Поперечный запрос подделка).
Если в форме есть намерение предоставить интерфейс для сохранения некоторых данных в СУБД сервера, вы можете использовать специальное поле для пересмотра, которое является обязательным для отправленных данных. Проверка, соответствует ли представленная ревизия, которая была бы в последней версии данных в базе данных (или является новой частью вставки данных), может предоставить вам хороший контроль над тем, что делать, если сделано несколько подчитанных. в последовательности.
Используя структуру веб-применения стойки, мы можем решить эту проблему следующим образом:
Стойки имеют 3 метода, используемые для token, saveToken(), isTokenValid() and resetToken()
.
saveToken()
- Сгенерируйте ключ токена и сохраните атрибут запроса/сеанса.
isTokenValid()
- Validate представил ключ токена против 1 магазина в запросе/сеансе.
resetToken()
- Сбросьте ключ токена.
Как это работает:
1) При загрузке формы вызывает saveToken()
На классе действий, чтобы создать и хранить ключ токена. Спорты будут хранить сгенерированный ключ в запросе/сеансе. Если токен успешно создан, когда источник просмотра в браузере вы увидите что -то похожее на следующее, ключ токена сохраняется как скрытое поле:
<form action="myaction.do" method="post">
<input type="hidden"
name="<%= Constants.TOKEN_KEY %>"
value="<%= session.getAttribute(Action.TRANSACTION_TOKEN_KEY) %>" >
2) После подачи формы вызывает isTokenValid()
В классе действий он будет проверять представленный ключ токена (скрытое поле) с ключом токена, хранящейся ранее в запросе/сеансе. Если совпадать, это вернет истину.
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);
}