【问题标题】:How do I stop the Back and Refresh buttons from resubmitting my form?如何阻止“返回”和“刷新”按钮重新提交我的表单?
【发布时间】:2009-03-20 09:01:29
【问题描述】:

我正在做网络开发。

我有一个关于信用卡的页面,当用户点击“刷新”或“返回”时,交易会再执行一次,这是不需要的。

这包括浏览器左上角的“返回”和“刷新”按钮,“右键单击->刷新/返回”,按“F5”键。 这只能在某些 cgi 页面上完成,而不是全部。

这可以使用 Javascript 来完成吗?还是其他方法?

【问题讨论】:

    标签: javascript browser double-submit-prevention


    【解决方案1】:

    standard way 分三步完成。

    1. 表单页面提交字段到处理页面
    2. 处理页面处理数据并重定向到结果页面
    3. 结果页面只显示结果,重新加载不会造成任何损害。

    【讨论】:

    • 也称为 Post-Redirect-Get 模式。
    • 如果用户点击“返回”(如果他们告诉浏览器重新提交),这不会阻止重新处理表单
    • @philfreo- 实际上,它确实阻止了它。今天的大多数框架都会发出“302 Moved”标题,它有效地告诉浏览器在返回按钮导航期间使用结果页面作为历史记录。
    • 在单页应用程序中,有人发布到您的应用程序的地方怎么样?
    • @jamiebarrow:在 SPA 中,您会使用 AJAX 调用来提交表单。
    【解决方案2】:

    这打破了基本的浏览器用户体验模型...用户应该始终能够在其浏览器中使用刷新和返回按钮。建议您以其他方式修复页面。

    如果您更新您的问题以包含您正在使用的服务器语言/平台/技术,那么有人可能会提出解决方案。

    【讨论】:

      【解决方案3】:

      重新提交表单会产生重复交易这一简单事实令人担忧。您应该进行某种检查以确保每次提交的表单数据都是唯一的。

      例如,应该为提交表单的页面指定一个唯一的 ID,该 ID 与表单一起提交。然后业务逻辑应该能够识别出提交的表单已经被处理(因为(不再)唯一 ID 将是相同的),因此忽略第二次尝试。

      “标准方式”仍然不会阻止客户点击两次后退按钮......甚至如果他们认为(无论出于何种原因)它没有被处理,甚至返回并重新提交表单。

      【讨论】:

        【解决方案4】:
        1. 生成随机字符串并存储在会话中,

        2. 然后将其作为隐藏值输出到您的表单中,

        3. 检查提交和存储变量,如果匹配处理您的请求,

        4. 转到 1。

        【讨论】:

        • “存储价值”是什么意思?
        【解决方案5】:

        将此代码放在表单页面上

        Response.Cache.SetCacheability(HttpCacheability.NoCache);
        
        Response.Cache.SetExpires(DateTime.Now-new TimeSpan(1,0,0));
        
        Response.Cache.SetLastModified(DateTime.Now);
        
        Response.Cache.SetAllowResponseInBrowserHistory(false);
        

        【讨论】:

        • 这段代码应该做什么?当用户点击返回按钮时页面过期?
        • +1 这是 C# 代码,如果用户尝试在浏览器上单击“返回”,浏览器会发出“页面已过期”警告
        【解决方案6】:

        您不应尝试“阻止”这些操作。 您应该做的是确保当有人“双重提交”表单时不会发生任何事情。

        【讨论】:

          【解决方案7】:

          在某些浏览器中你甚至不能这样做,这很好!

          【讨论】:

            【解决方案8】:

            最好的方法是有足够的会话处理逻辑,您可以将第二次(及以后)尝试识别为“这只是重新提交”并忽略它。

            【讨论】:

              【解决方案9】:

              我没在这里看到,所以在这里。

              1. 在表单中放置一个唯一的令牌。
              2. 提交按钮触发向服务器发送 xmlhttp(ajax) 请求,以创建一个以令牌命名的会话变量,其存储值为 1。
              3. ajax 请求在收到肯定的状态更改后提交表单。
              4. 表单处理脚本检查存储值为 1 的会话变量。
              5. 脚本删除会话变量并处理表单。

              如果未找到会话变量,则不会处理表单。由于一旦发现变量就会被删除,因此只能通过按下提交按钮来运行表单。刷新和返回不会提交表单。这将在不使用重定向的情况下工作。

              【讨论】:

                【解决方案10】:

                vartec:s 解决方案解决了重新加载问题,而不是返回问题,所以这里有一个解决方案:

                1. 表单页面设置会话变量,例如 session("fromformpage")=1
                2. 处理页面检查会话变量,如果它为“1”,则处理数据并重定向到结果页面,如果不是“1”,则直接重定向到结果页面。
                3. 结果页面将会话变量设置为“”。

                那么如果用户按下返回按钮,处理页面将不再进行处理,只会重定向到处理页面。

                【讨论】:

                • 后退按钮无论如何都不会带您进入处理页面。它会直接带你进入表单页面。
                • 不过,这是一个必须解决的问题。
                【解决方案11】:

                我发现上面的 Post/Redirect/Get 解释有点模棱两可

                这是我所遵循的,希望它对将来的人有所帮助

                http://wordsideasandthings.blogspot.ca/2013/04/post-redirect-get-pattern-in-php.html

                基本上基于上述方案的流程是:

                1. 从 FORM 页面提交到处理页面(或自身)
                2. 处理数据库或支付处理等
                3. 如果需要,将用户反馈消息、可能的错误消息等存储在会话变量中
                4. 将标题重定向到结果页面(或原始表单页面)。 如果需要,从处理页面显示自定义消息。例如“错误信用卡付款被拒绝”,并重置会话变量。

                重定向类似:

                header("HTTP/1.1 303 See Other");
                header("Location: http://$_SERVER[HTTP_HOST]/yourfilehere.php");
                die();
                

                标头重定向将在“yourfilehere.php”上发起GET 请求,因为重定向只是从服务器获取数据的“请求”,而不是向服务器提交数据的POST。因此,redirect/GET 可防止在刷新后发生任何进一步的 DB/支付处理。 301 错误状态将有助于按下返回按钮。

                有用的阅读:

                1. http://en.wikipedia.org/wiki/URL_redirection#HTTP_status_codes_3xx
                2. http://www.theserverside.com/news/1365146/Redirect-After-Post
                3. http://wordsideasandthings.blogspot.ca/2013/04/post-redirect-get-pattern-in-php.html
                4. https://en.wikipedia.org/wiki/HTTP#Request_methods
                5. http://en.wikipedia.org/wiki/Post/Redirect/Get

                【讨论】:

                  【解决方案12】:

                  只需将这个javascript放在头部分上方的aspx页面的html部分

                  <script type = "text/javascript" >
                  function disableBackButton()
                  {
                  window.history.forward();
                  }
                  setTimeout("disableBackButton()", 0);
                  </script>
                  

                  我们需要把它放在我们想要阻止用户通过点击后退按钮访问的页面的html部分

                  页面的完整代码如下所示

                  <%@ Page Language="C#" AutoEventWireup="true"
                  CodeFile="Default.aspx.cs" Inherits="_Default" %>
                  
                  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                  
                  <html xmlns="http://www.w3.org/1999/xhtml" >
                  <head runat="server">
                  <title>Untitled Page</title>
                  <script type = "text/javascript" >
                  function disableBackButton()
                  {
                  window.history.forward();
                  }
                  setTimeout("disableBackButton()", 0);
                  </script>
                  </head>
                  <body onload="disableBackButton()">
                  <form id="form1" runat="server">
                  <div>
                  This is First page <br />
                  <br />
                  Go to Second page
                  <br />
                  <br />
                  <asp:LinkButton ID="LinkButton1" runat="server"
                  PostBackUrl="~/Default2.aspx">Go to Second Page
                  </asp:LinkButton></div>
                  </form>
                  </body>
                  </html>
                  

                  如果您使用的是 firefox,请使用而不是 onload

                  如果你想使用 aspx 页面后面的代码禁用后退按钮,那么你需要编写下面提到的代码 后面的 C# 代码

                  protected override void OnPreRender(EventArgs e)
                  {
                  base.OnPreRender(e);
                  string strDisAbleBackButton;
                  strDisAbleBackButton = "<script language="javascript">\n";
                  strDisAbleBackButton += "window.history.forward(1);\n";
                  strDisAbleBackButton += "\n</script>";
                  ClientScript.RegisterClientScriptBlock(this.Page.GetType(), "clientScript", strDisAbleBackButton);
                  } 
                  

                  我们也可以通过禁用浏览器缓存或通过在 Page_load 事件或 Page_Init 事件中编写这行代码来实现这一点

                  protected void Page_Init(object Sender, EventArgs e)
                  {
                  Response.Cache.SetCacheability(HttpCacheability.NoCache);
                  Response.Cache.SetExpires(DateTime.Now.AddSeconds(-1));
                  Response.Cache.SetNoStore();
                  }
                  

                  这样做,用户在点击浏览器的返回按钮时会得到页面已过期的消息

                  演示是:

                  【讨论】:

                    【解决方案13】:

                    此代码适用于不从当前页面返回我..

                    在这里我放了一个代码来帮助你,不打开上下文菜单,在浏览器重新加载时询问你是否离开页面......

                    我正在尝试点击浏览器后退按钮的询问

                    jQuery( document ).ready(function() {
                    
                        document.onkeydown = fkey;
                        document.onkeypress = fkey
                        document.onkeyup = fkey;
                    
                        var wasPressed = false;
                    
                        function fkey(e){
                            e = e || window.event;
                            //alert(e.keyCode);
                            if( wasPressed ) return; 
                    
                    
                            if (e.keyCode == 116 || e.keyCode == 8 || e.keyCode == 17) {
                                         // alert("f5 pressed");
                                          window.onbeforeunload = null;
                                          return true;
                                     }
                    
                        }
                    window.onbeforeunload = function (event) {
                        var message = ''; // Type message here
                    
                        if (typeof event == 'undefined') {
                            event = window.event;
                        }
                        if (event) {
                            event.returnValue = message;
                        }
                    
                        return message;
                    };
                    
                    jQuery(function () {
                    
                        jQuery("a").click(function () {
                            window.onbeforeunload = null;
                        });
                    
                        jQuery(".btn").click(function () {
                            window.onbeforeunload = null;
                        });
                    
                        //Disable part of page
                        $(document).on("contextmenu",function(e){
                            return false;
                        });
                    });});
                    

                    谢谢,

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2018-02-21
                      • 2011-10-15
                      • 2011-12-06
                      • 1970-01-01
                      • 2013-02-20
                      • 2015-12-30
                      • 2019-12-09
                      • 2013-12-31
                      相关资源
                      最近更新 更多