代码之家  ›  专栏  ›  技术社区  ›  Emanuil Rusev

防止表单重新提交

  •  101
  • Emanuil Rusev  · 技术社区  · 15 年前

    第一页包含一个HTML表单。第二页-处理提交数据的代码。

    第一页的表格被提交。浏览器被重定向到第二页。第二页处理提交的数据。

    此时,如果刷新第二页,将弹出“确认表单重新提交”警报。

    这能防止吗?

    10 回复  |  直到 13 年前
        1
  •  144
  •   CodeTwice    15 年前

    这里人们通常采用两种方法:

    方法1: 使用AJAX+重定向

    通过这种方式,您可以使用JQuery或类似于Page2的东西在后台发布表单,而用户仍然可以看到page1显示出来。发布成功后,将浏览器重定向到第2页。

    方法2: 发布+重定向到self

    这是论坛上常见的技巧。第1页的表单将数据发布到第2页,第2页处理数据并执行需要执行的操作,然后它自己执行HTTP重定向。这样,浏览器记住的最后一个“操作”是一个简单的GET on page2,因此表单不会在F5时重新提交。

        2
  •  23
  •   Eugen Konkov    8 年前

    你刚刚执行了PRG的P。你需要 重定向 . (现在你根本不需要重定向。见 this )

    PRG是一种web开发设计模式,可以防止一些重复的表单提交,也就是说,提交表单(Post Request 1)->重定向->获取(Request 2)

    Under the hood
    

    重定向状态代码 -使用HTTP 302的HTTP 1.0或使用HTTP 303的HTTP 1.1

    带有重定向状态代码的HTTP响应还将在location header字段中提供URL。用户代理(例如,web浏览器)受此代码的响应的邀请,对“位置”字段中指定的新URL进行第二次(否则相同)请求。

    重定向状态代码是为了确保在这种情况下,web用户的浏览器可以安全地刷新服务器响应,而不会导致重新提交初始HTTP POST请求。

    Double Submit Problem
    

    Double Submit Problem

    Post/Redirect/Get Solution
    

    Post/Redirect/Get Solution

    Source

        3
  •  10
  •   Community Mohan Dere    9 年前

    直接说,你不能,这是件好事。浏览器的警报是有原因的。这条线应该回答你的问题:

    Prevent Back button from showing POST confirmation alert

    建议的两个关键解决方案是PRG模式,以及AJAX提交和脚本重新定位。

        4
  •  8
  •   Blrfl    15 年前

    要100%确保同一表单不会被提交两次,唯一的方法是在您发出的每个表单中嵌入一个唯一的标识符,并跟踪哪些表单已经在服务器上提交。这里的陷阱是,如果用户备份到表单所在的页面并输入新数据,同一个表单将不起作用。

        5
  •  6
  •   iwein    15 年前

    1. 确保重复的帖子不会干扰服务器端的数据。为此,请在post中嵌入唯一标识符,以便可以拒绝服务器端的后续请求。这种模式叫做 等幂接收机

    2. 确保用户不被两人提交重复的可能性所困扰

      • 在POST之后重定向到GET(POST redirect GET模式)
      • 使用javascript禁用按钮

    你2岁以下什么都不做。将完全防止重复提交。人们可以很快点击,黑客也可以发帖。你总是需要1。如果你想确定没有复制品。

        6
  •  2
  •   Joel    15 年前

        7
  •  2
  •   Highlight    9 年前

    我发现没人提起这个把戏。

    如果没有重定向,您仍然可以在刷新时阻止表单确认。

    默认情况下,表单代码如下:

    <form method="post" action="test.php">

    现在,改成 <form method="post" action="test.php?nonsense=1">

    你会看到魔法的。

    我想这是因为如果浏览器在url中获得GET方法(查询字符串),它不会触发确认警报弹出窗口。

        8
  •  1
  •   Rohan Rao    6 年前

    <script>
       $(document).ready(function(){
       window.history.replaceState('','',window.location.href)
       });
    </script>
    

    这是防止由于回发而在提交后再次提交数据的最优雅的方法。

    希望这有帮助。

        9
  •  0
  •   ehe888    10 年前

    PRG模式只能防止页面刷新导致的重新提交。这不是百分之百的安全措施。

    通常,我会采取以下措施防止重新提交:

    1. 客户端-使用javascript来防止重复单击将触发表单提交的按钮。你只需在第一次点击后禁用按钮。

    2. 服务器端-我将计算提交参数的哈希值,并将该哈希值保存在会话或数据库中,因此当收到重复的提交时,我们可以检测重复,然后正确响应客户端。但是,您可以设法在客户端生成散列。

    在大多数情况下,这些措施有助于防止再次提交。

        10
  •  0
  •   Scott C Wilson Joachim Kiørbye Bertelsen    9 年前

    我真的很喜欢“安吉林的回答”。但是如果你处理的是一些不实用的遗留代码,这种技术可能对你有用。

    在文件的顶部

    // Protect against resubmits
    if (empty($_POST))  {
       $_POST['last_pos_sub'] = time();
    } else {
         if (isset($_POST['last_pos_sub'])){
            if ($_POST['last_pos_sub'] == $_SESSION['curr_pos_sub']) {
               redirect back to the file so POST data is not preserved
            }
            $_SESSION['curr_pos_sub'] = $_POST['last_pos_sub'];
         }
    }
    

    然后在表格的最后,坚持 last_pos_sub 具体如下:

    <input type="hidden" name="last_pos_sub" value=<?php echo $_POST['last_pos_sub']; ?>>
    
        11
  •  0
  •   Rômulo Z. C. Cunha    8 年前

    试试崔丝:

    function prevent_multi_submit($excl = "validator") {
        $string = "";
        foreach ($_POST as $key => $val) {
        // this test is to exclude a single variable, f.e. a captcha value
        if ($key != $excl) {
            $string .= $key . $val;
        }
        }
        if (isset($_SESSION['last'])) {
        if ($_SESSION['last'] === md5($string)) {
            return false;
        } else {
            $_SESSION['last'] = md5($string);
            return true;
        }
        } else {
        $_SESSION['last'] = md5($string);
        return true;
        }
    }
    

    if (isset($_POST)) {
        if ($_POST['field'] != "") { // place here the form validation and other controls
        if (prevent_multi_submit()) { // use the function before you call the database or etc
            mysql_query("INSERT INTO table..."); // or send a mail like...
            mail($mailto, $sub, $body); // etc
        } else {
            echo "The form is already processed";
        }
        } else {
        // your error about invalid fields
        }
    }
    

    字体: https://www.tutdepot.com/prevent-multiple-form-submission/

        12
  •  0
  •   Tran Anh Hien    7 年前

    使用js防止添加数据:

    if ( window.history.replaceState ) {
        window.history.replaceState( null, null, window.location.href );
    }
    
    推荐文章