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

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

我认为的可能性是:

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

还有更多吗?

其中有一些具体的实现吗?

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

期待收到你们 MVC 人员的来信。

有帮助吗?

解决方案

人们常常忽略处理这个问题的最传统方法,即使用 随机数键.

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

我喜欢 Javascript 解决方案,因为它有效 最多 的时间。

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

随机数密钥还有一个额外的优点,即它通过防止 重放攻击 (中间的人嗅探您的 HTTP 请求,然后将其重播到服务器,服务器将其视为合法)。

其他提示

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

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

您可能想看看 重定向后获取 (PRG)模式:

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

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

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

博客文章在这里

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