如果有人问你,GET和POST,有什么区别?你会如何回答?
我的经历
电话面试的时候相当于每次必问的题目,不能不会啊,第一次不会就算了,没想到第二次也栽了!
我的回答:
1. GET使用URL或Cookie传参。而POST将数据放在BODY中。
2. GET的URL会有长度上的限制,则POST的数据则可以非常大。
3. POST比GET安全,因为数据在地址栏上不可见。
这是最普遍的答案,也是我见过最多的答案,可是面试官依旧说就这些区别吗?由于没有研究RFC文档和HTML中的form对于提交方法的描述,所以很是心虚。整个过程中面试官提出的问题都是具有高难度的问题,没有深入了解根本回答不上来。
所以总结一下这个问题:本文都是根据http1.1版本(http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.3)
GET和POST与数据如何传递的关系
GET:
GET方法意思是获取被请求URI(Request-URI)指定的信息(以实体的格式)。如果请求URI涉及到一个数据生成过程,那么这个过程生成的数据应该被作为实体在响应中返回而不是过程的源文本,除非源文本恰好是过程的输出。
如果请求消息包含If-Modified-Since,,If-Unmodified-Since,If-Match,If-None-Match 或者If-Range头域,GET的语义将变成“条(conditionall)GET”。一个条件GET方法会请求满足条件头域的实体。条件GET方法的目的是为了减少不必要的网络使用,这通过允许利用缓存里仍然保鲜的实体而不用多次请求或传输客户端已经拥有的实体来实现的。.
如果请求方法包含一个Range头域,那么GET方法就变成“部分Get”(partial GET)方法。一个部分GET会请求实体的一部分,这在14.35节里描述了。部分GET方法的目的是为了减少不必要的网络使用,可以允许客户端从服务器获取实体的部分数据,而不需要获取客户端本地已经拥有的部分实体数据。
GET请求的响应是可缓存的(cacheable)如果此响应满足第13节HTTP缓存的要求。看15.1.3节关于GET请求用于表单时安全考虑。
HEAD:
HEAD 方法和GET 方法一致,除了服务器不能在响应里返回消息主体。HEAD请求响应里HTTP头域里的元信息(译注:元信息就是头域信息)应该和GET请求响应里的元信息一致。此方法被用来获取请求实体的元信息而不需要传输实体主体(entity-body)。此方法经常被用来测试超文本链接的有效性,可访问性,和最近的改变。.
HEAD请求的响应是可缓存的,因为响应里的信息可能被缓存用于更新以前那个资源对应缓存的实体.。如果出现一个新的域值指明缓存的实体和当前源服务器上的实体有所不同(可能因为Content-Length,Content-MD5,ETag或Last-Modified值的改变),那么缓存(cache)必须认为缓存项是过时的(stale)。
POST:
POST 方法被用于请求源服务器接受请求中的实体作为请求资源的一个新的从属物。POST被设计涵盖下面的功能。
--已存在的资源的注释;
--发布消息给一个布告板,新闻组,邮件列表,或者相似的文章组。
--提供一个数据块,如提交一个表单给一个数据处理过程。
--通过追加操作来扩展数据库。
POST方法的实际功能是由服务器决定的,并且经常依赖于请求URI(Request-URI)。POST
提交的实体是请求URI的从属物,就好像一个文件从属于一个目录,一篇新闻文章从属于一个新闻组,或者一条记录从属于一个数据库。
POST方法执行的动作可能不会对请求URI所指的资源起作用。在这种情况下,200(成功)或者204(没有内容)将是适合的响应状态,这依赖于响应是否包含一个描述结果的实体。
如果资源被源服务器创建,响应应该是201(Created)并且包含一个实体,此实体描述了请求的状态。并且引用了这个新资源和一个Location头域(见14.30节)。
POST方法的响应是不可缓存的。除非响应里有合适的Cache-Control或者Expires头域。然而,303(见其他)响应能被用户代理利用去获得可缓存的响应。
POST 请求必须遵循8.2节里指明的消息传送的要求。
参见15.1.3节关于安全性的考虑.
原文如下:
The POST method isused to request that the origin server accept the entity enclosed in therequest as a new subordinate of the resource identified by the Request-URI inthe Request-Line. POST is designed to allow a uniform method to cover thefollowing functions:
-Annotation of existing resources;
-Posting a message to a bulletin board, newsgroup, mailing list,
or similar group of articles;
-Providing a block of data, such as the result of submitting a
form, to a data-handling process;
-Extending a database through an append operation.
The actualfunction performed by the POST method is determined by the server and isusually dependent on the Request-URI. The posted entity is subordinate to thatURI in the same way that a file is subordinate to a directory containing it, anews article is subordinate to a newsgroup to which it is posted, or a record issubordinate to a database.
The actionperformed by the POST method might not result in a resource that can beidentified by a URI. In this case, either 200 (OK) or 204 (No Content) is theappropriate response status, depending on whether or not the response includesan entity that describes the result.
If a resource hasbeen created on the origin server, the response SHOULD be 201 (Created) andcontain an entity which describes the status of the request and refers to thenew resource, and a Location header (see section 14.30).
Responses to thismethod are not cacheable, unless the response includes appropriateCache-Control or Expires header fields. However, the 303 (See Other) responsecan be used to direct the user agent to retrieve a cacheable resource.
POST requests MUSTobey the message transmission requirements set out in section 8.2.
See section 15.1.3 for securityconsiderations.
PUT
PUT方法请求服务器去把请求里的实体存储在请求URI(Request-URI)标识下。如果请求URI(Request-URI)指定的的资源已经在源服务器上存在,那么此请求里的实体应该被当作是源服务器关于此URI所指定资源实体的最新修改版本。如果请求URI(Request-URI)指定的资源不存在,并且此URI被用户代理定义为一个新资源,那么源服务器就应该根据请求里的实体创建一个此URI所标识下的资源。如果一个新的资源被创建了,源服务器必须能向用户代理(user agent)发送201(已创建)响应。如果已存在的资源被改变了,那么源服务器应该发送200(Ok)或者204(无内容)响应。如果资源不能根据请求URI创建或者改变,一个合适的错误响应应该给出以反应问题的性质。实体的接收者不能忽略任何它不理解和不能实现的Content-*(如:Content-Range)头域,并且必须返回501(没有被实现)响应。如果请求穿过一个缓存(cache),并且此请求URI(Request-URI)指示了一个或多个当前缓存的实体,那么这些实体应该被看作是旧的。PUT方法的响应是不可缓存的。POST方法和PUT方法请求最根本的区别是请求URI(Request-URI)的含义不同。POST请求里的URI 指示一个能处理请求实体的资源(译注:此资源可能是一段程序,如jsp 里的servlet)。此资源可能是一个数据接收过程,一个网关(gateway,译注:网关和代理的区别是:网关可以进行协议转换,而代理不能,只是起代理的作用,比如缓存服务器其实就是一个代理),或者一个单独接收注释的实体。对比而言,PUT方法请求里的URI标识请求里封装的实体一一用户代理知道URI 意指什么,并且服务器不能把此请求应用于其它资源(resource)。如果服务器期望请求被应用于一个不同的URI,那么它必须发送301(永久移动)响应;用户代理可以自己决定是否重定向请求。一个单独的资源可能会被许多不同的URI指定。如:一篇文章可能会有一个URI指定当前版本,而这个URI区别于这篇文章其它特殊版本的URI。这种情况下,对一个通用URI的PUT请求可能会导致其资源的其它URI请求被源服务器重定义。HTTP/1.1没有定义PUT方法对源服务器的状态影响。PUT请求必须遵循8.2节中的消息传送的要求。除非特别指出,PUT方法请求里的实体头域应该被用于资源的创建或修改。
DELETE(删除)
DELETE方法请求源服务器删除请求URI指定的资源。此方法可能会在源服务器上被人为的干涉(或通过其他方法)。客户端不能保证此操作能被执行,即使源服务器返回成功状态码。然而,服务器不应该指明成功除非它打算删除资源或把此资源移到一个不可访问的位置。如果响应里包含描述成功的实体,响应应该是200(OK);如果DELETE动作还没有执行,应该以202(已接受)响应;如果DELETE请求方法已经执行但响应不包含实体,那么应该以204(无内容)响应。如果请求穿过缓存,并且请求URI(Request-URI)指定了一个或多个缓存当前实体,那么这些缓存项应该被认为是旧的。DELETE方法的响应是不能被缓存的。
TRACE
TRACE方法被用于激发一个远程的,应用层的请求消息回路(译注:TRACE方法让客户端测试到服务器的网络通路,回路的意思如发送一个请返回一个响应,这就是一个请求响应回路,)。最后的接收者也许是源服务器,也许是接收到包含Max-Forwards头域值为0请求的代理或网关。TRACE请求不能包含一个实体。TRACE方法允许客户端去了解数据被请求链的另一端接收的情况,并且利用那些数据信息去测试或诊断。Via头域值(见14.45)有特殊的用途,因为它可以作为请求链的跟踪信息。利用Max-Forwards头域允许客户端限制请求链的长度,这是非常有用的,因为可以利用此去测试代理链在无限循环里转发消息。
如果请求是有效的,响应应该在实体主体里包含整个请求消息,并且响应应该包含一个
Content-Type头域值为”message/http”的头域。此方法的响应不能被缓存。
CONNECT(连接)
HTTP1.1 协议规范保留了CONNECT方法,此方法是为了能用于能动态切换到隧道的代理
HTML标准中对get和post的使用的规定:
17.13 Formsubmission
The following sections explain how user agents submit formdata to form processing agents.
17.13.1 Form submissionmethod
The method attribute of the FORM element specifies the HTTP method used to send the form tothe processing agent. This attribute may take two values:
- get: With the HTTP "get" method, the form data set is appended to the URI specified by the action attribute (with a question-mark ("?") as separator) and this new URI is sent to the processing agent.
- post: With the HTTP "post" method, the form data set is included in the body of the form and sent to the processing agent.
The "get" method should be used when the form isidempotent (i.e., causes no side-effects). Many database searches have novisible side-effects and make ideal applications for the "get"method.
If the service associated with the processing of a formcauses side effects (for example, if the form modifies a database orsubscription to a service), the "post" method should be used.
Note. The"get" method restricts form data set values to ASCIIcharacters. Only the "post" method (with enctype="multipart/form-data")is specified to cover the entire [ISO10646] character set.
HTTP协议对GET和POST都没有对长度的限制
HTTP协议明确地指出了,HTTP头和Body都没有长度的要求。而对于URL长度上的限制,有两方面的原因造成:
1. 浏览器。据说早期的浏览器会对URL长度做限制。据说IE对URL长度会限制在2048个字符内(流传很广,而且无数同事都表示认同)。但我自己试了一下,我构造了90K的URL通过IE9访问live.com,是正常的。网上的东西,哪怕是Wikipedia上的,也不能信。
2. 服务器。URL长了,对服务器处理也是一种负担。原本一个会话就没有多少数据,现在如果有人恶意地构造几个几M大小的URL,并不停地访问你的服务器。服务器的最大并发数显然会下降。另一种攻击方式是,把告诉服务器Content-Length是一个很大的数,然后只给服务器发一点儿数据,嘿嘿,服务器你就傻等着去吧。哪怕你有超时设置,这种故意的次次访问超时也能让服务器吃不了兜着走。有鉴于此,多数服务器出于安全啦、稳定啦方面的考虑,会给URL长度加限制。但是这个限制是针对所有HTTP请求的,与GET、POST没有关系。
安全不安全和GET、POST没有关系
我觉得这真是中国特色。我讲个小段子,大家应该可以体会出这个说法多么的可笑。
觉得POST数据比GET数据安全的人会说
“防君子不防小人;中国小白多,能防小白用户就行了。”
“哼,”我不以为然,“那你怎么不说,URL参数都Encode过了,或是Base64一下,小白也看不懂啊。”
那人反驳道,“Encode太简单了,聪明点儿的小白很容易就可以Decode并修改掉。”
我笑道,“五十步笑百步耳,再聪明点儿的小白还会截包并重发呢,Opera就有这功能。”
那人阴险地祭出神器——最终解释权,说,“这个不算小白。”
我日啊。
1. get是从服务器上获取数据,post是向服务器传送数据。
2.get是把参数数据队列加到提交表单的ACTION属性所指的URI中,值和表单内各个字段一一对应,在URI中可以看到。post是通过HTTP post机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程。
3. 对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Request.Form获取提交的数据。
4.get传送的数据量较小。post传送的数据量较大,一般被默认为不受限制。5.get安全性非常低,post安全性较高。但是执行效率却比Post方法好。
对于安全性的定义,http协议的解释是这样的:
Authors ofservices which use the HTTP protocol SHOULD NOT use GET based forms for thesubmission of sensitive data, because this will cause this data to be encodedin the Request-URI. Many existing servers, proxies, and user agents will logthe request URI in some place where it might be visible to third parties.Servers can use POST-based form submission instead.