http Form表单的Get和 Post请求深入分析
个人博客地址 http://blog.csdn.net/nndtdx
这个话提已经开始了好久,一直没有写。今天提出来,就把这个问题给深入的分析一下。
这里,我使用Fiddler跟踪表单的提交过程。探究一下Get方式提交和Post方式提交的差别究竟在哪里。
首先建立一个页面,该页面实现表单的基本提交。在测试中使用GET方式提交。
该页面编码如下
<body>
<form method="get"action="target.html" name="form">
<inputtype="hidden" name="op" value="hello"/>
<inputtype="checkbox" name="chkName"value="chkValue">
<inputtype="txt" name="txtname">
<ahref="#" onclick="form.submit()">GET方式提交</a>
</form>
</body>
这里使用的是a标签的提交,调用了js方法进行表单提交。
我们先看一下请求该页面本身的情况。
使用Fiddler抓包得到的数据如下
GEThttp://218.196.204.43:8081/HttpStudy/httpstudy.html HTTP/1.1
Host:218.196.204.43:8081
Proxy-Connection:keep-alive
Cache-Control:max-age=0
Proxy-Authorization:Basic Y2p0OmNoZW5namluZ3RhbzEyMy0=
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko)Chrome/14.0.835.202 Safari/535.1
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding:gzip,deflate,sdch
Accept-Language:zh-CN,zh;q=0.8
Accept-Charset:GBK,utf-8;q=0.7,*;q=0.3
If-None-Match:"0e412bb787cc1:0"
If-Modified-Since:Mon, 10 Oct 2011 04:47:36 GMT
看得出来,这是http协议的请求头http reqest header,这里边包含里request header 的各种字段。不同的字段代表不同的含义。如果你要想深入理解各个字段的含义,你可以在这里http://www.w3.org/Protocols/HTTP/HTRQ_Headers.html找到他。其实常用的不算多,等你需要了解某一个时再去查效果可能更好,因为看那些东西毕竟枯燥而空洞。这里,我是使用了代理上网的,所以会有Proxy 相关字段。
对于该次学习本身,客户端只是对http://218.196.204.43:8081/HttpStudy/httpstudy.html页面发出了 get 请求。ok,我们现在点击连接提交一下表单试一下。(我勾选上了chkbox在txt中填入中国)
GEThttp://218.196.204.43:8081/HttpStudy/target.html?op=hello&chkName=chkValue&txtname=%E4%B8%AD%E5%9B%BDHTTP/1.1
Host:218.196.204.43:8081
Proxy-Connection:keep-alive
Proxy-Authorization:Basic Y2p0OmNoZW5namluZ3RhbzEyMy0=
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko)Chrome/14.0.835.202 Safari/535.1
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Referer:http://218.196.204.43:8081/HttpStudy/httpstudy.html
Accept-Encoding:gzip,deflate,sdch
Accept-Language:zh-CN,zh;q=0.8
Accept-Charset:GBK,utf-8;q=0.7,*;q=0.3
同样,第一个页面向服务端发起了get请求。请求的地址是http://218.196.204.43:8081/HttpStudy/target.html?op=hello&chkName=chkValue&txtname=%E4%B8%AD%E5%9B%BD 这个地址中含有请求的目标页面,以及请求时附带的信息。这些信息的组织是很有规律的。可以看出来,是以表单中的各个控件的name=value& 的格式组织的 。这样就将表单中的数据提交给服务器的某一个页面target.html,那么该目标页面就会进行相应的处理,返回一定的结果给客户端。在整个过程中请求实体都是空的。
上边,我们使用a标签进行的提交,此种情况下,并不会将a表签的信息提交进去。下边是我在a标签下加了一个submit类型的input ,点击后的提交url
http://218.196.204.43:8081/HttpStudy/target.html?op=hello&chkName=on&txtname=&btnName=submit
我把chkbox的value值也去掉了。
可以看出,chkbox的传递的值是on,按钮也将自己的value值传了进去。Txtbox为空,没有填写任何内容。
当我没有选择chkbox时,该url中并没有传递该参数。
到目前为止,我们已经基本能够确定了,Form表单的get提交,将会将表单内部的控件以name=value并且以&为连接形成数据信息放在url中,提交到服务器。
接下来,我们看一下Post方式的提交
同样是上述代码,将Get改为post
<body>
<form method="post"action="target.html" name="form">
<input type="hidden" name="op"value="hello"/>
<input type="checkbox"name="chkName">
<input type="txt"name="txtname">
<a href="#" onclick="form.submit()">Post方式提交</a>
<input type="submit"name="btnName" value="submit"/>
</form>
</body>
这样直接点击按钮会出现一个406错误,不允许用于访问此页的 HTTP 谓词。原因是html页面本身是 不可执行的(post方式提交本意是让服务器接受数据后,进行处理)所以,出先错误。我们在建立一个target.aspx页面,里边什么都不写,只用来接受数据。
Ok,修改后的代码如下。
<body>
<formmethod="post" action="target.aspx"name="form">
<input type="hidden"name="op" value="hello"/>
<input type="checkbox"name="chkName">
<input type="txt"name="txtname">
<a href="#" onclick="form.submit()">POST方式提交</a>
<input type="submit"name="btnName" value="submit"/>
</form>
</body>
点击提交按钮,查看fiddler捕捉到信息如下
POSThttp://218.196.204.43:8081/HttpStudy/target.aspx HTTP/1.1
Host:218.196.204.43:8081
Proxy-Connection:keep-alive
Content-Length:48
Cache-Control:max-age=0
Proxy-Authorization:Basic Y2p0OmNoZW5namluZ3RhbzEyMy0=
Origin:http://218.196.204.43:8081
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko)Chrome/14.0.835.202 Safari/535.1
Content-Type:application/x-www-form-urlencoded
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Referer:http://218.196.204.43:8081/HttpStudy/httpstudy.html
Accept-Encoding:gzip,deflate,sdch
Accept-Language:zh-CN,zh;q=0.8
Accept-Charset:GBK,utf-8;q=0.7,*;q=0.3
op=hello&chkName=on&txtname=hahah&btnName=submit
可以看出,客户端向 http://218.196.204.43:8081/HttpStudy/target.aspx页面进行了数据提交。Content-length字段表明了提交内容的长度。request header 下空一行的部分是request entity。可以看出它的内容组织方式。
op=hello&chkName=on&txtname=hahah&btnName=submit和刚才的get方式提交的数据格式是一致的。
综上,get和post提交时数据存储的位置不相同,前者在url中,后者在请求的实体中保存。数据的组织格式相同,都是将当前form标签中的各个控件的状态传给服务器,即name=value的形式。
其实,就协议本身来讲,get方式的提交是安全的,他只是向服务器去获取数据,服务器并会由于该次请求而对服务器的数据产生具有影响性的操作。即get是只读的。而post 是客户端向服务器提交数据,服务器获取该数据后,要对服务器上的数据进行处理,进行一系列的操作,不是安全的。而二者提交时数据存放的位置不尽相同。前者,存放在url后者在entity中,协议本身并没有对该部分的数据量进行限制,但是大多数web服务器,浏览器,都对url的长度有限制,这样就导致了get方式提交数据时数据数据量有限的情况。或许,我们应该换一种说法,get方式是请求数据,post更像是提交数据。
你可能会想,如果这样的话,就目前的web设计来说,岂不是很多都违背了get的只读特性?。嗯,对没错,就是这样,至少我这么认为。当前的设计不符合协议设计者当初的意图。客户端提交的方式有很多种,这里不再依依列举,我也只是对当前的get和post做了研究,其他了解不多,很多web技术目前也仅是支持get和post两种提交。
下边附上向百度框输入hello word时的fiddler数据捕捉情况。
GEThttp://www.baidu.com/s?wd=helloworld&rsv_bp=0&rsv_spt=3&n=2&inputT=1314HTTP/1.1
Host:www.baidu.com
Proxy-Connection:keep-alive
Proxy-Authorization:Basic Y2p0OmNoZW5namluZ3RhbzEyMy0=
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko)Chrome/14.0.835.202 Safari/535.1
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Referer:http://www.baidu.com/
Accept-Encoding:gzip,deflate,sdch
Accept-Language:zh-CN,zh;q=0.8
Accept-Charset:GBK,utf-8;q=0.7,*;q=0.3
Cookie://很长不再粘贴
<!DOCTYPEhtml><!--STATUS OK--><html><head>
<metahttp-equiv="X-UA-Compatible" content="IE=7">
<metahttp-equiv="content-type"content="text/html;charset=gb2312">
<title>百度搜索_helloworld </title>
//页面的html内容。。。
可以看出来entity中保存了该页面的响应内容,该响应内容返回给客户端,客户端接受解析,在浏览器中显示。
Ok,这个话题就暂时探究到这里,在接下来,会学习一下ASP.NET的数据提交。