在ASP.NET MVC中防止表单双重发布有哪些可能的方法?

Jak*_*urc 3 html javascript asp.net-mvc

在我的ASP.NET MVC应用程序的日志检查期间,我发现一些用户设法两次发布相同的表单.我试图重现它,但我失败了.无论如何,我想阻止用户两次发布相同的数据.在ASP.NET MVC中是否有任何规范的解决方案,或者我必须开发自己的自定义解决方案?

我的自定义解决方案我可以想象客户端和服务器端解决方案.在这两种情况下你能推荐我吗?

小智 8

通常的方法是在单击后立即禁用提交按钮.

使用jQuery这样的东西应该工作:

<script type="text/javascript">
    $("#myform").submit(function()
        { $("#submit-button").attr("disabled", "disabled"); });
</script>
Run Code Online (Sandbox Code Playgroud)

现在仔细阅读你的问题,看到你使用ASP.NET MVC ....

双帖可能是由于用户在发布后刷新页面而引起的.如果您只是从帖子操作中返回一个视图:

[AcceptVerbs (HttpVerbs.Pos)]
ActionResult ProcessUserPost ()
{
    /*...*/

    return View ();
}
Run Code Online (Sandbox Code Playgroud)

然后,浏览器将尝试通过执行相同的步骤来重新创建页面,这意味着再次提交记住的表单.有些浏览器会显示一条警告信息(FireFox),其他浏览器会静静地显示(看Opera).为了避免这种情况,您需要确保用户获取的页面是GET请求而不是POST的结果.

基本上,您需要执行重定向而不是返回视图.这将指示浏览器再次获取页面.

[AcceptVerbs (HttpVerbs.Pos)]
ActionResult ProcessUserPost ()
{
    /*...*/

    return RedirectToAction ("DisplayTheForm");
}
Run Code Online (Sandbox Code Playgroud)

这样刷新页面不会导致发送新的POST请求.

当然,这不会阻止用户单击后退按钮返回到表单页面再次提交.但是应该在您的业务逻辑中处理这种情况,检查同一用户对您正在执行的任何操作的同一订单的双重提交.


tva*_*son 5

我可以想到三种方法来处理这个问题.

  1. 有一个双重职位是非破坏性的.也就是说,在可能的情况下,使重新发布只是以使其仍然有效的方式刷新数据.对于创建某些内容的帖子(例如信用卡交易),这实际上是不可能的,但是当您基本上设置新属性时,应该足以满足更新方法.
  2. 使用仅适用于一个操作的一次性随机数防止双重帖子.在您跟踪的页面上包含隐藏的随机数,并在看到第一个帖子后标记为已使用.检查此nonce以确保它之前未使用过,如果有,则显示错误消息而不是执行操作.
  3. 通过检查发布数据的唯一性约束来防止破坏性操作.这实际上是(2)的一个变体,因为你的nonce基本上是实际数据中的一些唯一值.这适用于某些创建方案,即,您无法使用相同的电子邮件地址创建重复的用户,但在数据中没有唯一字段时会失败.后者的示例可以是购买交易,其中用户可以多次购买相同的商品.