前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面试官:GET 和 POST 到底有什么区别?

面试官:GET 和 POST 到底有什么区别?

作者头像
沉默王二
发布2022-04-14 15:22:06
5090
发布2022-04-14 15:22:06
举报
文章被收录于专栏:沉默王二沉默王二

大家好,我是二哥呀。这个问题虽然看上去很初级,但实际上却涉及到方方面面,这也就是为啥面试里老爱问这个的原因之一。

刚好我最近在知乎上看到一篇文章,分析得非常透彻,就整理了一下发出来大家认真阅读一下。

作者:大宽宽,编辑:沉默王二,链接:https://www.zhihu.com/question/28586791/answer/767316172

HTTP 最早是被用来做浏览器和服务器之间交互 HTML 和 Form 表单的通讯协议,后来又被扩展到接口格式的定义上。所以要讨论 GET 和 POST 的区别,需要先确定是哪一种场景。

一、浏览器的 GET 和 POST

浏览器通过GET请求获取html页面/图片/css/js等资源;通过 POST来提交一个Form表单。

1)GET

“读取“一个资源,比如说GET一个html,反复 GET 不应该对访问的数据有副作用,没有副作用被称为“幂等“(Idempotent)。

比如说“GET一下,用户就下单了,返回订单已受理”是不可接受的,因为GET是读取,不应该改变数据的状态。

那既然 GET 是不改变数据状态的,就可以对GET请求的数据做缓存。

2)POST

点击 Form 表单中的 submit 按钮会发出一个POST请求让服务器做一件事。这件事往往是有副作用的,是不幂等的。

比如说通过POST下了一个单,服务器创建了新的订单,然后返回了订单成功的界面。那这个界面是不能缓存的,缓存了就意味着下单请求可以不向服务器发请求,而直接返回本地缓存的“下单成功界面”,而实际上服务器端并没有下单——多么的不符合逻辑。

如果尝试重新执行POST请求,浏览器也会弹一个框提示下这个刷新可能会有副作用,询问要不要继续。

3)小结

GET和POST携带数据的格式也有区别。

浏览器发出一个GET请求时,意味着要么是用户自己在浏览器的地址栏输入,要不就是点击了html里a标签的href中的url。

并不是GET只能用url,而是浏览器直接发出的GET只能由一个url触发。所以,GET请求上要带一些参数就只能依靠url上附带querystring。但是HTTP协议本身并没有这个限制。

浏览器的POST请求都来自表单提交。每次提交,表单的数据被浏览器用编码到HTTP请求的body里。浏览器发出的POST请求的body主要有有两种格式:

  • 一种是 application/x-www-form-urlencoded 用来传输简单的数据,大概就是"key1=value1&key2=value2"这样的格式
  • 另外一种是传文件,会采用multipart/form-data格式

浏览器在POST一个表单时,url上也可以带参数,只要<form action="url" >里的url带querystring就行。只不过表单里面的那些用<input> 等标签经过用户操作产生的数据都在会在body里。

我们一般会泛泛的说“GET请求没有body,只有url,请求数据放在url的querystring中;POST请求的数据在body中“。但这种情况仅限于浏览器发请求的场景。

二、接口中的GET和POST

这里通常是指通过浏览器的Ajax、IOS/Android App的http client、Java的commons-httpclient/okhttp、curl、postman之类的工具发出来的GET和POST请求。

此时的GET/POST不光能用在前端和后端的交互中,还能用在后端各个子服务的调用中(即当一种 RPC 协议使用)。

尽管RPC有很多协议,比如thrift、grpc,但是http本身已经有大量的现成的支持工具可以使用,并且很友好,容易debug。所以HTTP协议在微服务中的使用是相当普遍的。

当用HTTP实现接口发送请求时,就没有浏览器中那么多限制了,只要是符合HTTP格式的就可以发。HTTP请求的格式,大概是这样的一个字符串:

代码语言:javascript
复制
<METHOD> <URL> HTTP/1.1
<Header1>: <HeaderValue1>
<Header2>: <HeaderValue2>
...
<HeaderN>: <HeaderValueN>
<Body Data....>

其中的<METHOD>可以是GET也可以是POST,或者其他的HTTP Method,如PUT、DELETE、OPTION……。

从协议本身看,并没有什么限制说GET一定不能没有body,POST就一定不能把参放到<URL>的querystring上。

因此其实可以更加自由的去利用格式。比如Elastic Search的_search api就用了带body的GET;也可以自己开发接口让POST一半的参数放在url的querystring里,另外一半放body里;你甚至还可以让所有的参数都放Header里——可以做各种各样的定制,只要请求的客户端和服务器端能够约定好。

当然,太自由也带来了另一种麻烦,开发人员不得不每次讨论确定参数是放url的path里,querystring里,body里,header里这种问题,太低效了。

于是就有了一些列接口规范/风格。其中名气最大的当属REST。

REST充分运用GET、POST、PUT和DELETE,约定了这4个接口分别获取、创建、替换和删除“资源”,REST最佳实践还推荐在请求体使用json格式。这样仅仅通过看HTTP的method就可以明白接口是什么意思,并且解析格式也得到了统一。

REST中GET和POST不是随便用的。在REST中, 【GET】 + 【资源定位符】被专用于获取资源或者资源列表,比如:

代码语言:javascript
复制
GET http://foo.com/books          获取书籍列表
GET http://foo.com/books/:bookId  根据bookId获取一本具体的书

与浏览器的场景类似,REST GET也不应该有副作用,于是可以被反复无脑调用。

REST 【POST】+ 【资源定位符】则用于“创建一个资源”,比如:

代码语言:javascript
复制
POST http://foo.com/books
{
  "title": "大宽宽的碎碎念",
  "author": "大宽宽",
  "editor": "沉默王二",
  ...
}

这里你就能留意到浏览器中用来实现表单提交的POST,和REST里实现创建资源的POST语义上的不同。

三、关于安全性

我们常听到GET不如POST安全,因为POST用body传输数据,而GET用url传输,更加容易看到。但是从攻击的角度,无论是GET还是POST都不够安全,因为HTTP本身是明文协议。每个HTTP请求和返回的每个byte都会在网络上明文传播,不管是url,header还是body。

这完全不是一个“是否容易在浏览器地址栏上看到“的问题。

为了避免传输中数据被窃取,必须做从客户端到服务器端的加密。

业界的通行做法就是https——即用SSL协议协商出的密钥加密明文的http数据。这个加密的协议和HTTP协议本身相互独立。如果是利用HTTP开发公网的站点/App,要保证安全,https是最最基本的要求。

回到HTTP本身,GET请求的参数更倾向于放在url上,因此有更多机会被泄漏。

此外,从客户端到服务器端,有大量的中间节点,包括网关,代理等。他们的access log通常会输出完整的url,比如nginx的默认access log就是如此。如果url上携带敏感数据,就会被记录下来。

请注意,就算私密数据在body里,也是可以被记录下来的,因此如果请求要经过不信任的公网,避免泄密的唯一手段就是https。

安全是一个巨大的主题,有由很多细节组成的一个完备体系,比如返回私密数据的mask,XSS,CSRF,跨域安全,前端加密,钓鱼,salt,…… POST和GET在安全这件事上仅仅是个小角色。

因此单独讨论POST和GET本身哪个更安全意义并不是太大。只要记得一般情况下,私密数据传输用POST + body就好。

四、总结

上面讲了一大堆,是希望读者不要死记硬背GET和POST的区别,而是能从更广的层面去看待和思考这个问题。

协议都是人定的。只要客户端和服务器能彼此认同,就能工作。在常规的情况下,用符合规范的方式去实现系统可以减少很多工作量——大家都约定好了,就不要折腾了。但是,总会有一些情况用常规规范不合适,不满足需求。遇到这种情况的时候,思路不能被规范限制死。比如说:

用POST写一个下单接口时也要考虑幂等,因为前端的“下单按键”有bug,造成用户一次点击发出N个请求。你不能说因为POST 不是幂等的就不管了。


没有什么使我停留——除了目的,纵然岸旁有玫瑰、有绿荫、有宁静的港湾,我是不系之舟

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-03-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 沉默王二 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、浏览器的 GET 和 POST
  • 二、接口中的GET和POST
  • 三、关于安全性
  • 四、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档