何时使用POST,何时使用GET?

407

据我所知,它们可以分为三类:

  1. 永远不要使用 GET,而是使用 POST
  2. 永远不要使用 POST,而是使用 GET
  3. 你使用哪种方法都可以。

我是否正确地假设了这三种情况?如果是这样,每种情况有哪些例子?


3
那其实完全不正确。GET和POST在可见程度上是相同的,如果您查看浏览器发送的标头,您将看到您提交的键值对列表。 - Velimir Tchatchevsky
3
http://www.w3.org/2001/tag/doc/whenToUseGet.html - icc97
2
没有标准的方法可以将多个名称-值对编码到查询字符串中,因此除非您的请求非常基本(即没有数组或嵌套数据结构),否则应该仅考虑使用POST方法,它提供了一个body字段,您可以使用编码格式(JSON、XML等)来传输数据。 - themihai
请查看此答案:https://dev59.com/MHRB5IYBdhLWcg3wz6UK#63170529 - Chiwda
27个回答

443

对于创建(我知道这很讽刺)、编辑和删除等破坏性操作,请使用POST,因为您无法在浏览器地址栏中调用POST操作。当允许用户调用操作时,请使用GET。因此,URL可能如下:

http://myblog.org/admin/posts/delete/357

应该将您带到确认页面,而不仅仅是删除该项。这样更容易避免意外情况。

POSTGET 更安全,因为您不必将信息放入 URL 中。因此,在收集密码或其他敏感信息的 HTML 表单中使用 GET 作为 method 不是最好的选择。

最后注意一点: POST 可以传输比 GET 更多的信息。 'POST' 对于传输的数据没有大小限制,而 'GET' 的限制为2048个字符。


93
GET 请求的响应可能会被缓存。POST 请求的响应则不能被缓存。 - mkoeller
41
不在URL中添加信息如何使其更安全?(顺便说一句,我是那些相信虚假的安全感比根本没有安全感更危险的人之一)。 - ePharaoh
47
它可以防止旁观者在地址栏上看到用户输入密码。 - Quentin
40
“对于普通观察者来说暴露的数据稍微少一些”可能比“更安全”这个表述更好- URL可能会被记录、引用和缓存到许多地方。当然,你是正确的,这并不会增加安全性,但它限制了最糟糕的不安全实践(也可以参见:http://thedailywtf.com/Articles/The_Spider_of_Doom.aspx)。 - Piskvor left the building
30
@David Dorward:或者更常用的称呼:肩膀攻击。 - Idan K
显示剩余15条评论

248

简述

  • 对于安全且幂等idempotent的请求,请使用GET
  • 对于既不安全也不幂等的请求,请使用POST

详细说明 每个操作都有适当的位置。即使您不遵循RESTful原则,学习REST和资源导向方法的工作原理也可以获得很多收益。

RESTful应用程序将使用GET来进行既安全又幂等的操作。

一个安全的操作是一个不改变请求数据的操作。

一个幂等的操作是无论请求多少次结果都是相同的操作。

由于GET用于安全操作,因此它们也自动成为幂等操作。通常,GET用于检索资源(例如stackoverflow上的问题及其相关答案)或资源集合。

RESTful应用程序将使用PUT来进行既不安全但幂等的操作。

我知道这个问题是关于GET和POST的,但我会在一秒钟内回到POST。

通常,PUT用于编辑资源(例如stackoverflow上的问题或答案编辑)。

POST将用于任何既不安全也不幂等的操作。

通常情况下,POST用于创建新的资源,例如创建一个新的SO问题(尽管在某些设计中也可以使用PUT)。

如果你运行POST两次,你就会创建两个新问题。

还有一个DELETE操作,但我想我可以把它留在那里:)

讨论

实际上,现代Web浏览器通常只可靠支持GET和POST(您可以通过javascript调用执行所有这些操作,但在填写表单并按提交按钮方面,您通常只有两个选项)。在RESTful应用程序中,POST通常会被覆盖以提供PUT和DELETE调用。

但是,即使您不遵循RESTful原则,考虑使用GET检索/查看信息和POST创建/编辑信息也可能很有用。

您永远不应该使用GET来更改数据。如果搜索引擎爬取到您的恶意操作链接,或者客户端将其加为书签,可能会带来大麻烦。


如果您要创建用于登录的APIREST资源,您可以选择这种方式,它是安全的且幂等性良好,我猜是这样的。 - jhonny lopez
2
安全的获取操作并不自动满足幂等性。即使是相同的非破坏性查询,结果集也可能会有所不同。 - RichieHH
3
你写的那种类似“GET currenttime”的方式是不正确的,因为它不是幂等的(重复查询可能会产生不同的结果);实际上,任何查询的结果都可能随时间而变化。因此,我们应该从查询本身的“副作用”角度来表达幂等性。由于仅仅请求当前时间没有“副作用”,所以这是一个完美的GET请求而不是POST。 - Hagen von Eitzen
如果我想查看数据,但需要将数组或JSON作为参数传递,那么将数组转换为字符串并将其作为GET发送是否可行?还是在这种情况下只需使用POST并将数组作为主体发送即可? - A.J Alhorr
通常在GET请求中,任何参数都存在于URL的查询字符串中。现在,在HTTP规范中没有限制阻止您拥有非空的GET请求体,但是某些服务器配置可能不允许它。我认为Elasticsearch的API允许在GET请求的正文中包含信息,例如。现在这都是个人喜好。 - spencer741

85

如果您不介意请求被重复发送(即不改变状态),请使用GET。

如果操作会改变系统的状态,请使用POST。


1
由于表单会改变系统的状态,为什么HTML表单标签的默认方法是GET? - tirenweb
5
一个搜索框是否会改变可见状态?默认值很久以前就被设置好了,可能仅仅是偶然。我并没有深入研究历史,甚至不知道在表单成为选项时POST是否是一个选项。 - Douglas Leeder
@ziiweb 即使大多数情况下<form>的使用是POST,最好将默认值定义为“无害”的GET。从安全角度来看,这似乎很荒谬,因为它会导致数据在日志文件等中暴露,但就服务器端数据而言,它是故障安全的(服务器不应在GET时修改数据)。我想,今天人们会有不同的关注点(最好通过删除任何默认值并使“方法”强制执行来实现)。 - Hagen von Eitzen
假设我有一个接收文件作为输入的端点,在文件上执行某些处理(例如 - 基于正则表达式提取数据),并返回JSON数据,那么我可以使用GET请求将文件上传到服务器。还是应该使用POST请求? - variable
那非常简洁。 - Yehia A.Salam

70

简要版

GET:通常用于提交搜索请求或需要用户能够再次精确调取页面的任何请求。

GET 的优点:

  • URL 可以安全地加为书签。
  • 页面可以安全地重新加载。

GET 的缺点:

POST:用于更高安全级别的请求,其中数据可能用于更改数据库,或者您不希望某人加为书签的页面。

POST 的优点:

  • 名称-值对不会显示在 URL 中。(安全性增加1)
  • 可以通过 POST 传递无限数量的名称-值对。 参考资料。

POST 的缺点:

  • 使用 POST 数据的页面无法加为书签。(如果您愿意的话。)

详细版

直接引用超文本传输协议 - HTTP/1.1

9.3 GET

GET 方法表示检索由 Request-URI 标识的任何信息 (以实体形式)。如果 Request-URI 引用数据生成进程,则将作为响应中的实体返回所生成的数据,而不是该进程的源文本,除非该文本恰好是该进程的输出。

如果请求消息包含If-Modified-Since、If-Unmodified-Since、If-Match、If-None-Match或If-Range报头字段,则GET方法的语义将更改为“条件GET”。条件GET方法要求只在符合条件的情况下传输实体,这些条件由条件报头字段描述。条件GET方法旨在通过允许刷新缓存实体而无需多次请求或传输客户端已经持有的数据来减少不必要的网络使用。
如果请求消息包括一个Range报头字段,则GET方法的语义将更改为“部分GET”。部分GET请求只传输实体的部分内容,如第14.35节所述。部分GET方法旨在通过允许完成部分检索的实体而无需传输客户端已经持有的数据来减少不必要的网络使用。
仅当响应满足第13节中描述的HTTP缓存要求时,GET请求的响应才可缓存。
有关表单使用时的安全注意事项,请参见第15.1.3节。
POST方法用于请求源服务器将请求中封闭的实体作为与Request-Line中标识的资源的新下属接受。POST被设计为允许一个统一的方法来覆盖以下功能:
- 注释现有资源; - 将消息发布到公告板、新闻组、邮件列表或类似的文章组; - 提供一块数据,例如提交表单的结果,以供数据处理过程使用; - 通过追加操作扩展数据库。
POST方法实际执行的功能由服务器确定,通常取决于Request-URI。提交的实体与该URI相对应,就像文件与包含它的目录相对应,新闻文章与其所属的新闻组相对应一样。

发布(POST)方法是HTTP协议的一种方法,用于将实体提交到指定的资源,例如将新文章提交到新闻组或将记录提交到数据库的下级。

通过“POST”方法执行的操作可能不会产生可以由URI标识的资源。在这种情况下,根据响应是否包含描述结果的实体,200(OK)或204(无内容)是适当的响应状态。


2
使用了POST数据的页面无法被添加到书签:好吧,这是一个优点,不是吗?您可能不希望您的数据更改查询被添加到书签。 - Piskvor left the building
我想,如果每次使用post时都是出于安全目的,那么这将是一个优势。通常情况下确实如此,但GET有长度限制。也许有人只是传递了大量与安全无关的数据,并希望页面被加为书签?谁知道呢... - Cimplicity
关于GET的一个缺点,即“变量作为名称-值对通过URL传递”,MVC是否会通过路由和友好的URL解决这个问题? - MrBoJangles
@MrBoJangles:使用美观的URL并不能防止所提到的“肩上观察”的风险。顺便说一下,MVC并不需要使用美观的URL路由,使用美观的URL路由也不需要MVC;它们有时会一起使用,但也可以分别使用。 - icktoofay
在.NET世界中,就实际而言,良好的URL功能=MVC。我想你可以进行一些IIS重写或一些奇怪的基于代码的操作,但它们甚至更不愉快。毋庸置疑,MVC获胜了。 - MrBoJangles
“使用了post数据的页面不能被收藏”是彻头彻尾的谎言。在Mozilla上至少是可以的。” - Trect

32

首要重要的是GET和POST的含义区别:

  • GET 应该用于从服务器获取信息
  • 而 POST 应该用于向服务器发送信息。


此外,可以注意以下几点:

  • 使用 GET,您的用户可以使用浏览器的 "返回" 按钮,并且他们可以将页面加入书签
  • GET 参数传递的大小存在限制 (对于一些版本的Internet Explorer为2KB,如果我没有记错);POST 的限制更大,通常取决于服务器的配置。


无论如何,我认为没有 GET 我们就无法 "生存":想想您每天使用多少带有查询字符串参数的 URL —— 没有 GET,所有这些都不会工作 ;-)


如果每个人都使用GET风格的漂亮URL:http://example.com/var1/value1/var2/value2/var3/value3,我们在技术上就可以不再使用GET了... - Tyler Carter
6
除非你仍然需要获取那个资源。几乎所有的网页、图片、脚本等都是通过使用 GET 方法在 Web 浏览器中加载的。 - Ryan
3
@Chacha102 - 即使是www.mypage.com/contact/,内部也会使用GET方法来处理类似于index.php?url=/contact/的内容。 - Thiago Belem
1
强调GET的大小限制!此外,GET参数包含在书签中,而POST则不包括。用户可以刷新GET请求的页面,但不能刷新POST请求的页面(没有重新发送信息的警告)。 - Ricket

15

除了在许多Web浏览器中存在的长度限制差异外,还存在语义差异。GET应该是“安全”的,因为它们是只读操作,不会更改服务器状态。POST通常会更改状态,并且会在重新提交时发出警告。搜索引擎的网络爬虫可能会进行GET,但不应进行POST。

如果您想读取数据而不更改状态,请使用GET;如果您想在服务器上更新状态,请使用POST。


1
这是与其他一切相关内容遵循的RFC的关键概念差异。http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.3 - Frank Farmer

8

一个实际的区别是,浏览器和web服务器对URL中存在的字符数量有限制。具体的限制因应用程序而异,但如果表单中有标签,则很可能会超出限制。

另一个需要注意的问题是GET请求会被搜索引擎和其他自动化系统索引。谷歌曾经推出一款产品,可以预取你正在浏览的页面上的链接,以便在你点击这些链接时更快地加载。这给那些链接带有delete.php?id=1这样的网站造成了严重的破坏 - 用户失去了整个网站。


1
你的Web服务器可能也有限制。 - Billy ONeal
1
很好的观点,@BillyONeal,我已经加上了。@chelmertz 是的,但如果我想要的话,我可以更改它,而且它要高得多。例如,我已经将1 GB文件POST到Apache实例中。 - ceejayoz
2
@Honey 搜索引擎遵循链接。链接发出 GET 请求。搜索引擎不会提交表单(如果它们这样做,你会看到 Google 每隔几天在你的网站上注册一个帐户),因此不会发出 POST 请求。 - ceejayoz
@Honey,我真的不知道你想说什么。GET请求是用来获取信息的。POST请求是用来执行操作的。同一个URL可能会响应POST和GET请求,并根据请求的不同而执行不同的操作。Google只会索引它遇到的GET URL。如果在/qpoiweurpiowqueproiuwer.html上有一个GET URL,但没有任何链接指向它,Google也不会知道它的存在。 - ceejayoz
明白了。你的意思是Google可能会访问与GET使用相同的URL,但不会POST任何内容,因为它会自动填充表单,从而HTTP正文为空? - mfaani
显示剩余3条评论

8

我的一般准则是在向服务器发送不会更改状态的请求时使用 Get。而当需要向服务器发送更改状态的请求时,则应该使用 Post。


7

当您希望URL反映页面状态时,请使用GET。这对于查看动态生成的页面非常有用,例如在此处看到的那些页面。在表单中提交数据时应使用POST,例如当我点击“发布您的答案”按钮时。它还会生成一个更干净的URL,因为它不会在路径之后生成参数字符串。


6

1.3 选择 HTTP GETPOST 的快速检查清单

如果满足以下情况,请使用 GET:

    The interaction is more like a question (i.e., it is a safe operation such as a query, read operation, or lookup).

Use POST if:

    The interaction is more like an order, or
    The interaction changes the state of the resource in a way that the user would perceive (e.g., a subscription to a service), or
    The user be held accountable for the results of the interaction.

Source.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接