如何防止“确认表单重新提交”对话框?

IT技术 php javascript jquery codeigniter
2021-01-27 20:33:10

提交后如何清理表单中的信息,以便在页面刷新后不显示此错误?

见图片(来自铬):

对话框有文字:

您要查找的页面使用
了您输入的信息。返回该
页面可能会导致
重复您执行的任何操作你要继续吗?

我不希望这个对话框出现。

6个回答

编辑:自从我最初发布这个答案已经有几年了,尽管我得到了一些赞成,但我对之前的答案并不满意,所以我已经完全重做了。我希望这有帮助。


何时使用GETPOST

一个办法摆脱这种错误消息的是让你的形式使用GET,而不是POST请记住,这并不总是合适的解决方案(请阅读下文)。

如果您正在执行不想重复的操作,如果正在传输敏感信息,或者如果您的表单包含文件上传或发送的所有数据的长度超过~2000 个字符,请始终使用 POST

何时使用的示例POST包括:

  • 一个登录表单
  • 联系表格
  • 提交付款表格
  • 从数据库中添加、编辑或删除条目的东西
  • 一个图像上传器(注意,如果GET<input type="file">字段一起使用,则只会将文件名发送到服务器,这在 99.73% 的情况下不是您想要的。)
  • 包含多个字段的表单(如果使用 GET,则会创建一个长 URL)

在任何这些情况下,您都不希望人们刷新页面并重新发送数据。如果您要发送敏感信息,使用 GET 不仅不合适,而且会是一个安全问题(即使表单是由 AJAX 发送的),因为敏感项目(例如用户密码)是在 URL 中发送的,因此会显示出来在服务器访问日志中。

基本上可以将 GET用于其他任何事情。这意味着,当您不介意它是否重复时,对于您可以提供直接链接的任何内容,当没有传输敏感信息时,当您非常确定您的 URL 长度不会失控时,并且当您的表单没有任何文件上传时。

示例包括:

  • 在搜索引擎中执行搜索
  • 用于浏览网站的导航表单
  • 使用随机数或一次性密码(例如电子邮件中的“取消订阅”链接)执行一次性操作。

在这些情况下,POST 是完全不合适的。想象一下,如果搜索引擎使用 POST 进行搜索。每次刷新页面时,您都会收到此消息,并且您无法将结果 URL 复制并粘贴给人们,他们必须自己手动填写表单。

如果您使用POST

对我来说,在大多数情况下,即使弹出“确认表单重新提交”对话框也表明存在设计缺陷。由于POST被用来执行破坏性操作的本质,网页设计师应该防止用户因意外(或故意)刷新页面而多次执行这些操作。许多用户甚至不知道此对话框的含义,因此只需单击“继续”。如果那是在“提交付款”请求之后呢?付款会再次发送吗?

所以你会怎么做?幸运的是,我们有Post/Redirect/Get设计模式。用户向服务器提交 POST 请求,服务器将用户的浏览器重定向到另一个页面,然后使用 GET 检索该页面。

这是一个使用 PHP 的简单示例:

if(!empty($_POST['username'] && !empty($_POST['password'])) {
    $user = new User;
    $user->login($_POST['username'], $_POST['password']);

    if ($user->isLoggedIn()) {
        header("Location: /admin/welcome.php");
        exit;
    }
    else {
        header("Location: /login.php?invalid_login");
    }
}

注意在这个例子中,即使密码不正确,我仍然重定向回登录表单。要向用户显示无效的登录消息,只需执行以下操作:

if (isset($_GET['invalid_login'])) {
    echo "Your username and password combination is invalid";
}
如果使用 GET 并刷新,则不会出现错误,但会重新提交数据。不会推荐它。
2021-03-20 20:33:10
如果服务器端验证失败,您如何重定向回相同的表单,以便显示无效值和错误消息?假设表单有许多无法放入 cookie 的字段。另外,假设您不想要服务器端状态。
2021-03-23 20:33:10
很好的答案。它还强调了一个事实,即不改变服务器状态的表单提交应该使用“get”。
2021-04-05 20:33:10
@joshua 我不确定这是否会构成您的服务器端状态,但是您可以将值存储在会话中以用于一个附加请求(即在重定向之后),然后将其删除。以 Laravel 的flash()函数为例,了解如何实现这一点。如果这对您来说太有状态,请使用,LocalStorage因为大小限制比您可以放入 cookie 的大小要大几个数量级。
2021-04-07 20:33:10
除非人们重新提交数据无关紧要。
2021-04-11 20:33:10

这种方法对我很有效,我认为最简单的方法是在重新加载页面的 HTML 中使用这个 javascript 代码。

if ( window.history.replaceState ) {
  window.history.replaceState( null, null, window.location.href );
}

但问题是什么?
2021-03-29 20:33:10

它与您的形式或其中的值无关。它被浏览器触发,以防止用户对缓存数据重复相同的请求。如果您确实需要启用结果页面的刷新,您应该通过 PHP ( header('Location:result.php');) 或您正在使用的其他服务器端语言重定向用户元标记解决方案也应该可以禁用刷新时的重新发送。

对于重定向,在 CI 中,如果您加载 url helper,则可以redirect('somecontroller/somefunction');用作速记。有关成功消息,请阅读 flash session 部分的用户指南
2021-03-26 20:33:10
如何使用重定向,我显示消息“注册成功”?
2021-04-10 20:33:10

我遇到了这个问题并将这个 JavaScript 添加到我的页面底部,它似乎工作。解决方案似乎要简单得多。有什么缺点吗?

<script>
if ( window.history.replaceState ) {
  window.history.replaceState( null, null, window.location.href );
}
</script>
它与我完美配合。我希望没有缺点。
2021-03-25 20:33:10

处理 POST 页面后,将用户重定向到同一页面。

http://test.com/test.php

header('Location: http://test.com/test.php');

这将摆脱该框,因为刷新页面不会重新提交数据。

这不是以无限循环的重定向结束吗?
2021-03-20 20:33:10
这需要另一个检查,如 if($request present) {redirect} 否则它将结束重定向的无限循环......
2021-04-02 20:33:10
@MatthewOakley 确实如此。即使有出口;
2021-04-08 20:33:10
这种方法的小警告是页面随后在浏览器历史记录中出现两次。
2021-04-10 20:33:10