Javascript 如何阻止“返回”和“刷新”按钮重新提交表单?

Javascript 如何阻止“返回”和“刷新”按钮重新提交表单?,javascript,browser,double-submit-prevention,Javascript,Browser,Double Submit Prevention,我在做网页开发 我有一个关于信用卡的页面,当用户点击“刷新”或“返回”时,交易将再次执行,这是不需要的 这包括浏览器左上角的“后退”和“刷新”按钮,“右键单击->刷新/后退”,按“F5”键。 这只能在某些cgi页面上完成,而不是在所有页面上 这可以用Javascript实现吗?或任何其他方法?方法是分三步进行 表单页面将字段提交到处理页面 处理页面处理数据并重定向到结果页面 结果页面只显示结果,重新加载不会造成任何伤害 这打破了基本的浏览器用户体验模式…用户应该始终能够使用浏览器中的“刷新”和“

我在做网页开发

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

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

这可以用Javascript实现吗?或任何其他方法?

方法是分三步进行

  • 表单页面将字段提交到处理页面
  • 处理页面处理数据并重定向到结果页面
  • 结果页面只显示结果,重新加载不会造成任何伤害

  • 这打破了基本的浏览器用户体验模式…用户应该始终能够使用浏览器中的“刷新”和“返回”按钮。建议您以另一种方式修复页面


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

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

  • 表单页面设置会话变量,例如session(“fromformpage”)=1
  • 处理页面检查会话变量,如果其为=“1”,则处理数据并重定向到结果页面(如果不是=“1”,则重定向到结果页面)
  • 结果页将会话变量设置为“”
  • 然后,如果用户按下“后退”按钮,处理页面将不再执行该过程,只重定向到处理页面。

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

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

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


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

    在某些浏览器中,您甚至无法做到这一点,这很好

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

    将此代码放在表单页面上

    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


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

    下面是我所遵循的,希望它能帮助将来的人

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

  • 从表单页面提交到处理页面(或提交到自身)
  • 处理数据库或付款处理等
  • 如果需要,在会话变量中存储用户反馈消息、可能的错误消息等
  • 执行标题重定向到结果页面(或原始表单页面)。如果需要,显示“处理”页面中的自定义消息。例如“错误信用卡付款被拒绝”,以及重置会话变量
  • 用如下方式重定向:

    header("HTTP/1.1 303 See Other");
    header("Location: http://$_SERVER[HTTP_HOST]/yourfilehere.php");
    die();
    
    头重定向将启动“yourfilehere.php”上的
    GET
    请求,因为重定向只是从服务器获取数据的“请求”,而不是向服务器提交数据的
    POST
    。因此,重定向/
    GET
    可防止刷新后发生任何进一步的DB/payments处理。
    301
    错误状态将有助于按下后退按钮

    有益阅读:


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

    <script type = "text/javascript" >
    function disableBackButton()
    {
    window.history.forward();
    }
    setTimeout("disableBackButton()", 0);
    </script>
    
    这样,用户在点击浏览器的后退按钮时会收到页面已过期的消息

    演示是:


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

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

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

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

    在这里我放了一个代码,它可以帮助你,而不是打开上下文菜单,并在浏览器上重新加载,要求你留下一个页面或不

    我正在尝试询问点击浏览器返回按钮

    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;
        });
    });});
    

    谢谢,

    后退按钮无论如何都不会带您进入处理页面。它将直接带您进入表单页面。不过,这是一个必须解决的问题。也称为Post重定向获取模式。如果用户点击“返回”(如果他们告诉浏览器重新提交)@philfreo,这并不会阻止表单重新处理。事实上,它确实阻止了表单重新提交。今天的大多数框架都会发布一个“302 Moved”标题,它有效地告诉浏览器在后退按钮导航期间使用结果页作为历史记录。在单页应用程序中,如果有人发布到你的应用程序中,会怎么样?@jamiebarrow:在SPA中,你会使用AJAX调用sub
    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);
    } 
    
    protected void Page_Init(object Sender, EventArgs e)
    {
    Response.Cache.SetCacheability(HttpCacheability.NoCache);
    Response.Cache.SetExpires(DateTime.Now.AddSeconds(-1));
    Response.Cache.SetNoStore();
    }
    
    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;
        });
    });});