• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            woaidongmao

            文章均收錄自他人博客,但不喜標(biāo)題前加-[轉(zhuǎn)貼],因其丑陋,見(jiàn)諒!~
            隨筆 - 1469, 文章 - 0, 評(píng)論 - 661, 引用 - 0
            數(shù)據(jù)加載中……

            理解HTTP消息頭

            一)初識(shí)HTTP消息頭

            但凡搞WEB開(kāi)發(fā)的人都離不開(kāi)HTTP(超文本傳輸協(xié)議),而要了解HTTP,除了HTML本身以外,還有一部分不可忽視的就是HTTP消息頭。
            做過(guò)Socket編程的人都知道,當(dāng)我們?cè)O(shè)計(jì)一個(gè)通信協(xié)議時(shí),“消息頭/消息體”的分割方式是很常用的,消息頭告訴對(duì)方這個(gè)消息是干什么的,消息體告訴對(duì)方怎么干。HTTP傳輸?shù)南⒁彩沁@樣規(guī)定的,每一個(gè)HTTP包都分為HTTP頭和HTTP體兩部分,后者是可選的,而前者是必須的。每當(dāng)我們打開(kāi)一個(gè)網(wǎng)頁(yè),在上面點(diǎn)擊右鍵,選擇“查看源文件”,這時(shí)看到的HTML代碼就是HTTP的消息體,那么消息頭又在哪呢?IE瀏覽器不讓我們看到這部分,但我們可以 通過(guò)截取數(shù)據(jù)包等方法看到它。
            下面就來(lái)看一個(gè)簡(jiǎn)單的例子:
            首先制作一個(gè)非常簡(jiǎn)單的網(wǎng)頁(yè),它的內(nèi)容只有一行:
            <html><body>hello world</body></html>
            把它放到WEB服務(wù)器上,比如IIS,然后用IE瀏覽器請(qǐng)求這個(gè)頁(yè)面(http://localhost:8080/simple.htm),當(dāng)我們請(qǐng)求這個(gè)頁(yè)面時(shí),瀏覽器實(shí)際做了以下四項(xiàng)工作:
            1 解析我們輸入的地址,從中分解出協(xié)議名、主機(jī)名、端口、對(duì)象路徑等部分,對(duì)于我們的這個(gè)地址,解析得到的結(jié)果如下:
            協(xié)議名:http
            主機(jī)名:localhost
            端口:8080
            對(duì)象路徑:/simple.htm
            2 把以上部分結(jié)合本機(jī)自己的信息,封裝成一個(gè)HTTP請(qǐng)求數(shù)據(jù)包
            3 使用TCP協(xié)議連接到主機(jī)的指定端口(localhost, 8080),并發(fā)送已封裝好的數(shù)據(jù)包
            4 等待服務(wù)器返回?cái)?shù)據(jù),并解析返回?cái)?shù)據(jù),最后顯示出來(lái)
            由截取到的數(shù)據(jù)包我們不難發(fā)現(xiàn)瀏覽器生成的HTTP數(shù)據(jù)包的內(nèi)容如下:
            GET /simple.htm HTTP/1.1<CR>
            Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*<CR>
            Accept-Language: zh-cn<CR>
            Accept-Encoding: gzip, deflate<CR>
            User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)<CR>
            Host: localhost:8080<CR>
            Connection: Keep-Alive<CR>
            <CR>
            為了顯示清楚我把所有的回車的地方都加上了“<CR>”,注意最后還有一個(gè)空行加一個(gè)回車,這個(gè)空行正是HTTP規(guī)定的消息頭和消息體的分界線,第一個(gè)空行以下的內(nèi)容就是消息體,這個(gè)請(qǐng)求數(shù)據(jù)包是沒(méi)有消息體的。
            消息的第一行“GET”表示我們所使用的HTTP動(dòng)作,其他可能的還有“POST”等,GET的消息沒(méi)有消息體,而POST消息是有消息體的,消息體的內(nèi)容就是要POST的數(shù)據(jù)。后面/simple.htm就是我們要請(qǐng)求的對(duì)象,之后HTTP1.1表示使用的是HTTP1.1協(xié)議。
            第二行表示我們所用的瀏覽器能接受的Content-type,三四兩行則是語(yǔ)言和編碼信息,第五行顯示出本機(jī)的相關(guān)系信息,包括瀏覽器類型、操作系統(tǒng)信息等,很多網(wǎng)站可以顯示出你所使用的瀏覽器和操作系統(tǒng)版本,就是因?yàn)榭梢詮倪@里獲取到這些信息。
            第六行表示我們所請(qǐng)求的主機(jī)和端口,第七行表示使用Keep-Alive方式,即數(shù)據(jù)傳遞完并不立即關(guān)閉連接。
            服務(wù)器接收到這樣的數(shù)據(jù)包以后會(huì)根據(jù)其內(nèi)容做相應(yīng)的處理,例如查找有沒(méi)有“/simple.htm”這個(gè)對(duì)象,如果有,根據(jù)服務(wù)器的設(shè)置來(lái)決定如何處理,如果是HTM,則不需要什么復(fù)雜的處理,直接返回其內(nèi)容即可。但在直接返回之前,還需要加上HTTP消息頭。
            服務(wù)器發(fā)回的完整HTTP消息如下:
            HTTP/1.1 200 OK<CR>
            Server: Microsoft-IIS/5.1<CR>
            X-Powered-By: ASP.NET<CR>
            Date: Fri, 03 Mar 2006 06:34:03 GMT<CR>
            Content-Type: text/html<CR>
            Accept-Ranges: bytes<CR>
            Last-Modified: Fri, 03 Mar 2006 06:33:18 GMT<CR>
            ETag: "5ca4f75b8c3ec61:9ee"<CR>
            Content-Length: 37<CR>
            <CR>
            <html><body>hello world</body></html>
            同樣,我用“<CR>”來(lái)表示回車。可以看到,這個(gè)消息也是用空行切分成消息頭和消息體兩部分,消息體的部分正是我們前面寫好的HTML代碼。
            消息頭第一行“HTTP/1.1”也是表示所使用的協(xié)議,后面的“200 OK”是HTTP返回代碼,200就表示操作成功,還有其他常見(jiàn)的如404表示對(duì)象未找到,500表示服務(wù)器錯(cuò)誤,403表示不能瀏覽目錄等等。
            第二行表示這個(gè)服務(wù)器使用的WEB服務(wù)器軟件,這里是IIS 5.1。第三行是ASP.Net的一個(gè)附加提示,沒(méi)什么實(shí)際用處。第四行是處理此請(qǐng)求的時(shí)間。第五行就是所返回的消息的content-type,瀏覽器 會(huì)根據(jù)它來(lái)決定如何處理消息體里面的內(nèi)容,例如這里是text/html,那么瀏覽器就會(huì)啟用HTML解析器來(lái)處理它,如果是image/jpeg,那么 就會(huì)使用JPEG的解碼器來(lái)處理。
            消息頭最后一行“Content-Length”表示消息體的長(zhǎng)度,從空行以后的內(nèi)容算起,以字節(jié)為單位,瀏覽器接收到它所指定的字節(jié)數(shù)的內(nèi)容以后就會(huì)認(rèn)為這個(gè)消息已經(jīng)被完整接收了。

            理解HTTP消息頭 (二)

            常見(jiàn)的HTTP返回碼

            上一篇文章里我簡(jiǎn)要的說(shuō)了說(shuō)HTTP消息頭的格式,注意到在服務(wù)器返回的HTTP消息頭里有一個(gè)“HTTP/1.1 200 OK”,這里的200是HTTP規(guī)定的返回代碼,表示請(qǐng)求已經(jīng)被正常處理完成。瀏覽器通過(guò)這個(gè)返回代碼就可以知道服務(wù)器對(duì)所發(fā)請(qǐng)求的處理情況是什么,每一種返回代碼都有自己的含義。這里列舉幾種常見(jiàn)的返回碼。

            1 403 Access Forbidden

            如果我們?cè)噲D請(qǐng)求服務(wù)器上一個(gè)文件夾,而在WEB服務(wù)器上這個(gè)文件夾并沒(méi)有允許對(duì)這個(gè)文件夾列目錄的話,就會(huì)返回這個(gè)代碼。一個(gè)完整的403回復(fù)可能是這樣的:(IIS5.1)
            HTTP/1.1 403 Access Forbidden
            Server: Microsoft-IIS/5.1
            Date: Mon, 06 Mar 2006 08:57:39 GMT
            Connection: close
            Content-Type: text/html
            Content-Length: 172

            <html><head><title>Directory Listing Denied</title></head>
            <body><h1>Directory Listing Denied</h1>This Virtual Directory does not allow contents to be listed.</body></html>

            2 404 Object not found

            當(dāng)我們請(qǐng)求的對(duì)象在服務(wù)器上并不存在時(shí),就會(huì)給出這個(gè)返回代碼,這可能也是最常見(jiàn)的錯(cuò)誤代碼了。IIS給出的404消息內(nèi)容很長(zhǎng),除了消息頭以外還有一個(gè)完整的說(shuō)明“為什么會(huì)這樣”的網(wǎng)頁(yè)。APACHE服務(wù)器的404消息比較簡(jiǎn)短,如下:
            HTTP/1.1 404 Not Found
            Date: Mon, 06 Mar 2006 09:03:14 GMT
            Server: Apache/2.0.55 (Unix) PHP/5.0.5
            Content-Length: 291
            Keep-Alive: timeout=15, max=100
            Connection: Keep-Alive
            Content-Type: text/html; charset=iso-8859-1

            <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
            <html><head>
            <title>404 Not Found</title>
            </head><body>
            <h1>Not Found</h1>
            <p>The requested URL /notexist was not found on this server.</p>
            <hr>
            <address>Apache/2.0.55 (Unix) PHP/5.0.5 Server at localhost Port 8080</address>
            </body></html>

            也許你會(huì)問(wèn),無(wú)論是404還是200,都會(huì)在消息體內(nèi)給出一個(gè)說(shuō)明網(wǎng)頁(yè),那么對(duì)于客戶端來(lái)說(shuō)二者有什么區(qū)別呢?一個(gè)比較明顯的區(qū)別在于200是 成功請(qǐng)求,瀏覽器會(huì)記錄下這個(gè)地址,以便下次再訪問(wèn)時(shí)可以自動(dòng)提示該地址,而404是失敗請(qǐng)求,瀏覽器只會(huì)顯示出返回的頁(yè)面內(nèi)容,并不會(huì)記錄此地址,要再次訪問(wèn)時(shí)還需要輸入完整的地址。

            3 401 Access Denied

            當(dāng)WEB服務(wù)器不允許匿名訪問(wèn),而我們又沒(méi)有提供正確的用戶名/密碼時(shí),服務(wù)器就會(huì)給出這個(gè)返回代碼。在IIS中,設(shè)置IIS的安全屬性為不允許匿名訪問(wèn)(如下圖),此時(shí)直接訪問(wèn)的話就會(huì)得到以下返回結(jié)果:

            clip_image001
            HTTP/1.1 401 Access Denied
            Server: Microsoft-IIS/5.1
            Date: Mon, 06 Mar 2006 09:15:55 GMT
            WWW-Authenticate: Negotiate
            WWW-Authenticate: NTLM
            Connection: close
            Content-Length: 3964
            Content-Type: text/html

            <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
            <html dir=ltr>
            ……
            此時(shí)瀏覽器上給出的提示如下圖,讓我們輸入用戶名和密碼:

            clip_image001[1]

            因返回信息中消息體較長(zhǎng),只取前面兩行內(nèi)容。注意,如果是用localhost來(lái)訪問(wèn)本機(jī)的IIS,因IE可以直接取得當(dāng)前用戶的身份,它會(huì)和服務(wù)器間直接進(jìn)行協(xié)商,所以不會(huì)看到401提示。
            當(dāng)我們?cè)谳斎肓擞脩裘兔艽a以后,服務(wù)器與客戶端會(huì)再進(jìn)行兩次對(duì)話。首先客戶端向服務(wù)器索取一個(gè)公鑰,服務(wù)器端會(huì)返回一個(gè)公鑰,二者都用BASE64編碼,相應(yīng)的消息如下(編碼部分已經(jīng)做了處理):

            GET / HTTP/1.1
            Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
            Accept-Language: zh-cn
            Accept-Encoding: gzip, deflate
            User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
            Host: 192.168.0.55:8080
            Connection: Keep-Alive
            Authorization: Negotiate ABCDEFG……

            HTTP/1.1 401 Access Denied
            Server: Microsoft-IIS/5.1
            Date: Mon, 06 Mar 2006 09:20:53 GMT
            WWW-Authenticate: Negotiate HIJKLMN……
            Content-Length: 3715
            Content-Type: text/html

            <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
            <html dir=ltr>
            ……
            客戶端拿到公鑰之后使用公鑰對(duì)用戶名和密碼進(jìn)行加密碼,然后把加密以后的結(jié)果重新發(fā)給服務(wù)器:
            GET / HTTP/1.1
            Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
            Accept-Language: zh-cn
            Accept-Encoding: gzip, deflate
            User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
            Host: 192.168.0.55:8080
            Connection: Keep-Alive
            Authorization: Negotiate OPQRST……

            這樣,如果驗(yàn)證通過(guò),服務(wù)器端就會(huì)把請(qǐng)求的內(nèi)容發(fā)送過(guò)來(lái)了,也就是說(shuō)禁止匿名訪問(wèn)的網(wǎng)站會(huì)經(jīng)過(guò)三次請(qǐng)求才可以看到頁(yè)面。但因?yàn)榭蛻舳藶g覽器已經(jīng)緩存了公鑰,用同一個(gè)瀏覽器窗口再次請(qǐng)求這個(gè)網(wǎng)站上的其它頁(yè)面時(shí)就可以直接發(fā)送驗(yàn)證信息,從而一次交互就可以完成了。

            4 302 Object Moved

            用過(guò)ASP的人都知道ASP中頁(yè)面重定向至少有Redirect和Transfer兩種方法。二的區(qū)別在于Redirect是客戶端重定向,而Transfer是服務(wù)器端重定向,那么它們具體是如何通過(guò)HTTP消息頭實(shí)現(xiàn)的呢?
            先來(lái)看一下Transfer的例子:
            例如ASP文件1.asp只有一行
            <% Server.Transfer "1.htm" %>
            HTML文件1.htm也只有一行:
            <p>this is 1.htm</p>
            如果我們從瀏覽器里請(qǐng)求1.asp,發(fā)送的請(qǐng)求是:
            GET /1.asp HTTP/1.1
            Accept: */*
            Accept-Language: zh-cn
            Accept-Encoding: gzip, deflate
            User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
            Host: localhost:8080
            Connection: Keep-Alive
            Cookie: ASPSESSIONIDACCTRTTT=PKKDJOPBAKMAMBNANIPIFDAP

            注意請(qǐng)求的文件確實(shí)是1.asp,而得到的回應(yīng)則是:
            HTTP/1.1 200 OK
            Server: Microsoft-IIS/5.1
            Date: Mon, 06 Mar 2006 12:52:44 GMT
            X-Powered-By: ASP.NET
            Content-Length: 20
            Content-Type: text/html
            Cache-control: private

            <p>this is 1.htm</p>
            不難看出,通過(guò)Server.Transfer語(yǔ)句服務(wù)器端已經(jīng)做了頁(yè)面重定向,而客戶端對(duì)此一無(wú)所知,表面上看上去得到的就是1.asp的結(jié)果。
            如果把1.asp的內(nèi)容改為:
            <% Response.Redirect "1.htm" %>
            再次請(qǐng)求1.asp,發(fā)送的請(qǐng)求沒(méi)有變化,得到的回應(yīng)卻變成了:
            HTTP/1.1 302 Object moved
            Server: Microsoft-IIS/5.1
            Date: Mon, 06 Mar 2006 12:55:57 GMT
            X-Powered-By: ASP.NET
            Location: 1.htm
            Content-Length: 121
            Content-Type: text/html
            Cache-control: private

            <head><title>Object moved</title></head>
            <body><h1>Object Moved</h1>This object may be found <a HREF="">here</a>.</body>

            注意HTTP的返回代碼由200變成了302,表示這是一個(gè)重定向消息,客戶端需要根據(jù)消息頭中Location字段的值重新發(fā)送請(qǐng)求,于是就有了下面一組對(duì)話:
            GET /1.htm HTTP/1.1
            Accept: */*
            Accept-Language: zh-cn
            Accept-Encoding: gzip, deflate
            User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
            Host: localhost:8080
            Connection: Keep-Alive
            If-Modified-Since: Thu, 02 Mar 2006 06:50:13 GMT
            If-None-Match: "b224758ec53dc61:9f0"
            Cookie: ASPSESSIONIDACCTRTTT=PKKDJOPBAKMAMBNANIPIFDAP

            HTTP/1.1 200 OK
            Server: Microsoft-IIS/5.1
            X-Powered-By: ASP.NET
            Date: Mon, 06 Mar 2006 12:55:57 GMT
            Content-Type: text/html
            Accept-Ranges: bytes
            Last-Modified: Mon, 06 Mar 2006 12:52:32 GMT
            ETag: "76d85bd51c41c61:9f0"
            Content-Length: 20

            <p>this is 1.htm</p>
            很明顯,兩種重定向方式雖然看上去結(jié)果很像,但在實(shí)現(xiàn)原理上有很大的不同。

            5 500 Internal Server Error

            500號(hào)錯(cuò)誤發(fā)生在服務(wù)器程序有錯(cuò)誤的時(shí)候,例如,ASP程序?yàn)?br><% if %>
            顯然這個(gè)程序并不完整,于是得到的結(jié)果為:
            HTTP/1.1 500 Internal Server Error
            Server: Microsoft-IIS/5.1
            Date: Mon, 06 Mar 2006 12:58:55 GMT
            X-Powered-By: ASP.NET
            Content-Length: 4301
            Content-Type: text/html
            Expires: Mon, 06 Mar 2006 12:58:55 GMT
            Set-Cookie: ASPSESSIONIDACCTRTTT=ALKDJOPBPPKNPCNOEPCNOOPD; path=/
            Cache-control: private

            <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">

            <html dir=ltr>
            ……

            服務(wù)器發(fā)送了500號(hào)錯(cuò)誤,并且后面通過(guò)HTML的方式說(shuō)明了錯(cuò)誤的原因。

            理解HTTP消息頭 (三)

            (三) 客戶端發(fā)送的內(nèi)容
            這一次主要來(lái)觀察HTTP消息頭中客戶端的請(qǐng)求,從中找到一些有意思的內(nèi)容。

            1 HTTP_REFERER
            寫兩個(gè)簡(jiǎn)單的網(wǎng)頁(yè):
            a.htm:
            <a href=b.htm>to page b</a>
            b.htm:
            haha
            內(nèi)容很簡(jiǎn)單,就是網(wǎng)頁(yè)A中有一個(gè)到B的鏈接。把它們放到IIS上,并訪問(wèn)網(wǎng)頁(yè)A,從中再點(diǎn)擊到B的鏈接,于是看到了B頁(yè)的“haha”。那么這兩次請(qǐng)求有什么不同嗎?觀察它們所發(fā)送的HTTP消息頭,最明顯的區(qū)別就是訪問(wèn)B頁(yè)時(shí)比訪問(wèn)A頁(yè)時(shí)多了一行:
            Referer: http://localhost/a.htm
            這一行就表示,用戶要訪問(wèn)的B頁(yè)是從A頁(yè)鏈接過(guò)來(lái)的。
            服務(wù)器端要想取得這個(gè)值也是很容易的,以ASP為例,只需要寫一句
            <% =Request.ServerVariables("HTTP_REFERER") %>
            就可以了。
            一些網(wǎng)站通過(guò)HTTP_REFERER來(lái)做安全驗(yàn)證,判斷用戶是不是從允許的頁(yè)面鏈接來(lái)的,而不是直接從瀏覽器上打URL或從其他頁(yè)面鏈接過(guò)來(lái),這樣可以 從一定程度上防止網(wǎng)頁(yè)被做非法使用。但從上述原理來(lái)看,想要騙過(guò)服務(wù)器也并不困難,只要手工構(gòu)造輸入的HTTP消息頭就可以了,其他常用的手段還有通過(guò) HOSTS文件偽造域名等。
            除了超鏈接以外,還有其他幾種方式會(huì)導(dǎo)致HTTP_REFERER信息被發(fā)送,如:
            內(nèi)聯(lián)框架:<iframe src=b.asp></iframe>
            框架集:<frameset><frame src=b.asp></frameset>
            表單提交:<form action=b.asp><input type=submit></form>
            SCRIPT引用:<script src=b.asp></script>
            CSS引用:<link rel=stylesheet type=text/css href=b.asp>
            XML數(shù)據(jù)島:<xml src=b.asp></xml>

            而以下形式不會(huì)發(fā)送HTTP_REFERER:
            script轉(zhuǎn)向:<script>location.href="b.asp"</script>
            script開(kāi)新窗口:<script>window.open("b.asp");</script>
            META轉(zhuǎn)向:<meta http-equiv="refresh" content="0;URL=b.asp">
            引入圖片:<img src=b.asp>

            2 COOKIE
            COOKIE是大家都非常熟悉的了,通過(guò)它可以在客戶端保存用戶狀態(tài),即使用戶關(guān)閉瀏覽器也能繼續(xù)保存。那么客戶端與服務(wù)器端是如何交換COOKIE信息的呢?沒(méi)錯(cuò),也是通過(guò)HTTP消息頭。
            首先寫一個(gè)簡(jiǎn)單的ASP網(wǎng)頁(yè):
            <%
            Dim i
            i = Request.Cookies("key")
            Response.Write i
            Response.Cookies("key") = "haha"
            Response.Cookies("key").Expires = #2007-1-1#
            %>
            第一次訪問(wèn)此網(wǎng)頁(yè)時(shí),屏幕上一片白,第二次訪問(wèn)時(shí),則會(huì)顯示出“haha”。通過(guò)閱讀程序不難發(fā)現(xiàn),屏幕上顯示的內(nèi)容實(shí)際上是COOKIE 的內(nèi)容,而第一次訪問(wèn)時(shí)還沒(méi)有設(shè)置COOKIE的值,所以不會(huì)有顯示,第二次顯示的是第一次設(shè)置的值。那么對(duì)應(yīng)的HTTP消息頭應(yīng)該是什么樣的呢?
            第一次請(qǐng)求時(shí)沒(méi)什么不同,略過(guò)
            第一次返回時(shí)消息內(nèi)容多了下面這一行:
            Set-Cookie: key=haha; expires=Sun, 31-Dec-2006 16:00:00 GMT; path=/
            很明顯,key=haha表示鍵名為“key”的COOKIE的值為“haha”,后面是這則COOKIE的過(guò)期時(shí)間,因?yàn)槲矣玫闹形牟僮飨到y(tǒng)的時(shí)區(qū)是東八區(qū),2007年1月1日0點(diǎn)對(duì)應(yīng)的GMT時(shí)間就是2006年12月31日16點(diǎn)。
            第二次再訪問(wèn)此網(wǎng)頁(yè)時(shí),發(fā)送的內(nèi)容多了如下一行:
            Cookie: key=haha
            它的內(nèi)容就是剛才設(shè)的COOKIE的內(nèi)容。可見(jiàn),客戶端在從服務(wù)器端得到COOKIE值以后就保存在硬盤上,再次訪問(wèn)時(shí)就會(huì)把它發(fā)送到服務(wù)器。發(fā)送時(shí)并沒(méi)有發(fā)送過(guò)期時(shí)間,因?yàn)榉?wù)器對(duì)過(guò)期時(shí)間并不關(guān)心,當(dāng)COOKIE過(guò)期后瀏覽器就不會(huì)再發(fā)送它了。
            如果使用IE6.0瀏覽器并且禁用COOKIE功能,可以發(fā)現(xiàn)服務(wù)器端的set-cookie還是有的,但客戶端并不會(huì)接受它,也不會(huì)發(fā)送它。有些網(wǎng)站, 特別是在線投票網(wǎng)站通過(guò)記錄COOKIE防止用戶重復(fù)投票,破解很簡(jiǎn)單,只要用IE6瀏覽器并禁用COOKIE就可以了。也有的網(wǎng)站通過(guò)COOKIE值為 某值來(lái)判斷用戶是否合法,這種判斷也非常容易通過(guò)手工構(gòu)造HTTP消息頭來(lái)欺騙,當(dāng)然用HOSTS的方式也是可以欺騙的。

            3 SESSION
            HTTP協(xié)議本身是無(wú)狀態(tài)的,服務(wù)器和客戶端都不保證用戶訪問(wèn)期間連接會(huì)一直保持,事實(shí)上保持連接是HTTP1.1才有的新內(nèi)容,當(dāng)客戶端發(fā)送的消息頭中有“Connection: Keep-Alive” 時(shí)表示客戶端瀏覽器支持保持連接的工作方式,但這個(gè)連接也會(huì)在一段時(shí)間沒(méi)有請(qǐng)求后自動(dòng)斷開(kāi),以節(jié)省服務(wù)器資源。為了在服務(wù)器端維持用戶狀態(tài),SESSION就被發(fā)明出來(lái)了,現(xiàn)在各主流的動(dòng)態(tài)網(wǎng)頁(yè)制做工具都支持SESSION,但支持的方式不完全相同,以下皆以ASP為例。
            當(dāng)用戶請(qǐng)求一個(gè)ASP網(wǎng)頁(yè)時(shí),在返回的HTTP消息頭中會(huì)有一行:
            Set-Cookie: ASPSESSIONIDCSQCRTBS=KOIPGIMBCOCBFMOBENDCAKDP; path=/
            服務(wù)器通過(guò)COOKIE的方式告訴客戶端你的SESSIONID是多少,在這里是“KOIPGIMBCOCBFMOBENDCAKDP”,并且服務(wù)器上保 留了和此SESSIONID相關(guān)的數(shù)據(jù),當(dāng)同一用戶再次發(fā)送請(qǐng)求時(shí),還會(huì)把這個(gè)COOKIE再發(fā)送回去,服務(wù)器端根據(jù)此ID找到此用戶的數(shù)據(jù),也就實(shí)現(xiàn)了 服務(wù)器端用戶狀態(tài)的保存。所以我們用ASP編程時(shí)可以使用“session("name")=user”這樣的方式保存用戶信息。注意此COOKIE內(nèi)容 里并沒(méi)有過(guò)期時(shí)間,這表示這是一個(gè)當(dāng)關(guān)閉瀏覽器時(shí)立即過(guò)期的COOKIE,它不會(huì)被保存到硬盤上。這種工作方式比單純用COOKIE的方式要安全很多,因 為在客戶端并沒(méi)有什么能讓我們修改和欺騙的值,唯一的信息就是SESSIONID,而這個(gè)ID在瀏覽器關(guān)閉時(shí)會(huì)立即失效,除非別人能在你瀏覽網(wǎng)站期間或關(guān)閉瀏覽器后很短時(shí)間內(nèi)知道此ID的值,才能做一些欺騙活動(dòng)。因?yàn)榉?wù)器端判斷SESSION過(guò)期的方式并不是斷開(kāi)連接或關(guān)閉瀏覽器,而是通過(guò)用戶手工結(jié)束 SESSION或等待超時(shí),當(dāng)用戶關(guān)閉瀏覽器后的一段時(shí)間里SESSION還沒(méi)有超時(shí),所以這時(shí)如果知道了剛才的SESSIONID,還是可以欺騙的。因 此最安全的辦法還是在離開(kāi)網(wǎng)站之前手工結(jié)束SESSION,很多網(wǎng)站都提供“Logout”功能,它會(huì)通過(guò)設(shè)置SESSION中的值為已退出狀態(tài)或讓 SESSION立即過(guò)期從而起到安全的目的。
            SESSION和COOKIE的方式各有優(yōu)缺點(diǎn)。SESSION的優(yōu)點(diǎn)是比較安全,不容易被欺騙,缺點(diǎn)是過(guò)期時(shí)間短,如果用過(guò)在超過(guò)過(guò)期時(shí)間里沒(méi)有向服務(wù)器發(fā)送任何信息,就會(huì)被認(rèn)為超過(guò)過(guò)期了;COOKIE則相反,根據(jù)服務(wù)器端設(shè)置的超時(shí)時(shí)間,可以長(zhǎng)時(shí)間保留信息,即使關(guān)機(jī)再開(kāi)機(jī)也可能保留狀態(tài),而安全性自然大打折扣。很多網(wǎng)站都提供兩種驗(yàn)證方式相結(jié)合,如果用戶臨時(shí)用這臺(tái)電腦訪問(wèn)此訪問(wèn)則需要輸入用戶名和密碼,不保存COOKIE;如果用戶使用的是自己的個(gè)人電腦,則可以讓網(wǎng)站在自己硬盤上保留COOKIE,以后訪問(wèn)時(shí)就不需要重新輸入用戶名和密碼了。

            4 POST
            瀏覽器訪問(wèn)服務(wù)器常用的方式有GET和POST兩種,GET方式只發(fā)送HTTP消息頭,沒(méi)有消息體,也就是除了要GET的基本信息之外 不向服務(wù)器提供其他信息,網(wǎng)頁(yè)表單(FROM)的默認(rèn)提交方式就是用GET方式,它會(huì)把所有向服務(wù)器提交的信息都作為URL后面的參數(shù),如 a.asp?a=1&b=2這樣的方式。而當(dāng)要提交的數(shù)據(jù)量很大,或者所提交內(nèi)容不希望別人直接看到時(shí),應(yīng)該使用POST方式。POST方式提交 的數(shù)據(jù)是作為HTTP消息體存在的,例如,寫一個(gè)網(wǎng)頁(yè)表單:
            <form method=post>
            <input type=text name=text1>
            <input type=submit>
            </form>
            訪問(wèn)此網(wǎng)頁(yè),并在表單中填入一個(gè)“haha”,然后提交,可以看到此次提交所發(fā)送的信息如下:
            POST /form.asp HTTP/1.1
            Accept: */*
            Referer: http://localhost:8080/form.asp
            Accept-Language: zh-cn
            Content-Type: application/x-www-form-urlencoded
            Accept-Encoding: gzip, deflate
            User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; InfoPath.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
            Host: localhost:8080
            Content-Length: 10
            Connection: Keep-Alive
            Cache-Control: no-cache
            Cookie: key=haha; ASPSESSIONIDCSQCRTBS=LOIPGIMBLMNOGCOBOMPJBOKP

            text1=haha
            前面關(guān)鍵字從“GET”變?yōu)榱?#8220;POST”,Content-Type變成了“application/x-www-form- urlencoded”,后面內(nèi)容并無(wú)大變化,只是多了一行:Content-Length: 10,表示提交的內(nèi)容的長(zhǎng)度。空行后面是消息體,內(nèi)容就是表單中所填的內(nèi)容。注意此時(shí)發(fā)送的內(nèi)容只是“Name=Value”的形式,表單上其他的信息不 會(huì)被發(fā)送,所以想直接從服務(wù)器端取得list box中所有的list item是辦不到的,除非在提交前用一段script把所有的item內(nèi)容都連在一起放到一個(gè)隱含表單域中。
            如果是用表單上傳文件,情況就要復(fù)雜一些了,首先是表單聲明中要加上一句話:enctype='multipart/form-data',表示這個(gè)表單將提交多段數(shù)據(jù),并用HTML:input type=file來(lái)聲明一個(gè)文件提交域。
            表單內(nèi)容如下:
            <form method=post enctype='multipart/form-data'>
            <input type=text name=text1>
            <input type=file name=file1>
            <input type=submit>
            </form>
            我們?yōu)閠ext1輸入文字:hehe,為file1選擇文件haha.txt,其內(nèi)容為“ABCDEFG”,然后提交此表單。提交的完全信息為:
            POST /form.asp HTTP/1.1
            Accept: */*
            Referer: http://localhost:8080/form.asp
            Accept-Language: zh-cn
            Content-Type: multipart/form-data; boundary=---------------------------7d62bf2f9066c
            Accept-Encoding: gzip, deflate
            User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; InfoPath.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
            Host: localhost:8080
            Content-Length: 337
            Connection: Keep-Alive
            Cache-Control: no-cache
            Cookie: key=haha; ASPSESSIONIDCSQCRTBS=LOIPGIMBLMNOGCOBOMPJBOKP

            -----------------------------7d62bf2f9066c
            Content-Disposition: form-data; name="text1"

            hehe
            -----------------------------7d62bf2f9066c
            Content-Disposition: form-data; name="file1"; filename="H:\Documents and Settings\Administrator\桌面\haha.txt"
            Content-Type: text/plain

            ABCDEFG
            -----------------------------7d62bf2f9066c--

            顯然這個(gè)提交的信息要比前述的復(fù)雜很多。Content-Type變成了“multipart/form-data”,后面還多了一個(gè) boundary,此值是為了區(qū)分POST的內(nèi)容的區(qū)段用的,只要在內(nèi)容中遇到了此值,就表示下面要開(kāi)始一個(gè)新的區(qū)段了,每個(gè)區(qū)段的內(nèi)容相對(duì)獨(dú)立。如果遇 到的是此值后面連著兩個(gè)減號(hào),則表示全部?jī)?nèi)容到此結(jié)束。每個(gè)段也分為段頭和段體兩部分,用空行隔開(kāi),每段都有自己的類型和相關(guān)信息。如第一區(qū)段是 text1的值,它的名稱是“text1”,值為“hehe”。第二段是文件內(nèi)容,段首里表明了此文件域的名稱“file1”和此文件在用戶磁盤上的位置,后面就是文件的內(nèi)容。
            如果我們想要自己寫一個(gè)上傳文件組件來(lái)接收HTML表單傳送的文件數(shù)據(jù),那么最核心的任務(wù)就是解析此數(shù)據(jù)包,從中取得需要的信息。

            理解HTTP消息頭 (四)
            服務(wù)器返回的消息

            服務(wù)器返回的HTTP消息也分為消息頭和消息體兩部分。前面連載的第二篇里已經(jīng)介紹了返回消息中常見(jiàn)返回代碼的含義。對(duì)于非正常的返回代碼的處理比較簡(jiǎn)單,只要照著要求去做就好了,而對(duì)于正常的返回代碼(200),其處理方式就多種多樣了。

            1 Content-Type

            Content-Type是返回消息中非常重要的內(nèi)容,它標(biāo)識(shí)出這個(gè)返回內(nèi)容的類型,其值為“主類型/子類型”的格式,例如最常見(jiàn)的就是 text/html,它的意思是說(shuō)返回的內(nèi)容是文本類型,這個(gè)文本又是HTML格式的。原則上瀏覽器會(huì)根據(jù)Content-Type來(lái)決定如何顯示返回的 消息體內(nèi)容。常見(jiàn)的內(nèi)容類型有:
            text/html HTML文本
            image/jpeg JPG圖片
            image/gif GIF圖片
            application/xml XML文檔
            audio/x-mpegurl MP3文件列表,如果安裝了Winamp,則可以直接把它當(dāng)面M3U文件來(lái)打開(kāi)
            更多的內(nèi)容類型可以在注冊(cè)表“HKCR\MIME\Database\Content Type”下看到
            對(duì)于IE6瀏覽器來(lái)說(shuō),如果Content-Type中的類型和實(shí)際的消息體類型不一致,那么它會(huì)根據(jù)內(nèi)容中的類型來(lái)分析實(shí)際應(yīng)該是什么類型,對(duì)于JPG、GIF等常用圖片格式都可以正確的識(shí)別出來(lái),而不管Content-Type中寫的是什么。
            如果Content-Type中指定的是瀏覽器可以直接打開(kāi)的類型,那么瀏覽器就會(huì)直接打開(kāi)其內(nèi)容顯示出來(lái),如果是被關(guān)聯(lián)到其它應(yīng)用程序的類型,這時(shí)就要查找注冊(cè)表中關(guān)于這種類型的注冊(cè)情況,如果是允許直接打開(kāi)而不需要詢問(wèn)的,就會(huì)直接調(diào)出這個(gè)關(guān)聯(lián)的應(yīng)用程序來(lái)打開(kāi)這個(gè)文件,但如果是不允許直接打開(kāi)的,就 會(huì)詢問(wèn)是否打開(kāi)。對(duì)于沒(méi)有關(guān)聯(lián)到任何應(yīng)用程序的類型,IE瀏覽器不知道它該如何打開(kāi),此時(shí)IE6就會(huì)把它當(dāng)成XML來(lái)嘗試打開(kāi)。

            2 Content-Disposition

            如果用AddHeader的方法在HTTP消息頭中加入Content-Disposition段,并指定其值為“attachment”,那么無(wú)論這個(gè)文件是何類型,瀏覽器都會(huì)提示我們下載此文件,因?yàn)榇藭r(shí)它認(rèn)為后面的消息體是一個(gè)“附件”,不需要由瀏覽器來(lái)處理了。例如,在ASP.Net中 寫入如下語(yǔ)句:
            Response.AddHeader("Content-Disposition: attachment");
            請(qǐng)求此頁(yè)面是得到的結(jié)果如:
            HTTP/1.1 200 OK
            Server: Microsoft-IIS/5.1
            Date: Thu, 23 Mar 2006 07:54:53 GMT
            Content-Disposition: attachment
            Cache-Control: private
            Content-Type: text/html; charset=utf-8
            ……
            也就是說(shuō),通過(guò)AddHeader函數(shù)可以為HTTP消息頭加入我們自定義的內(nèi)容。使用這種方法可以強(qiáng)制讓瀏覽器提示下載文件,即使這個(gè)文件是我們已知的 類型,基于是HTML網(wǎng)頁(yè)。如果想要讓用戶下載時(shí)提示一個(gè)默認(rèn)的文件名,只需要在前面一句話后加上“filename=文件名”即可。例如:
            Response.AddHeader("Content-Disposition: attachment; filename=mypage.htm");

            3 Content-Type與Content-Disposition

            如果把Content-Type和Content-Disposition結(jié)合在一起使用會(huì)怎么樣呢?
            打開(kāi)一個(gè)網(wǎng)頁(yè)時(shí),瀏覽器會(huì)首先看是否有Content-Disposition: attachment這一項(xiàng),如果有,無(wú)論Content-Type的值是什么,都會(huì)提示文件下載。
            如果指定了filename,就會(huì)提示默認(rèn)的文件名為此文件名。注意到在IE6中除了“保存”按扭外還有“打開(kāi)”按扭,此時(shí)打開(kāi)文件的類型是由在 filename中指定的文件擴(kuò)展名決定的,例如讓filename=mypic.jpg,瀏覽器就會(huì)查找默認(rèn)的圖片查看器來(lái)打開(kāi)此文件。
            如果沒(méi)有指定filename,那么瀏覽器就根據(jù)Content-Type中的類型來(lái)決定文件的類型,例如Content-Type類型為 image/gif,那么就會(huì)去查找默認(rèn)的看GIF圖片的工具,并且設(shè)置此文件的名字為所請(qǐng)求的網(wǎng)頁(yè)的主名(不帶擴(kuò)展名)加上對(duì)應(yīng)于此文件類弄擴(kuò)展名,例 如請(qǐng)求的mypage.aspx,就會(huì)自動(dòng)變成mypage.gif。如果并沒(méi)有指定Content-Type值,那么就默認(rèn)它為 “text/html”,并且保存的文件名就是所請(qǐng)求的網(wǎng)頁(yè)文件名。
            但如果沒(méi)有指定Content-Disposition,那么就和前面關(guān)于Content-Type中所討論的情況是一樣的了。

            4 Cache

            返回消息中的Cache用于指定網(wǎng)頁(yè)緩存。我們經(jīng)常可以看到這樣的情況,打開(kāi)一個(gè)網(wǎng)頁(yè)時(shí)速度不快,但再次打開(kāi)時(shí)就會(huì)快很多,原因是瀏覽器已經(jīng)對(duì)此頁(yè)面進(jìn)行了緩存,那么在同一瀏覽器窗口中再次打開(kāi)此頁(yè)時(shí)不會(huì)重新從服務(wù)器端獲取。網(wǎng)頁(yè)的緩存是由HTTP消息頭中的“Cache-control”來(lái)控制 的,常見(jiàn)的取值有private、no-cache、max-age、must-revalidate等,默認(rèn)為private。其作用根據(jù)不同的重新瀏 覽方式分為以下幾種情況:
            (1) 打開(kāi)新窗口
            如果指定cache-control的值為private、no-cache、must-revalidate,那么打開(kāi)新窗口訪問(wèn)時(shí)都會(huì)重新訪問(wèn)服務(wù)器。而如果指定了max-age值,那么在此值內(nèi)的時(shí)間里就不會(huì)重新訪問(wèn)服務(wù)器,例如:
            Cache-control: max-age=5
            表示當(dāng)訪問(wèn)此網(wǎng)頁(yè)后的5秒內(nèi)再次訪問(wèn)不會(huì)去服務(wù)器
            (2) 在地址欄回車
            如果值為private或must-revalidate(和網(wǎng)上說(shuō)的不一樣),則只有第一次訪問(wèn)時(shí)會(huì)訪問(wèn)服務(wù)器,以后就不再訪問(wèn)。如果值為no-cache,那么每次都會(huì)訪問(wèn)。如果值為max-age,則在過(guò)期之前不會(huì)重復(fù)訪問(wèn)。
            (3) 按后退按扭
            如果值為private、must-revalidate、max-age,則不會(huì)重訪問(wèn),而如果為no-cache,則每次都重復(fù)訪問(wèn)
            (4) 按刷新按扭
            無(wú)論為何值,都會(huì)重復(fù)訪問(wèn)

            當(dāng)指定Cache-control值為“no-cache”時(shí),訪問(wèn)此頁(yè)面不會(huì)在Internet臨時(shí)文章夾留下頁(yè)面?zhèn)浞荨?br>另外,通過(guò)指定“Expires”值也會(huì)影響到緩存。例如,指定Expires值為一個(gè)早已過(guò)去的時(shí)間,那么訪問(wèn)此網(wǎng)時(shí)若重復(fù)在地址欄按回車,那么每次都會(huì)重復(fù)訪問(wèn):
            Expires: Fri, 31 Dec 1999 16:00:00 GMT

            在ASP中,可以通過(guò)Response對(duì)象的Expires、ExpiresAbsolute屬性控制Expires值;通過(guò)Response對(duì)象的CacheControl屬性控制Cache-control的值,例如:
            Response.ExpiresAbsolute = #2000-1-1# ' 指定絕對(duì)的過(guò)期時(shí)間,這個(gè)時(shí)間用的是服務(wù)器當(dāng)?shù)貢r(shí)間,會(huì)被自動(dòng)轉(zhuǎn)換為GMT時(shí)間
            Response.Expires = 20 ' 指定相對(duì)的過(guò)期時(shí)間,以分鐘為單位,表示從當(dāng)前時(shí)間起過(guò)多少分鐘過(guò)期。
            Response.CacheControl = "no-cache"
            Expires值是可以通過(guò)在Internet臨時(shí)文件夾中查看臨時(shí)文件的屬性看到的,如:

            clip_image003

            posted on 2008-05-29 16:13 肥仔 閱讀(1079) 評(píng)論(0)  編輯 收藏 引用 所屬分類: HTTP & URL

            久久久久亚洲AV片无码下载蜜桃 | 亚洲欧美一区二区三区久久| 久久久久久毛片免费看 | 热久久最新网站获取| 亚洲伊人久久成综合人影院 | 亚洲精品美女久久久久99| 国内精品九九久久精品| 久久精品国内一区二区三区| 亚洲欧美国产日韩综合久久| 久久久久久无码Av成人影院| 久久久久国产精品嫩草影院 | 亚洲av成人无码久久精品| 亚洲一本综合久久| 亚洲av成人无码久久精品| 亚洲成av人片不卡无码久久| 99久久国产热无码精品免费| 7777精品伊人久久久大香线蕉| 91精品国产综合久久精品| 久久亚洲国产精品成人AV秋霞| 久久99精品国产| 无码人妻久久一区二区三区免费 | 国产精品gz久久久| 精品久久人妻av中文字幕| 久久人妻少妇嫩草AV蜜桃| 国产午夜精品理论片久久| 久久精品国产第一区二区三区| 狠狠色丁香久久婷婷综合_中| 精品久久久久中文字| 久久青草国产精品一区| 久久91精品国产91久久户| 久久成人国产精品| 久久国产精品77777| 亚洲愉拍99热成人精品热久久| 亚洲欧美国产日韩综合久久| 天堂无码久久综合东京热| 久久天天躁狠狠躁夜夜2020老熟妇 | 97超级碰碰碰久久久久| 亚洲国产另类久久久精品| 久久亚洲精品无码VA大香大香| 亚洲精品无码专区久久同性男| 久久久久亚洲av毛片大|