【问题标题】:Post Redirect Get - how is POST never ever ever resubmitted?Post Redirect Get - POST 如何永远不会重新提交?
【发布时间】:2012-07-07 21:32:53
【问题描述】:

这里有很多关于 Post Redirect Get 模式的有趣文章,例如:http://www.theserverside.com/news/1365146/Redirect-After-Post

但这里有一个简单的问题......

如果用户执行 POST 并被重定向到 GET。很好,如果他们点击刷新浏览器只是发送 GET,很容易理解。但是如果在 GET 之后点击 BACK 按钮然后点击刷新,他们肯定可以再次点击 POST 吗?是吗?

我想了解我们如何能 100% 确定 POST 永远不会被重新提交?

【问题讨论】:

  • 从一些研究中值得指出的一点是,返回 302、303 的请求通常不会进入浏览器历史记录。这意味着当按下返回时,浏览不会返回到 POST 请求,而是返回到它之前的请求。

标签: http http-post http-get


【解决方案1】:

确保不重新提交 POST 的一种方法是使用与该发布会话关联的唯一标识符,例如,如果它是购物车,则在他们开始结账时,为该进程生成一个唯一 ID。结帐完成后(例如已发送 POST),从可使用的 ID 中删除该 ID。

您也可以通过为表单生成一个唯一键来实现此目的,如果表单已提交,请从存储它的位置删除该键。

<input type="hidden" name="key" value="<?php echo generateUniqueKey(); ?>" />

其中 generateUniqueKey() 函数将查询一个表并插入一个唯一 ID,然后返回该 ID。在您处理表单的页面上,执行以下操作:

<?php 
    $key = $_POST['key'];
    if (isKeyStillValid ($key)) {
        markKeyAsInvalid ($key);
        // Process form ...
    }
    else {
        die ("You have already submitted this form".);
    }
?>

isKeyStillValid() 函数将检查数据库以确保与表单一起使用的键仍然是可用的键,而 markKeyAsInvalid() 函数将从数据库中删除该键。

更新: 这是我刚刚制作的一个示例,其中包含我之前描述的内容。这是一个非常简单的例子,只是简单地使用了一个 SQL 表中的自增 ID 作为 key,但作为一个例子应该足够了。实际上,你会想要比这更深思熟虑的东西。 http://alexloney.com/post/

【讨论】:

  • 谢谢。当我第一次到达该页面时,会生成一个隐藏密钥。当我“返回”到该页面时,为什么没有生成另一个隐藏密钥?
  • 之所以有效,是因为在请求页面时,它会调用服务器端 PHP 脚本来生成密钥。但是,当您“返回”时,您的网络浏览器只会加载页面的缓存版本,而不是重新请求页面。由于它加载了保存的版本,它不会再次请求页面,因此它不会生成新的密钥。
  • 有道理,但您不应该缓存此类页面吗?
  • 这取决于您希望它如何运行。如果您想强制页面不缓存,那么您将需要另一种方法来跟踪表单是否未被验证​​,例如将标识符存储在 cookie 中,通知您表单已经提交。或者,您可以将表单 ID 与用户 ID(如果他们必须登录才能提交表单)一起存储在一个表中,以判断他们是否已经提交了表单。但是,如果您在用户使用“后退”按钮时强制页面重新加载,它可能会清除表单内容。
  • 如果您使用 PHP,在页面顶部添加这两行应该会强制在用户访问页面时重新验证页面(如果您使用其他语言,我当然也有一种方法可以发送标头)header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
【解决方案2】:

但是如果在 GET 之后点击 BACK 按钮然后点击刷新,他们肯定可以再次点击 POST 吗?是吗?

是的。

当用户使用后退按钮时,可能会发生这种情况 - 模式并不能防止这种情况发生,只是防止结果出现在与原始表单相同的 页面中,其中刷新(F5) 会导致转发。

我们如何能 100% 确定 POST 永远不会被重新提交?

一种方法是根据过去 X 分钟内提交的所有值检查发布的值,丢弃重复项(有丢失故意重复项的风险)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-11
    相关资源
    最近更新 更多