为啥是 PRG 模式而不是其他模式?

Posted

技术标签:

【中文标题】为啥是 PRG 模式而不是其他模式?【英文标题】:Why PRG pattern rather than others?为什么是 PRG 模式而不是其他模式? 【发布时间】:2015-03-08 13:56:36 【问题描述】:

我需要防止为我客户的网站提交重复的表单。

我们需要一些来自用户的表单数据用于订单确认页面。 我们对 Web 服务器使用负载平衡。

方法一:发布/重定向/获取

(PRG 模式:http://en.wikipedia.org/wiki/Post/Redirect/Get)

一开始我尝试使用 PRG 模式。 在这种情况下,我认为我需要跨多个 Web 服务器处理会话(或 spring flashmap)。

方法 2:在客户端禁用刷新。

我的一位同事建议采用这种方法。

方法 3:发布/发布

另一位同事建议采用这种方法。

我认为方法 2、3 不是一个好的选择。 但我不知道这些方法的具体缺点或安全风险。 我试图谷歌,但我没有找到答案。

提前谢谢你。

[编辑]

我想更新利弊。

方法一:发布/重定向/获取

优点

安全!

缺点

如果您需要用户的一些表单数据在确认页面上显示,您需要使用session ,database 之类的。 如果您使用session,并且拥有多个服务器,则您必须做一些事情以使会话在多个服务器上可用。

方法 2:在客户端禁用刷新。

优点

缺点

如果您限制浏览器标准功能(例如刷新),用户会感到不安。 需要考虑F5、Ctrl+F5、⌘+F5等各种刷新图标。 在移动设备中,当用户重新加载浏览器时,许多网络浏览器会自动刷新页面。

方法 3:发布/发布

优点

您不必担心跨多个服务器的会话共享问题。

缺点

第二个表单提交可能会失败。

【问题讨论】:

【参考方案1】:

方法 1 是一种非常直接的方法,可以解决一些重复的帖子问题。它无法应对服务器延迟,这是重复提交的原因。

方法 2 是错误的。如果您限制浏览器标准功能(例如刷新),用户会感到不安。也就是说,如果您甚至能够在技术上跨浏览器这样做。您需要考虑 F5、Ctrl+F5、⌘ + F5 等各种刷新图标。

我必须承认我并不完全理解方法 3 的意图,但是,将用户退回到空白页面感觉有点不对。

另一种标准方法是在表单帖子中使用公告。这也将帮助您避免称为Cross Site Request Forgery 的安全风险。这很简单。

    在服务器上生成一个“唯一”随机字符串,称为 nonce。 将随机数插入数据库。 将 nonce 作为隐藏字段附加到表单(或通过 URL 或类似方式传递)。 确保随机数以表单形式发送到服务器。 在服务器端,验证 nonce,删除 nonce,“保存表单数据”。 显示确认页面。

如果您收到另一个带有不存在 nonce 的请求,那么您就知道它是重复的帖子或更邪恶的 CSRF 攻击。

您可能会找到为您执行此操作的 some support library。

【讨论】:

方法3的意图,正如我所说,我们需要用户提供一些表单数据(例如用户选择的颜色),并需要在确认页面上显示。 在PRG模式中,我们可以使用session。但由于我们使用多个 Web 服务器,会话共享或其他工作是一项额外的工作。 我们可以在重定向时使用参数,但我认为在url中显示用户的订单数据并不是一个好主意。 所以,从提交页面发送“用户表单数据”以轻松确认页面,我的同事建议方法 3。 好的,nonce 方法不依赖于共享会话 - 它依赖于我猜你已经拥有的共享数据库。

以上是关于为啥是 PRG 模式而不是其他模式?的主要内容,如果未能解决你的问题,请参考以下文章

PRG(Post/Redirect/Get)

其他设计模式

关于 std::cout,为啥使用“外部”而不是“单例模式”

为啥 SQL Server 不允许我启用混合身份验证模式,以便我可以使用 sa 用户将角色分配给其他用户?

为啥在vim中插入模式下按Backspace键,会输入^?,而不是向前删除呢?怎样更改设置?

“语义”是啥意思?为啥“移动语义”这样命名,而不是任何其他术语?