我想看看网络开发人员如何避免双重提交问题。因此,基本上我对问题的理解如下:

当不耐烦的用户多次提交表单时,会发生双重提交。此问题可以通过JavaScript(特别是JQuery脚本)解决,该问题一旦提交表单,就可以禁用提交按钮 - 如果客户端已禁用JavaScript,则可以解决此问题。

还有服务器端检测方法。

所以我的问题是:

人们如何克服双重提交?双重提交引起的问题的现实生活示例是什么?是否有任何Web应用程序框架都内置了双重提交工具?

有帮助吗?

解决方案

如果您正在使用Java服务器端脚本并使用Strut 2,则您将参考此链接,该链接在使用令牌上进行了讨论。

http://www.xinotes.org/notes/note/369/

应生成一个令牌并保存在初始页面渲染的会话中,当请求与令牌一起提交时,在Struts Action中,在struts Action中运行一个带有线程名称的线程作为令牌ID,并运行客户端的逻辑请求,当客户端再次提交相同的请求时,请检查线程是否仍在运行(thread.getCurrentThread()。中断)如果仍在运行,请发送客户端重定向503。

请查看Struts 2 Code的executeandwaitinterceptor,与令牌结合的逻辑将有助于快速单击

其他提示

现实生活状况:将赌注放在博彩网站上。用户将双击并获得两个下注。不好! JavaScript检查不足以防止这种情况。

解决方案:

  1. 创造 UUID/GUID 使用服务器端脚本语言以呈现形式的隐藏输入。

  2. 在表单上提交立即将其添加到名为的数据库表中 UniqueSubmissions (例如)。然后继续处理。

  3. 如果在 UniqueSubmissions 桌子。

这对我们有用。希望有助于回答您的问题!

使用 重定向序列 或有时被打电话 PRG(邮政/重定向/GET)

简而言之,当用户发布表单时,您会执行客户端重定向(在将帖子数据消耗后)到响应(成功)页面。

一个现实生活中的例子是这个答案两次;-)。如果您不想依靠客户端的任何方面(JavaScript甚至Cookie),则可以通过添加诸如源IP和使用的浏览器之类的信息来计算提交的数据的MD5哈希,并拒绝帖子具有相同的哈希。

web2py 框架有 内置保护 反对双表提交。它在会话中以及表格中的隐藏字段中存储一个单令牌,并且必须在提交时匹配或拒绝提交。此方法也是如此 防止CSRF (跨站点伪造)。

如果表格有意提供一个将某些数据保存在服务器dbms中的接口,则可以使用针对已提交数据的特殊修订字段。检查提交的修订是否匹配数据库中数据的最新版本(或是要插入的新数据)按顺序。

使用Struts Web申请框架,我们可以按以下方式处理此问题:

Struts有3种方法用于 token, saveToken(), isTokenValid() and resetToken().

saveToken() - 生成令牌密钥并保存到请求/会话属性。
isTokenValid() - 在请求/会话中验证针对1个商店提交的令牌密钥。
resetToken() - 重置令牌键。

这个怎么运作:
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);
}

参考

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top