从HTTP GET和POST的区别说起

在推特上抱怨面试时问HTTP GETE和POST的区别得到回答都不满意,有人不清楚,当时只回复了看 RFC2616。趁有空说说

面试时得到的回答大多是:POST是安全的,因为被提交的数据看不到,或者被加密的,其它的还有GET的时候中文出现乱码(在地址栏里),数据最大长度限制等等。

说 POST 比 GET 安全肯定是错的,POST跟GET都是明文传输,用httpfox等插件,或者像WireShark 等类似工具就能观察到。

POST和GET的差别其实是很大的。语义上,GET是获取指定URL上的资源,是读操作,重要的一点是不论对某个资源GET多少次,它的状态是不会改变的,在这个意义上,我们说GET是安全的(不是被密码学或者数据保护意义上的安全)。因为GET是安全的,所以GET返回的内容可以被浏览器,Cache服务器缓存起来(其中还有很多细节,但不影响这里的讨论)。

而POST的语意是对指定资源“追加/添加”数据,所以是不安全的,每次提交的POST,参与的代码都会认为这个操作会修改操作对象资源的状态,于是,浏览器在你按下F5的时候会跳出确认框,缓存服务器不会缓存POST请求返回内容。

很遗憾到目前为止没有应聘者能够提到这一点。我猜测这背后的原因大概有两个,一是也许大多数人往往(我也一样)满足于只要完成任务就好,不管用哪个,表单提交了,数据处理了,内容显示或者重新定向到另外一个页面,就算完成了一个任务,从任务表里划掉,结束。而且对大部分项目(OA, CRM, MIS)的大部分情况下,用哪个似乎都可以。

同时,在被商业机构在媒体和书籍上宣传兜售的WS-*概念和使用集成开发环境提供的“方便”的代码生成工具后,“了解”到所有Web服务调用都是通过POST,更潜意识里确定了POST和GET是一样的,而且GET能做的,POST都能做,POST简直就是GET++嘛。自然,能用POST就用POST,不必在乎两者的差别了。

这又让我想起最近学到的一个概念: Radius Of Comprehension,理解的半径:

当学习概念A的时候,需要先了解概念B,而概念C又是理解B的前提。当B和C都是新的需要学习的概念时,可以说A的理解半径是2,如图:

A --> B --> C
|--1--|--2--|

在学习Web开发时,接触到GET和POST时,“理解的半径”可能包涵:

POST vs. GET
     |---> Conditional GET -> ETag -> Cache
     |         `--> Status Code
     `---> HTTP的方法 --> URL

往往因为仅仅满足于完成手上被要求的任务,或者懒于问一个为什么,我们就把自己的理解半径设置成零,那么就学不到更深入的东西,也因此仅仅知道POST和GET不同,而不再会了解不同在哪里,什么是Conditional GET和缓存header等概念。

从一个简单的面试问题谈到这,貌似小题大作了,写到哪算哪吧。

<UPDATE>
看到Fenng Buzz 了这篇文字,引起一些评论,因此在这再讨论两个概念: 安全的(Safe)和幂等的(Idempotent)

安全的是指没有明显的对用户有影响的副作用(包括修改该资源的状态)。HTTP方法里的GET和HEAD都是安全的。

幂等的是指一个方法不论多少次操作,结果都是一样。PUT(把内容放到指定URL),DELETE(删除某个URL代表的资源),虽然都修改了资源内容,但多次操作,结果是相同的,因此和HEAD,GET一样都是幂等的。

所以根据HTTP协议,GET是安全的,也是幂等的,而POST既不是安全的,也不是幂等的。
</UPDATE>

16 Responses to “从HTTP GET和POST的区别说起”

  1. Tweets that mention 从HTTP GET和POST的区别说起 -- Topsy.com Says:

    [...] This post was mentioned on Twitter by Yining and Felix Wang | 特别变态老王王, 蓝色马赛克. 蓝色马赛克 said: #share 从HTTP GET和POST的区别说起: 在推特上抱怨面试时问HTTP GETE和POST的区别得到回答都不满意,有人不清楚,当时只回复了看 RFC2616。趁有空说说… http://goo.gl/fb/dQelE [...]

  2. yegle Says:

    个人感觉,如果非要从POST和GET的区别,希望应聘者推导出所谓的”安全”与”不安全”的区别,那么至少提问方式上要有倾向或者暗示。

    我作为应试者,被提问过这个问题。折腾过squid,知道POST不能被缓存以及不能被缓存的原因,但是要回答出您日志里提到的那点,还是有点距离的。

  3. yegle Says:

    提问应试者对http proxy的缓存功能的理解,才是更合适的问题。

  4. lanqy Says:

    对这两个概念有了更深入的了解,感谢分享

  5. IUSR Says:

    @yegle 这个GET vs POST的比较从缓存方面来说应该算是稍微边缘一些的方向。

  6. wuxian Says:

    老实说,这是语义的问题,你说的缓存等问题,现代的ajax技术都依靠加时间戳的方式来避免缓存,所以你的这个答案实在是让人想不到,我只想到一些长度限制,以及跨域的问题

  7. ShiningRay Says:

    lz在这里面涉及了restful的概念

  8. Yining Says:

    @yegle 缓存除了 http proxy 还有浏览器部分,从网站应用开发(PHP, JSP)和前端性能也都需要了解到这些概念的。

    @wuxian ajax也是基于http,也要了解和应用这些概念。ajax get的请求返回头里用last-modified来避免(长期)缓存和post的概念还是不一样。

  9. 神仙 Says:

    哈哈
    我出的题里也有这个。情况也差不多。

  10. dh Says:

    你这个从Restful那种角度来分析,但是的确,很多OA系统都是post的。可能是为了那个url更简单。设计URL难度也不小。呵呵

  11. duan Says:

    nice post,thannks for sharing,this is what i want

  12. xiaog Says:

    从协议上来理解,最大的区别还是,是否改变资源状态,T大师的REST架构设计中,就说了。

  13. 从HTTP GET和POST的区别说起【转】 | 段弘 Says:

    [...] 原文链接 This entry was posted in Play by Hong Duan. Bookmark the permalink. [...]

  14. 瓶盖er Says:

    请问一下 您说的缓存服务器不会缓存POST请求返回内容是什么意思 我想得到我们图书馆登陆后的页面信息,用的post,可是得不到想要的结果,总是得到 此请求需要数据缓冲以便成功进行身份验证或重定向 这根你说的缓存有关系吗

  15. post和get请求方式以及区别 | 侯三儿 Says:

    [...] 通过上面概念的理解,我们很容易发现,GET是用于信息获取或查询的,这就意味着它是幂等的(对幂等的解释参见http://www.yining.org/2010/05/04/http-get-vs-post-and-thoughts/),POST可能会改变服务器上的资源请求。 [...]

  16. GET、POST | 2012,一路同程 Says:

    [...] 文章来源http://www.yining.org/2010/05/04/http-get-vs-post-and-thoughts/ [...]

Leave a Reply