写在最前,如果想立刻知道区别,直接看第四章即可。
一、误区
http get和post的区别?五大误区?
1、get用于获取数据,post用于提交数据
2、get提交参数追加在url后面,post参数可以通过http body提交
3、get的url会有长度上的限制,则post的数据则可以非常大
4、get提交信息明文显示在url上,不够安全,post提交的信息不会在url上显示
5、get提交可以被浏览器缓存,post不会被浏览器缓存
满满的套路,害死人不偿命。接下来为您一一解开谜底。。
二、交互方式
为了更好的说明问题,先扯扯淡,说说客户端与服务器交互方式。
我们都知道,使用URL可以确定一个资源所在的位置,那么我们确定这个资源以后,是如何对这个资源进行处理的呢?
Http协议定义了客户端与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE。URL定位了这个资源,而HTTP中的GET,POST,PUT,DELETE就是对应着对这个资源的查,改,增,删4个操作。到这里,大家应该有个大概的了解了,GET一般用于获取/查询资源信息,而POST一般用于更新资源信息。那么,除了上面说的四种方法,HTTP还有其它方法么?其实HTTP中定义了以下几种请求方法:
- GET方法
- HEAD方法
- PUT方法
- POST方法
- TRACE方法
- OPTIONS方法
- DELETE方法
2.1 Get
Get是最常用的方法,通常用于请求服务器发送某个资源。
HEAD方法与GET方法的行为很类似,但服务器在响应中只返回实体的主体部分。这就允许客户端在未获取实际资源的情况下,对资源的首部进行检查,使用HEAD,我们可以更高效的完成以下工作:
在不获取资源的情况下,了解资源的一些信息,比如资源类型;
通过查看响应中的状态码,可以确定资源是否存在;
通过查看首部,测试资源是否被修改。
2.2 Put
PUT方法是让服务器用请求的主体部分来创建一个由所请求的URL命名的新文档;如果那个文档存在的话,就用这个主体来代替它。
2.3 Post
POST方法向服务器提交数据,比如完成表单数据的提交,将数据提交给服务器处理。
2.4 Trace
TRACE方法会在目的服务器端发起一个“回环”诊断,我们都知道,客户端在发起一个请求时,这个请求可能要穿过防火墙、代理、网关、或者其它的一些应用程序。这中间的每个节点都可能会修改原始的HTTP请求,TRACE方法允许客户端在最终将请求发送服务器时,它变成了什么样子。由于有一个“回环”诊断,在请求最终到达服务器时,服务器会弹回一条TRACE响应,并在响应主体中携带它收到的原始请求报文的最终模样。这样客户端就可以查看HTTP请求报文在发送的途中,是否被修改过了。
2.5 Options
OPTIONS方法用于获取当前URL所支持的方法。若请求成功,则它会在HTTP头中包含一个名为“Allow”的头,值是所支持的方法,如“GET, POST”。
2.6 Delete
DELETE方法就是请求服务器删除指定URL所对应的资源。但是,客户端无法保证删除操作一定会被执行,因为HTTP规范允许服务器在不通知客户端的情况下撤销请求。
上面对HTTP所支持的所有方法大体上进行了介绍,但是在实际开发中,我们使用的更多的是GET和POST,而且在面试的时候,也经常会问GET和POST的区别,这里就着重对GET和POST的区别进行总结。
三、揭露真相
3.1 get用于获取数据,post用于提交数据
GET 的本质是「得」,而 POST 的本质是「给」。而且,GET 是「幂等」的,在这一点上,GET 被认为是「安全的」。但实际上 server 端get方法也可以用作资源更新,都有“写”功能,最简单的例子就是/delete?id=1,但是这种用法违反了约定,容易造成 CSRF(跨站请求伪造)。
3.2 get提交参数追加在url后面,post参数可以通过http body提交
http没明确规定什么get/post方法要用什么样的方式传输数据,之所以有这种描述,原因主要有两点:浏览器设计、服务器设计。
浏览器不支持get+httpbody是比较常见的。fiddler模拟请求时,如果是get,你填下面的body部分会红色显示,告诉你这样不好,仅仅是不好,因为fiddler并没有禁止get+body这种请求,但看得出它不建议你用这种方式的请求。
常见的servlet服务器不支持。比如tomcat,默认不解析get的body部分,造成了get不能用body传递参数的现象。
3.3 get的url会有长度上的限制,则post的数据则可以非常大
由于使用GET方法提交数据时,数据会以&符号作为分隔符的形式,在URL后面添加需要提交的参数,有人就会说了,浏览器地址栏输入的参数是有限的,而POST不用再地址栏输入,所以POST就比GET可以提交更多的数据。难道真的是这样的么?
而实际上,URL不存在参数上限的问题,HTTP协议规范没有对URL长度进行限制。这个限制是特定的浏览器及服务器对它的限制。IE对URL长度的限制是2083字节(2K+35)。对于其他浏览器,如Netscape、FireFox等,理论上没有长度限制,其限制取决于操作系统的支持。
同时,POST是没有大小限制的,HTTP协议规范也没有进行大小限制。POST数据是没有限制的,起限制作用的是服务器的处理程序的处理能力。
总归一句话,这个限制是针对所有HTTP请求的,与GET、POST没有多少关系。
3.4 get提交信息明文显示在url上,不够安全,post提交的信息不会在url上显示
GET将提交到服务器的数据添加到URL中了,可见;虽然POST的数据,你肉眼看不到,你抓个包看看,在HTTP包的包体中,我们提交的数据时仍然可见的;所以说,从这方面来说,POST也是以五十步笑百步了。
另外扯一句,Base64不是加密,用这个加密就是掩耳盗铃啊。
3.5 get提交可以被浏览器缓存,post不会被浏览器缓存
get被建议做成幂等的,缓存是很有必要的,一般静态资源的get请求都是会设置有效缓存时间的,这一点很容易想明白。很多时候缓存get在服务器和浏览器中是默认行为,这对大量使用get请求的ajax不利,所以ajax请求一般会在请求url后加上一个随机数,浏览器和服务器就认为它是不同的get请求,不会缓存这个get请求。
POST的resp实际上是允许被缓存的,但是一般都不实现这个。
浏览器不实现是有道理的,现实中POST大多执行的是写操作,缓存写操作结果无意义,还有POST可以说是登录/支付这类功能的标准方法了,双方交流的是敏感数据,缓存这类数据的安全隐患很大。
四、Get与Post的区别
4.1 post请求包含更多的请求头
post需要在请求的body部分包含数据,所以会多了几个数据描述部分的首部字段(如content-type),这其实是微乎其微的。
4.2 post比get慢
- post请求的过程:
1.浏览器请求tcp连接(第一次握手)
2.服务器答应进行tcp连接(第二次握手)
3.浏览器确认,并发送post请求头(第三次握手,这个报文比较小,所以http会在此时进行第一次数据发送)
4.服务器返回100 continue响应
5.浏览器开始发送数据
6.服务器返回200 ok响应
- get请求的过程
1.浏览器请求tcp连接(第一次握手)
2.服务器答应进行tcp连接(第二次握手)
3.浏览器确认,并发送get请求头和数据(第三次握手,这个报文比较小,所以http会在此时进行第一次数据发送)
4.服务器返回200 ok响应
也就是说,目测get的总耗是post的2/3左右。
4.3 post能发送更多的数据类型
post能发送更多的数据类型、get只能发送ASCII字符。
4.4 安全性
post不会作为url的一部分,不会被缓存、保存在服务器日志、以及浏览器浏览记录中。
4.5 post发送的数据量更大
前面误区说了,不是因为post和get的原因,是因为浏览器设计与服务器设计的问题导致的。