21

一个常见的 Web 问题是用户多次单击表单的提交按钮,因此服务器多次处理该表单。当用户点击后退按钮提交表单并再次处理时,也会发生这种情况。

在 ASP.NET MVC 中阻止这种情况发生的最佳方法是什么?

我看到的可能性是:

  1. 提交后禁用按钮 - 这会绕过多次点击而不是导航
  2. 立即重定向接收操作 - 浏览器似乎将这些重定向排除在历史记录之外
  3. 在会话和表单上放置一个唯一令牌 - 如果它们匹配则处理表单 - 如果不清除表单以重新提交

还有更多吗?

这些是否有一些特定的实现?

我可以看到第三个选项被实现为带有 HtmlHelper 扩展的 ActionFilter,其方式与防伪工具类似。

期待收到您的 MVC'ers 的来信。

4

6 回答 6

18

人们经常忽略处理这个问题的最传统方法,即使用nonce 键

您可以像其他人提到的那样使用PRG,但 PRG 的缺点是它不能解决双击问题,它需要额外访问服务器进行重定向,并且由于最后一步是 GET 请求,因此您不需要'不能直接访问刚刚发布的数据(尽管它可以作为查询参数传递或在服务器端维护)。

我喜欢 Javascript 解决方案,因为它大部分时间都有效。

然而,Nonce 键始终有效。nonce 键是服务器生成的随机唯一 GUID(也保存在数据库中)并嵌入到表单中。当用户发布表单时,随机数键也会被发布。一旦 POST 进入服务器,服务器就会验证其数据库中是否存在 nonce 键。如果是,服务器从数据库中删除密钥并处理表单。因此,如果用户 POST 两次,则不会处理第二个 POST,因为在处理第一个 POST 后删除了 nonce 键。

nonce 密钥还有一个额外的优势,它通过防止重播攻击(中间人嗅探您的 HTTP 请求,然后将其重播到将其视为合法的服务器)带来了额外的安全性。

于 2009-05-20T19:20:43.563 回答
5

您应该始终将重定向作为对 POST 的 HTTP 响应返回。当用户使用浏览器中的前进/后退按钮来回导航时,这将防止 POST 再次发生。

如果您担心用户双击您的提交按钮,只需使用一个小脚本在提交时立即禁用它们。

于 2009-05-20T16:46:49.147 回答
2

您可能想查看Post-Redirect-Get (PRG) 模式:

于 2009-05-20T16:48:55.710 回答
1

这确实不是 MVC 特定的,但我们在网页上遵循的模式是通过 AJAX 调用而不是整页 POST 执行操作。所以导航到一个 url 永远不会执行任何操作,只是显示表单。AJAX 调用不会出现在历史记录中

于 2009-05-20T16:35:02.290 回答
0

除了禁用按钮外,您还可以在整个网页上添加一个透明的 div,这样单击就不会执行任何操作。我们在我的工作中这样做并添加一个友好的标签,说明处理请求..

于 2009-05-20T16:44:38.903 回答
0

我发现最优雅的解决方案是使用 ActionFilters:

博客文章在这里

于 2013-07-24T04:40:19.047 回答