为什么HTTP没有POST重定向?


162

HTTP重定向是通过HTTP代码301和302(也可能是其他代码)以及带有新位置的地址的称为“位置”的标头字段完成的。但是,浏览器始终向该URL发送“ GET”请求。

但是,很多时候您需要通过POST(例如银行付款)将用户重定向到另一个域。这是一个常见的场景,并且确实是一个要求。有人知道为什么HTTP规范中忽略了这样的通用要求吗?解决方法是将表单(带有隐藏字段中的参数)的操作发送到目标位置(Location标头字段的值),然后setTimeout将表单提交到目标位置。


1
您正在寻找状态码307吗?请参阅下面的答案。
大卫·鲁特卡

Answers:


180

在HTTP 1.1中,实际上存在一个状态码307),该状态码指示应使用相同的方法并发布数据来重复该请求。

正如其他人所说的那样,这里有可能被滥用,这可能就是为什么许多框架在其抽象中坚持使用301和302的原因。但是,通过适当的理解和负责任的使用,您应该能够完成所需的工作。

请注意,根据W3.org规范,如果METHOD不是HEADGET,则用户代理应提示用户,然后在新位置重新执行请求。您还应该为用户提供注释和备用机制,以防旧的用户代理不确定如何处理307。

使用这种形式:

<form action="Test307.aspx" method="post">
    <input type="hidden" name="test" value="the test" />
    <input type="submit" value="test" />    
</form>

让Test307.aspx只需在以下位置返回307:http : //google.com,Chrome 13和Fiddler确认“ test = the test”确实已发布到Google。当然,进一步的响应是405,因为Google不允许发布POST,但它显示了机制。

有关更多信息,请参见HTTP状态代码列表W3.org规范

307临时重定向(自HTTP / 1.1起)在这种情况下,应使用另一个URI重复该请求,但是以后的请求仍可以使用原始URI。2与303相反,重新发出原始请求时,不应更改请求方法。例如,必须使用另一个POST请求重复POST请求。


2
@DavidRuttka,野外对浏览器的支持什么?
Pacerier,2014年

5
@DavidRuttka,您可能需要更新您的答案以将rfc7231考虑在内(已作废rfc2616)。提示用户是基于rfc2616中的要求。rfc7231中删除了此要求,并且rfc7231还引入了307重定向一定不能更改请求方法的要求(您在引用中提到了答案的结尾)。
nibarius

请注意,根据tools.ietf.org/id/draft-hunt-http-rest-redirect-00.html “,除非服务提供商知道客户端实际上是用户,否则不应该使用HTTP重定向代码301-306。代理”,因此看来ReSTful服务应该使用308而不是301。但这只是草稿。
布鲁斯·亚当斯

49

我在这里在此页面上找到了很好的解释。

WWW上最简单的情况是“幂等”事务,即可以重复而不会造成任何损害的事务。这些通常是“ GET”事务,这是因为它们是直接的URL引用(例如HTML中的href =或src =属性)的检索,或者是它们是使用GET方法提交的表单。重定向这样的事务很简单,没有任何问题:客户端接收到重定向响应,其中包括指定新URL的Location:标头,并且客户端通过将事务重新发布到新URL来对此做出反应。与这些重定向相关联的不同30x状态代码之间在隐式可缓存性方面有所不同,但是在其他方面,它们对于GET请求的响应基本相似(301和302)。

POST事务是不同的,因为从原则上讲,它们被定义为非等幂的(例如订购比萨饼,进行表决或进行其他操作),并且不得任意重复。

HTTP协议规范旨在考虑这种区别:GET方法定义为固有幂等,而POST方法至少定义为非幂等;该规范要求客户端代理(例如浏览器)采取多种预防措施,以防止用户无意间(重新)提交他们不想要的POST事务,或将POST提交到他们不希望的上下文中。

尽管我不喜欢从技术上限制用户的使用,以防止用户造成不必要的混乱或对应用程序造成不必要的伤害,但我可以理解这一点,这很有意义。


大部分的推论都归因于插管缓慢且不可靠的时代(它们仍然在世界上的许多地方)。我清楚地记得当我使用拨号时,每当有人拿起电话时,它就会随机断开。重新加载页面并查看服务器所处的状态比重新提交内容和冒两次执行相同操作的风险要好。
zzzzBov 2011年

@Falcon,是否将增加“访客计数器”视为非幂等?如果是这样,这些天几乎没有网站可以进行幂等的获取...
Pacerier 2014年

@Pacerier:通常将幂等解释为“以有意义的方式幂等”,例如,两次购买相同的商品,而不需要进行两次拜访。否则,你会说对的。但是实际上,该规范应该要求服务器在必要时具有有意义的幂等性,例如在页面中嵌入ID以防止重复-不需要浏览器向用户询问他们无法准确回答的问题。无论如何,阻止POST重定向都不会影响幂等性。这只是一条消息,说明请求的目标实际上在那儿。
劳伦斯·多尔

我看不出这种推理有何意义。假设我在大通银行网站上,然后提交了表格。我已经同意/信任他们。因此,如果他们必须将该数据重定向到另一页,我为什么还要再次同意。再举一个例子,假设我是默认情况下关闭JavaScript的人。有一天,我会在线填写抵押贷款应用程序,提交表单时会出错。如果应用程序可以重定向(使用POST)到我刚刚填写的用于预填充数据的页面,那就太好了。
b01

@Flacon,我需要证明用POST限制重定向可以在任何方面防止混乱。由于我首先必须使用我的数据来信任该应用程序,因此一旦拥有数据,他们就可以使用该应用程序执行任何操作。而且我认为重定向比使用POST请求更容易受到攻击。
b01

3

GET(和其他一些方法)在http规范(RFC 2616)中定义为“ SAFE” :

9.1.1安全方法

实施者应注意,该软件在通过Internet进行的交互中代表用户,并应小心谨慎,以使用户知道他们可能采取的任何对自己或他人而言具有意想不到的意义的动作。

特别是,已经建立了约定,即GET和HEAD方法不应具有除检索之外的其他任何操作。这些方法应该被认为是“安全的”。这允许用户代理以特殊方式表示其他方法,例如POST,PUT和DELETE,以便使用户知道请求了可能不安全的操作这一事实。

自然地,不可能确保服务器不会由于执行GET请求而产生副作用;实际上,一些动态资源认为该功能。这里的重要区别是用户没有要求副作用,因此不能对它们负责。

这意味着,除了看到他们可能不想看到的内容外,GET请求对用户永远不会有任何严重的后果,但是POST请求可能会更改对他们或其他人重要的资源。

尽管JavaScript改变了这种情况,但传统上用户界面有所不同-用户可以通过单击链接来触发GET请求,但必须填写表单来触发POST请求。我认为HTTP的设计者渴望维护安全和非安全方法之间的区别。

我也认为没有必要重定向到POST。大概需要执行的任何操作都可以通过在服务器端代码中调用一个函数来完成,或者如果它需要在其他服务器上发生,则可以将包含浏览器URL的重定向发送到服务器,而不是发送重定向到该服务器可以向该服务器本身发出请求,就像用户的代理一样。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.