何时应该使用GET或POST方法?它们之间有什么区别?

282

使用GETPOST方法的区别是什么?哪一个更安全?它们各自的(不)优点是什么?

(类似问题)


3
由于GET没有请求体,因此在实践中,您只能使用名称/值对作为数据结构,因为缺少任何查询字符串编码格式来处理更复杂的结构(例如数组、对象等)。如果您需要处理更复杂的数据结构(例如数组、对象等),则需要使用POST并且可能需要使用更高级的格式(如json/xml)。简而言之:除非必须(例如URL/资源必须可发现),否则不要使用GET。 - themihai
1
可能是当你使用POST和GET时的区别的重复问题。 - Imran Ali Khan
15个回答

295

这并不是安全问题。HTTP协议将GET类型请求定义为 幂等的,而POST可能会产生副作用。简单来说,GET用于查看某些内容而不更改它,而POST用于更改某些内容。例如,搜索页面应该使用GET,而更改密码的表单应该使用POST。

此外,请注意PHP有点混淆了概念。POST请求从查询字符串和请求正文获取输入。GET请求只从查询字符串获取输入。因此,POST请求是GET请求的超集;可以在POST请求中使用$_GET,并且甚至可以在$_POST$_GET中具有相同名称的参数,这些参数有不同的含义。

例如,假设您有一个用于编辑文章的表单。文章ID可能在查询字符串中(因此可以通过$_GET ['id']获得),但是假设您想更改文章ID。新ID可能存在于请求正文中($_POST ['id'])。好吧,也许这不是最好的例子,但我希望它能说明两者之间的区别。


16
GET和POST之间有明显的安全差异。例如,恶意网站可以在图像标签中添加任意GET请求,导致用户对另一个服务器执行GET操作。如果此GET请求类似于http://otherserver/deletemyaccount,则会发生糟糕的事情。请注意,这种差异可能会导致安全问题。 - Frank Schwieterman
3
我的意思是,$_POST 的内容并不会神奇地隐藏起来,使其免受恶意用户的攻击。显然,在所有编程事物中都存在安全方面的考虑。 - troelskn
2
这篇文章并没有完全回答问题,因为他没有提到安全方面的影响。上半部分还不错,只要把拼写错误的“pain English”改成“plain English”就可以了。下半部分太难理解了。总体而言,比我的帖子好多了。 :-) - Akrikos
1
“一个POST请求从查询字符串和请求体中获取输入。” 我认为这是不正确的。要使用任何一种输入,您都需要使用$ _REQUEST。$ _POST无法获取URL条目。 - Gunnar Bernstein
1
@Frank Schwieterman 我知道这篇帖子很旧了,但删除我的账户不是幂等的,也不应该使用get。 - frostymarvelous
显示剩余8条评论

87

当用户在表格中输入信息并单击提交按钮时,信息可以通过两种方式从浏览器发送到服务器:在URL中或在HTTP请求的正文中。

GET方法,在先前的示例中使用,在URL中附加名称/值对。不幸的是,URL的长度有限,因此只适用于少量参数。如果表单使用大量参数或参数包含大量数据,则URL可能会被截断。传递给URL的参数在浏览器的地址栏中可见,这不是密码显示的最佳位置。

GET方法的替代方法是POST方法。该方法将名称/值对封装在HTTP请求的正文中,使URL更加清晰,对表格输出没有大小限制。它也更加安全。


4
因为更难改变?你可以更改网址栏中的GET,但是修改POST就不那么容易了。 - IAdapter
12
服务器不能信任客户端。围绕错误假设设计应用程序,远非安全。 - troelskn
openid 也不安全,因为它可能会被破解? - IAdapter
1
我相信这是最清晰的解释——有关发送数据位置的差异。谢谢。 - greenoldman
客户端也可以使用curl或ajax发出get请求,并编写任何他想要的内容。 - shinzou

38

最佳答案是第一个。

您正在使用:

  • GET 当您想检索数据时(获取数据)。
  • POST 当您想发送数据时(提交数据)。

2
如果使用请求/响应服务模式并且想要同时执行两个操作怎么办? ;) 大多数情况下,当我需要得到响应时,我更喜欢使用 POST。 - Dmitry Pavlov
11
一般来说,这是正确的。GET也完全有能力“发送”数据,因此并不是非常准确的答案。 - Patrick Hofman

29
使用 GET 方法存在两种常见的“安全”隐患。由于数据出现在 URL 字符串中,可能会有人在地址栏/URL 上窥视,看到他们不应该知道的内容,例如会话 cookie,这可能会被用来劫持你的会话。请记住,每个人都有相机手机。 GET 的另一个安全隐患与 GET 变量被记录在大多数 Web 服务器访问日志中作为请求 URL 的一部分有关。根据情况、监管氛围和数据的一般敏感性,这可能会引起关注。
一些客户端/防火墙/IDS 系统可能会对包含过多数据的 GET 请求表示不满,并因此提供不可靠的结果。 POST 支持高级功能,如支持用于文件上传到 Web 服务器的多部分二进制输入。 POST 需要一个 content-length 头,这可能会增加应用程序特定客户端实现的复杂性,因为必须事先知道提交的数据大小,以防止客户端请求以单独的递增模式形成。对于那些选择滥用 HTTP 作为 RPC(远程过程调用)传输的人来说,这可能只是一个小问题。
其他人已经很好地涵盖了这个问题的语义差异和“何时”部分。

20

当我从URL中检索信息时,我使用GET,而在将信息发送到URL时,我则使用POST。


2
但你也可以使用GET发送。不同之处在于格式(在URL中(GET)或在请求中(POST))。 - eric
2
如果端点接受文件并从文件返回一行(不涉及数据创建、更改或数据库),那么该端点应该是GET还是POST? - variable

20
您应该使用POST方法来发送大量数据或者一些敏感信息(对于真正敏感的内容需要使用安全连接)。
如果您希望用户能够将您的页面添加到书签,请使用GET方法,因为所有数据都包含在书签中。
但是请注意,对于使用GET方法的页面,如果用户点击刷新按钮,数据将会重新发送,而不会提醒用户(POST方法有时会提醒用户重新发送数据)。

如果端点接受文件并从文件返回一行(不涉及数据创建、更改或数据库),那么该端点应该是GET还是POST? - variable
@variable POST。在这种情况下,主要是因为POST被构建用于处理文件上传,而标准的GET则不是。你必须每次页面加载时发送文件,因此使用标准的POST而不是GET+file是有意义的,否则会破坏GET期望URL每次都能提供更或多或少相同的结果的预期。 - Grant

18

这份 W3C 文档解释了使用HTTP GET和POST的情况。

我认为这是一份权威的资料。

总结如下(文档的第1.3节):

  • 如果交互更像一个问题(即,它是安全操作,如查询、读取操作或查找),请使用GET
  • 如果:
    • 交互更像一个订单,或者
    • 交互以某种方式改变了资源的状态,用户会感知到(例如,订阅服务),或者
    • 用户对交互的结果应负责任。
  • 请使用POST

11
我认为可以进一步概括为:在服务器状态未改变时使用GET方法,状态改变时使用POST方法。 - Yamcha

13

获取和提交(Get 和 Post)方法与您使用的服务器技术无关,在 php、asp.net 或 ruby 中都能正常工作。 GET 和 POST 是 HTTP 协议的一部分。 如 Mark 所指出的那样,POST 更加安全。POST 表单也不会被浏览器缓存。 POST 还用于传输大量数据。


12

在修改数据时使用POST的原因:

  • 像谷歌 Web 加速器这样的网络加速器会点击页面上所有的(GET)链接并将它们缓存。如果这些链接执行更改操作,这将非常糟糕。
  • 浏览器缓存 GET 请求,因此即使用户单击了链接,它也可能不会向服务器发送请求以执行更改。
  • 为了防止 CSRF 攻击,必须使用 POST。要完全保护应用程序,还必须在服务器上生成唯一标识符并将其发送到请求中。

同时,不要将敏感信息放在查询字符串中(只有使用 GET 才有这个选项),因为它会显示在地址栏、书签和服务器日志中。

希望这解释了人们为什么说 POST 是“安全”的原因。如果您正在传输敏感数据,必须使用 SSL。


9

GETPOST 是 HTTP 方法,它们都可以实现类似的目标。

GET 主要用于获取(检索)数据。一个 GET 请求不应该有请求体,所以除了 cookie 之外,传递信息的唯一位置就是 URL。由于 URL 的长度受限,GET 比起 POST 来说安全性较差,因为发送的数据是 URL 的一部分。

绝对不能在发送密码、信用卡或其他敏感信息时使用 GET!数据在 URL 中对所有人可见,可能被缓存。当我们重新加载页面或点击回退按钮时,GET 不会造成任何破坏,它会被书签化,参数会留在浏览器历史记录中,只允许使用 ASCII 字符。

POST 可以涉及任何内容,如存储或更新数据、订购产品或发送电子邮件。 POST 请求具有请求体。

POST 方法用于将敏感和机密信息传输到服务器,这些信息不会在 URL 的查询参数中可见,也不会保存在浏览器的历史记录中。数据长度没有限制。当我们重新加载页面时,浏览器应该警告用户即将重新提交数据。 POST 请求不能被书签化。


“GET请求不应该有消息体” - 这是什么意思? - Nico Haase

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