39

我一直在研究 Microsoft 的 ASP.NET MVC 教程,最后在这个页面

http://www.asp.net/learn/mvc/tutorial-32-cs.aspx

本页底部有以下声明:

通常,您不希望在调用修改 Web 应用程序状态的操作时执行 HTTP GET 操作。执行删除时,您希望执行 HTTP POST,或者更好的是 HTTP DELETE 操作。

这是真的?谁能提供更详细的解释这个声明背后的理由?

编辑

维基百科声明如下:

某些方法(例如,HEAD、GET、OPTIONS 和 TRACE)被定义为安全的,这意味着它们仅用于信息检索,不应更改服务器的状态。

相比之下,POST、PUT 和 DELETE 等方法适用于可能对服务器造成副作用的操作

4

10 回答 10

64

Jon Skeet 的答案是典型的答案。但是:假设您有一个链接:

href = "\myApp\DeleteImportantData.aspx?UserID=27"

和 google-bot 出现并索引您的页面?那会发生什么?

于 2009-04-24T14:30:17.677 回答
53

GET 通常没有副作用——换句话说,它不会改变状态。这意味着可以缓存结果,可以安全地制作书签等。

来自HTTP 1.1 RFC 2616

实施者应该意识到软件代表了他们在互联网上的交互,并且应该小心让用户意识到他们可能采取的任何可能对他们自己或他人产生意想不到的意义的行动。

特别是,已经建立了约定,即 GET 和 HEAD 方法不应该具有采取除检索之外的操作的意义。这些方法应该被认为是“安全的”。这允许用户代理以特殊的方式表示其他方法,例如 POST、PUT 和 DELETE,以便用户意识到正在请求可能不安全的操作。

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

于 2009-04-24T14:26:41.773 回答
20

除了关于幂等的纯粹问题之外,还有一个实际的方面:蜘蛛/机器人/爬虫等将跟随超链接。如果您将“删除”操作作为执行 GET 的超链接,那么 google 可以愉快地删除您的所有数据。参见“末日蜘蛛”。

对于帖子,这不是风险。

于 2009-04-24T14:29:25.480 回答
16

另一个例子..

http://example.com/admin/articles/delete/2

如果您已登录并拥有正确的权限,这将删除该文章。例如,如果您的网站接受评论并且用户将该链接作为图像提交;像这样:

<img src="http://example.com/admin/articles/delete/2" alt="This will delete your article."/>

然后,当您自己作为管理员用户浏览您网站上的评论时,浏览器将尝试通过向该 URL 发送请求来获取该图像。但是由于您在浏览器执行此操作时已登录,因此该文章将被删除。

如果不查看源代码,您甚至可能不会注意到,因为如果找不到图像,大多数浏览器都不会显示任何内容。

希望这是有道理的。

于 2011-03-11T17:08:13.793 回答
12

请在此处查看我的答案。它同样适用于这个问题。

  • 预取:很多网络浏览器都会使用预取。这意味着它会在您单击链接之前加载一个页面。预计您稍后会单击该链接。
  • 机器人:有几个机器人可以扫描和索引互联网以获取信息。他们只会发出 GET 请求。由于这个原因,您不想从 GET 请求中删除某些内容。
  • 缓存: GET HTTP 请求不应该改变状态,它们应该是幂等的。幂等意味着发出一次请求,或多次发出请求会给出相同的结果。即没有副作用。因此,GET HTTP 请求与缓存紧密相关。
  • HTTP 标准是这样说的:HTTP 标准说明了每种 HTTP 方法的用途。有几个程序是为使用 HTTP 标准而构建的,它们假定您将按照您应该的方式使用它。因此,如果您不遵循,您将在大量随机程序中出现未定义的行为。
于 2009-04-24T14:29:28.350 回答
4

除了蜘蛛和请求必须是幂等的之外,get 请求还有一个安全问题。有人可以轻松地向您的用户发送一封电子邮件

<img src="http://yoursite/Delete/Me" />

在文本中,浏览器会很高兴地继续尝试访问资源。使用 POST 并不能解决此类问题(因为您可以很容易地用 javascript 将表单帖子放在一起),但这是一个好的开始。

于 2009-04-24T18:07:54.813 回答
3

关于这个话题(HTTP 方法的使用),我推荐阅读这篇博文:http: //blog.codevader.com/2008/11/02/why-learning-http-does-matter/

这实际上是相反的问题:为什么在没有数据更改的情况下不使用 POST。

于 2009-04-24T14:30:04.853 回答
2

假设我们有一个网上银行应用程序,我们访问了转账页面。登录的用户选择将 10 美元转移到另一个帐户。

单击提交按钮重定向(作为 GET 请求)到https://my.bank.com/users/transfer?amount=10&destination=23lk3j2kj31lk2j3k2j

但是互联网连接很慢和/或服务器很忙,所以在点击提交按钮后,新页面加载速度很慢。

用户感到沮丧并开始疯狂地按 F5(刷新页面)。猜猜会发生什么?可能会发生多次转账,可能会清空用户的帐户。


现在,如果请求是作为 POST(或除 GET 之外的任何其他内容)发出的,第一个 F5(刷新页面)用户会让浏览器轻轻询问“你确定要这样做吗?它可能会产生副作用 [bla bla bla ]……”

于 2009-04-25T09:01:42.060 回答
2

除了这里提到的所有极好的原因之外,GET 请求可以由接收服务器记录,例如在access.log. 如果您在请求中发送敏感数据(例如密码),它们将被记录为纯文本。

即使为了安全的数据库存储而对它们进行了散列/加盐处理,违规(或有人在 IT 人员的肩膀上看着)也可能会暴露它们。这些数据应该放在 POST 正文中。

于 2018-09-29T01:32:02.910 回答
1

GET 的另一个问题是命令转到浏览器的地址栏。因此,如果您刷新页面,则再次发出命令,无论是“删除最后的东西”、“提交订单”还是类似的命令。

于 2009-04-24T15:02:48.473 回答