【Web開發原理】HTTP協議詳解
一、概念
協議是指計算機通訊網路中兩臺計算機之間進行通訊所必須共同遵守的規定或規則,超文字傳輸協議(HTTP)是一種通訊協議,它允許將超文字標記語言(HTML)文件從Web伺服器傳送到客戶端的瀏覽器。
HTTP協議,即超文字傳輸協議(Hypertext transfer protocol)。是一種詳細規定了瀏覽器和全球資訊網(WWW = World Wide Web)伺服器之間互相通訊的規則,通過因特網傳送全球資訊網文件的資料傳送協議。
HTTP協議是用於從WWW伺服器傳輸超文字到本地瀏覽器的傳送協議。它可以使瀏覽器更加高效,使網路傳輸減少。它不僅保證計算機正確快速地傳輸超文字文件,還確定傳輸文件中的哪一部分,以及哪部分內容首先顯示(如文字先於圖形)等。
HTTP是一個應用層協議,由請求和響應構成,是一個標準的客戶端伺服器模型。HTTP是一個無狀態的協議。
在Internet中所有的傳輸都是通過TCP/IP進行的。HTTP協議作為TCP/IP模型中應用層的協議也不例外。HTTP協議通常承載於TCP協議之上,有時也承載於TLS或SSL協議層之上,這個時候,就成了我們常說的HTTPS。如下圖所示:
HTTP預設的埠號為80,HTTPS的埠號為443。
瀏覽網頁是HTTP的主要應用,但是這並不代表HTTP就只能應用於網頁的瀏覽。HTTP是一種協議,只要通訊的雙方都遵守這個協議,HTTP就能有用武之地。比如咱們常用的QQ,迅雷這些軟體,都會使用HTTP協議(還包括其他的協議)。
二、簡史
它的發展是全球資訊網協會(World Wide Web Consortium)和Internet工作小組IETF(Internet Engineering Task Force)合作的結果,(他們)最終釋出了一系列的RFC,RFC 1945定義了HTTP/1.0版本。其中最著名的就是RFC 2616。RFC 2616定義了今天普遍使用的一個版本——HTTP 1.1。
三、特點
HTTP協議永遠都是客戶端發起請求,伺服器回送響應。這樣就限制了使用HTTP協議,無法實現在客戶端沒有發起請求的時候,伺服器將訊息推送給客戶端。
HTTP協議的主要特點可概括如下:
1、支援客戶/伺服器模式。支援基本認證和安全認證。
2、簡單快速:客戶向伺服器請求服務時,只需傳送請求方法和路徑。請求方法常用的有GET、HEAD、POST。每種方法規定了客戶與伺服器聯絡的型別不同。由於HTTP協議簡單,使得HTTP伺服器的程式規模小,因而通訊速度很快。
3、靈活:HTTP允許傳輸任意型別的資料物件。正在傳輸的型別由Content-Type加以標記。
4、HTTP 0.9和1.0使用非持續連線:限制每次連線只處理一個請求,伺服器處理完客戶的請求,並收到客戶的應答後,即斷開連線。採用這種方式可以節省傳輸時間。HTTP 1.1使用持續連線:不必為每個web物件建立一個新的連線,一個連線可以傳送多個物件。
5、無狀態:HTTP協議是無狀態協議。無狀態是指協議對於事務處理沒有記憶能力。缺少狀態意味著如果後續處理需要前面的資訊,則它必須重傳,這樣可能導致每次連線傳送的資料量增大。
無狀態協議:
協議的狀態是指下一次傳輸可以“記住”這次傳輸資訊的能力。
http是不會為了下一次連線而維護這次連線所傳輸的資訊,為了保證伺服器記憶體。
比如客戶獲得一張網頁之後關閉瀏覽器,然後再一次啟動瀏覽器,再登陸該網站,但是伺服器並不知道客戶關閉了一次瀏覽器。
由於Web伺服器要面對很多瀏覽器的併發訪問,為了提高Web伺服器對併發訪問的處理能力,在設計HTTP協議時規定Web伺服器傳送HTTP應答報文和文件時,不儲存發出請求的Web瀏覽器程序的任何狀態資訊。這有可能出現一個瀏覽器在短短几秒之內兩次訪問同一物件時,伺服器程序不會因為已經給它發過應答報文而不接受第二期服務請求。由於Web伺服器不儲存傳送請求的Web瀏覽器程序的任何資訊,因此HTTP協議屬於無狀態協議(Stateless Protocol)。
HTTP協議是無狀態的和Connection: keep-alive的區別:
無狀態是指協議對於事務處理沒有記憶能力,伺服器不知道客戶端是什麼狀態。從另一方面講,開啟一個伺服器上的網頁和你之前開啟這個伺服器上的網頁之間沒有任何聯絡。
HTTP是一個無狀態的面向連線的協議,無狀態不代表HTTP不能保持TCP連線,更不能代表HTTP使用的是UDP協議(無連線)。
從HTTP/1.1起,預設都開啟了Keep-Alive,保持連線特性,簡單地說,當一個網頁開啟完成後,客戶端和伺服器之間用於傳輸HTTP資料的TCP連線不會關閉,如果客戶端再次訪問這個伺服器上的網頁,會繼續使用這一條已經建立的連線。
Keep-Alive不會永久保持連線,它有一個保持時間,可以在不同的伺服器軟體(如Apache)中設定這個時間。
四、工作流程
一次HTTP操作稱為一個事務,其工作過程可分為四步:
1)首先客戶機與伺服器需要建立連線。只要單擊某個超級連結,HTTP的工作開始。
2)建立連線後,客戶機發送一個請求給伺服器,請求方式的格式為:統一資源識別符號(URL)、協議版本號,後邊是MIME資訊包括請求修飾符、客戶機資訊和可能的內容。
3)伺服器接到請求後,給予相應的響應資訊,其格式為一個狀態行,包括資訊的協議版本號、一個成功或錯誤的程式碼,後邊是MIME資訊包括伺服器資訊、實體資訊和可能的內容。
4)客戶端接收伺服器所返回的資訊通過瀏覽器顯示在使用者的顯示屏上,然後客戶機與伺服器斷開連線。
如果在以上過程中的某一步出現錯誤,那麼產生錯誤的資訊將返回到客戶端,有顯示屏輸出。對於使用者來說,這些過程是由HTTP自己完成的,使用者只要用滑鼠點選,等待資訊顯示就可以了。
HTTP是基於傳輸層的TCP協議,而TCP是一個端到端的面向連線的協議。所謂的端到端可以理解為程序到程序之間的通訊。所以HTTP在開始傳輸之前,首先需要建立TCP連線,而TCP連線的過程需要所謂的“三次握手”。下圖所示TCP連線的三次握手。
在TCP三次握手之後,建立了TCP連線,此時HTTP就可以進行傳輸了。一個重要的概念是面向連線,既HTTP在傳輸完成之間並不斷開TCP連線。在HTTP1.1中(通過Connection頭設定)這是預設行為。
五、使用Wireshark抓TCP、http包
開啟Wireshark,選擇工具欄上的"Capture"->"Options"
點選"Capture Filter",此處選擇的是"HTTP TCP port(80)",選擇後點擊上圖的"Start"開始抓包。
然後在瀏覽器中開啟http://image.baidu.com/,抓包結果如下圖所示:
在上圖中,可清晰的看到客戶端瀏覽器(ip為192.168.1.6)與伺服器(115.239.210.36)的互動過程:
1)No1:瀏覽器(192.168.1.6)向伺服器(115.239.210.36)發出連線請求。此為TCP三次握手第一步,此時從圖中可以看出,為SYN,seq:X (x=0);
2)No2:伺服器(115.239.210.36)迴應了瀏覽器(192.168.1.6)的請求,並要求確認,此時為:SYN,ACK,此時seq:y(y為0),ACK:x+1(為1)。此為三次握手的第二步;
3)No3:瀏覽器(192.168.1.6)迴應了伺服器(115.239.210.36)的確認,連線成功。為:ACK,此時seq:x+1(為1),ACK:y+1(為1)。此為三次握手的第三步;
4)No4:瀏覽器(192.168.1.6)發出一個頁面HTTP請求;
5)No5:伺服器(115.239.210.36)確認;
6)No6:伺服器(115.239.210.36)傳送資料;
7)No8:客戶端瀏覽器(192.168.1.6)確認;
8)No81:客戶端(192.168.1.6)發出一個圖片HTTP請求;
9)No202:伺服器(115.239.210.36)傳送狀態響應碼200 OK。
六、頭域
每個頭域由一個域名,冒號(:)和域值三部分組成。域名是大小寫無關的,域值前可以新增任何數量的空格符,頭域可以被擴充套件為多行,在每行開始處,使用至少一個空格或製表符。
6.1、請求資訊:
發出的請求資訊格式如下:
●請求行,例如GET /images/logo.gif HTTP/1.1,表示從/images目錄下請求logo.gif這個檔案。
●(請求)頭,例如Accept-Language: en
●空行
●可選的訊息體 請求行和標題必須以<CR><LF>作為結尾(也就是,回車然後換行)。空行內必須只有<CR><LF>而無其他空格。在HTTP/1.1協議中,所有的請求頭,除post外,都是可選的。
三個部分分別是:請求行、訊息報頭、請求正文。
6.2、請求方法
HTTP/1.1協議中共定義了八種方法(有時也叫“動作”)來表明Request-URI指定的資源的不同操作方式:
OPTIONS - 返回伺服器針對特定資源所支援的HTTP請求方法。也可以利用向Web伺服器傳送'*'的請求來測試伺服器的功能性。
HEAD- 向伺服器索要與GET請求相一致的響應,只不過響應體將不會被返回。這一方法可以在不必傳輸整個響應內容的情況下,就可以獲取包含在響應訊息頭中的元資訊。該方法常用於測試超連結的有效性,是否可以訪問,以及最近是否更新。
GET - 向特定的資源發出請求。注意:GET方法不應當被用於產生“副作用”的操作中,例如在web app.中。其中一個原因是GET可能會被網路蜘蛛等隨意訪問。
POST - 向指定資源提交資料進行處理請求(例如提交表單或者上傳檔案)。資料被包含在請求體中。POST請求可能會導致新的資源的建立和/或已有資源的修改。
PUT - 向指定資源位置上傳其最新內容。
DELETE - 請求伺服器刪除Request-URI所標識的資源。
TRACE- 回顯伺服器收到的請求,主要用於測試或診斷。
CONNECT - HTTP/1.1協議中預留給能夠將連線改為管道方式的代理伺服器。
PATCH - 用來將區域性修改應用於某一資源,添加於規範RFC5789。
方法名稱是區分大小寫的。當某個請求所針對的資源不支援對應的請求方法的時候,伺服器應當返回狀態碼405(Method Not Allowed);當伺服器不認識或者不支援對應的請求方法的時候,應當返回狀態碼501(Not Implemented)。
HTTP伺服器至少應該實現GET和HEAD方法,其他方法都是可選的。此外,除了上述方法,特定的HTTP伺服器還能夠擴充套件自定義的方法。
GET和POST的區別:
1、GET提交的資料會放在URL之後,以?分割URL和傳輸資料,引數之間以&相連,如EditPosts.aspx?name=test1&id=123456. POST方法是把提交的資料放在HTTP包的Body中。
2、GET提交的資料大小有限制,最多隻能有1024位元組(因為瀏覽器對URL的長度有限制),而POST方法提交的資料沒有限制。
3、GET方式需要使用Request.QueryString來取得變數的值,而POST方式通過Request.Form來獲取變數的值。
4、GET方式提交資料,會帶來安全問題,比如一個登入頁面,通過GET方式提交資料時,使用者名稱和密碼將出現在URL上,如果頁面可以被快取或者其他人可以訪問這臺機器,就可以從歷史記錄獲得該使用者的賬號和密碼。
6.3、響應訊息
客戶端向伺服器傳送一個請求,伺服器以一個狀態行作為響應,響應的內容包括:訊息協議的版本、成功或者錯誤編碼、伺服器資訊、實體元資訊以及必要的實體內容。根據響應類別的類別,伺服器響應裡可以含實體內容,但不是所有的響應都有實體內容。
響應頭第一行也稱為狀態行,格式如下(下圖中紅線標出的那行):
HTTP-Version 空格 Status-Code 空格 Reason-Phrase CRLF
HTTP- Version表示HTTP版本,例如為HTTP/1.1。Status- Code是結果程式碼,用三個數字表示。Reason-Phrase是個簡單的文字描述,解釋Status-Code的具體原因。Status-Code用於機器自動識別,Reason-Phrase用於人工理解。Status-Code的第一個數字代表響應類別,可能取5個不同的值。後兩個數字沒有分類作用。Status-Code的第一個數字代表響應的類別,後續兩位描述在該類響應下發生的具體狀況,具體請參見:HTTP狀態碼 。
響應訊息的結構:
三個部分分別是:狀態行、訊息報頭、響應正文。
無論你何時瀏覽一個網頁,你的電腦都會通過一個使用HTTP協議的伺服器來獲取所請求的資料。在你請求的網頁顯示在瀏覽器之前,支配網頁的網站伺服器會返回一個包含有狀態碼的HTTP標頭檔案。這個狀態碼提供了有關所請求網頁的相關條件資訊。如果一切正常,一個標準網頁會收到一條諸如200的狀態碼。當然我們的目的不是去研究200響應碼,而是去探討那些代表出現錯誤資訊的伺服器標頭檔案響應碼,例如表示“未找到指定網頁”的404碼。
6.4、響應頭域
伺服器需要傳遞許多附加資訊,這些資訊不能全放在狀態行裡。因此,需要另行定義響應頭域,用來描述這些附加資訊。響應頭域主要描述伺服器的資訊和Request-URI的資訊。
6.5、HTTP常見的請求頭(在HTTP/1.1 協議中,所有的請求頭,除Host外,都是可選的)
If-Modified-Since:把瀏覽器端快取頁面的最後修改時間傳送到伺服器去,伺服器會把這個時間與伺服器上實際檔案的最後修改時間進行對比。如果時間一致,那麼返回304,客戶端就直接使用本地快取檔案。如果時間不一致,就會返回200和新的檔案內容。客戶端接到之後,會丟棄舊檔案,把新檔案快取起來,並顯示在瀏覽器中。
例如:If-Modified-Since: Thu, 09 Feb 2012 09:07:57 GMT
If-None-Match:If-None-Match和ETag一起工作,工作原理是在HTTP Response中新增ETag資訊。 當用戶再次請求該資源時,將在HTTP Request 中加入If-None-Match資訊(ETag的值)。如果伺服器驗證資源的ETag沒有改變(該資源沒有更新),將返回一個304狀態告訴客戶端使用本地快取檔案。否則將返回200狀態和新的資源和Etag. 使用這樣的機制將提高網站的效能。例如: If-None-Match: "03f2b33c0bfcc1:0"。
Pragma:指定“no-cache”值表示伺服器必須返回一個重新整理後的文件,即使它是代理伺服器而且已經有了頁面的本地拷貝;在HTTP/1.1版本中,它和Cache-Control:no-cache作用一模一樣。Pargma只有一個用法, 例如: Pragma: no-cache
注意: 在HTTP/1.0版本中,只實現了Pragema:no-cache, 沒有實現Cache-Control
Cache-Control:指定請求和響應遵循的快取機制。快取指令是單向的(響應中出現的快取指令在請求中未必會出現),且是獨立的(在請求訊息或響應訊息中設定Cache-Control並不會修改另一個訊息處理過程中的快取處理過程)。請求時的快取指令包括no-cache、no-store、max-age、max-stale、min-fresh、only-if-cached,響應訊息中的指令包括public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age、s-maxage。
Cache-Control:Public 可以被任何快取所快取
Cache-Control:Private 內容只快取到私有快取中
Cache-Control:no-cache 所有內容都不會被快取
Cache-Control:no-store 用於防止重要的資訊被無意的釋出。在請求訊息中傳送將使得請求和響應訊息都不使用快取。
Cache-Control:max-age 指示客戶機可以接收生存期不大於指定時間(以秒為單位)的響應。
Cache-Control:min-fresh 指示客戶機可以接收響應時間小於當前時間加上指定時間的響應。
Cache-Control:max-stale 指示客戶機可以接收超出超時期間的響應訊息。如果指定max-stale訊息的值,那麼客戶機可以接收超出超時期指定值之內的響應訊息。
Accept:瀏覽器端可以接受的MIME型別。例如:Accept: text/html 代表瀏覽器可以接受伺服器回發的型別為 text/html 也就是我們常說的html文件,如果伺服器無法返回text/html型別的資料,伺服器應該返回一個406錯誤(non acceptable)。萬用字元 * 代表任意型別,例如 Accept: */* 代表瀏覽器可以處理所有型別,(一般瀏覽器發給伺服器都是發這個)。
Accept-Encoding:瀏覽器申明自己可接收的編碼方法,通常指定壓縮方法,是否支援壓縮,支援什麼壓縮方法(gzip,deflate);Servlet能夠向支援gzip的瀏覽器返回經gzip編碼的HTML頁面。許多情形下這可以減少5到10倍的下載時間。例如: Accept-Encoding: gzip, deflate。如果請求訊息中沒有設定這個域,伺服器假定客戶端對各種內容編碼都可以接受。
Accept-Language:瀏覽器申明自己接收的語言。語言跟字符集的區別:中文是語言,中文有多種字符集,比如big5,gb2312,gbk等等;例如:Accept-Language: en-us。如果請求訊息中沒有設定這個報頭域,伺服器假定客戶端對各種語言都可以接受。
Accept-Charset:瀏覽器可接受的字符集。如果在請求訊息中沒有設定這個域,預設表示任何字符集都可以接受。
User-Agent:告訴HTTP伺服器,客戶端使用的作業系統和瀏覽器的名稱和版本。
例如: User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; CIBA; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; InfoPath.2; .NET4.0E)。
Content-Type:例如:Content-Type: application/x-www-form-urlencoded。
Referer:包含一個URL,使用者從該URL代表的頁面出發訪問當前請求的頁面。提供了Request的上下文資訊的伺服器,告訴伺服器我是從哪個連結過來的,比如從我主頁上鍊接到一個朋友那裡,他的伺服器就能夠從HTTP Referer中統計出每天有多少使用者點選我主頁上的連結訪問他的網站。
例如: Referer:http://translate.google.cn/?hl=zh-cn&tab=wT
Connection:
例如:Connection: keep-alive 當一個網頁開啟完成後,客戶端和伺服器之間用於傳輸HTTP資料的TCP連線不會關閉,如果客戶端再次訪問這個伺服器上的網頁,會繼續使用這一條已經建立的連線。HTTP 1.1預設進行持久連線。利用持久連線的優點,當頁面包含多個元素時(例如Applet,圖片),顯著地減少下載所需要的時間。要實現這一點,Servlet需要在應答中傳送一個Content-Length頭,最簡單的實現方法是:先把內容寫入ByteArrayOutputStream,然後在正式寫出內容之前計算它的大小。
Connection: close 代表一個Request完成後,客戶端和伺服器之間用於傳輸HTTP資料的TCP連線會關閉,當客戶端再次傳送Request,需要重新建立TCP連線。
Host:(傳送請求時,該頭域是必需的)主要用於指定被請求資源的Internet主機和埠號,它通常從HTTP URL中提取出來的。HTTP/1.1請求必須包含主機頭域,否則系統會以400狀態碼返回。
例如: 我們在瀏覽器中輸入:http://www.guet.edu.cn/index.html,瀏覽器傳送的請求訊息中,就會包含Host請求頭域:Host:http://www.guet.edu.cn,此處使用預設埠號80,若指定了埠號,則變成:Host:指定埠號。
Cookie:最重要的請求頭之一, 將cookie的值傳送給HTTP伺服器。
Content-Length:表示請求訊息正文的長度。例如:Content-Length: 38。
Authorization:授權資訊,通常出現在對伺服器傳送的WWW-Authenticate頭的應答中。主要用於證明客戶端有權檢視某個資源。當瀏覽器訪問一個頁面時,如果收到伺服器的響應程式碼為401(未授權),可以傳送一個包含Authorization請求報頭域的請求,要求伺服器對其進行驗證。
UA-Pixels,UA-Color,UA-OS,UA-CPU:由某些版本的IE瀏覽器所傳送的非標準的請求頭,表示螢幕大小、顏色深度、作業系統和CPU型別。
From:請求傳送者的email地址,由一些特殊的Web客戶程式使用,瀏覽器不會用到它。
Range:可以請求實體的一個或者多個子範圍。例如,
表示頭500個位元組:bytes=0-499
表示第二個500位元組:bytes=500-999
表示最後500個位元組:bytes=-500
表示500位元組以後的範圍:bytes=500-
第一個和最後一個位元組:bytes=0-0,-1
同時指定幾個範圍:bytes=500-600,601-999
但是伺服器可以忽略此請求頭,如果無條件GET包含Range請求頭,響應會以狀態碼206(PartialContent)返回而不是以200(OK)。
6.6、HTTP常見的響應頭
Allow:伺服器支援哪些請求方法(如GET、POST等)。
Date:表示訊息傳送的時間,時間的描述格式由rfc822定義。例如,Date:Mon,31Dec200104:25:57GMT。Date描述的時間表示世界標準時,換算成本地時間,需要知道使用者所在的時區。你可以用setDateHeader來設定這個頭以避免轉換時間格式的麻煩
Expires:指明應該在什麼時候認為文件已經過期,從而不再快取它,重新從伺服器獲取,會更新快取。過期之前使用本地快取。HTTP1.1的客戶端和快取會將非法的日期格式(包括0)看作已經過期。eg:為了讓瀏覽器不要快取頁面,我們也可以將Expires實體報頭域,設定為0。
例如: Expires: Tue, 08 Feb 2022 11:35:14 GMT
P3P:用於跨域設定Cookie, 這樣可以解決iframe跨域訪問cookie的問題
例如: P3P: CP=CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR
Set-Cookie:非常重要的header, 用於把cookie傳送到客戶端瀏覽器,每一個寫入cookie都會生成一個Set-Cookie。
例如: Set-Cookie: sc=4c31523a; path=/; domain=.acookie.taobao.com
ETag:和If-None-Match 配合使用。
Last-Modified:用於指示資源的最後修改日期和時間。Last-Modified也可用setDateHeader方法來設定。
Content-Type:WEB伺服器告訴瀏覽器自己響應的物件的型別和字符集。Servlet預設為text/plain,但通常需要顯式地指定為text/html。由於經常要設定Content-Type,因此HttpServletResponse提供了一個專用的方法setContentType。可在web.xml檔案中配置副檔名和MIME型別的對應關係。
例如:Content-Type: text/html;charset=utf-8
Content-Type:text/html;charset=GB2312
Content-Type: image/jpeg
媒體型別的格式為:大類/小類,比如text/html。
IANA(The Internet Assigned Numbers Authority,網際網路數字分配機構)定義了8個大類的媒體型別,分別是:
application— (比如: application/vnd.ms-excel.)
audio (比如: audio/mpeg.)
image (比如: image/png.)
message (比如,:message/http.)
model(比如:model/vrml.)
multipart (比如:multipart/form-data.)
text(比如:text/html.)
video(比如:video/quicktime.)
Content-Range:用於指定整個實體中的一部分的插入位置,他也指示了整個實體的長度。在伺服器向客戶返回一個部分響應,它必須描述響應覆蓋的範圍和整個實體長度。一般格式:Content-Range:bytes-unitSPfirst-byte-pos-last-byte-pos/entity-length。
例如,傳送頭500個位元組次欄位的形式:Content-Range:bytes0-499/1234如果一個http訊息包含此節(例如,對範圍請求的響 應或對一系列範圍的重疊請求),Content-Range表示傳送的範圍。
Content-Length:指明實體正文的長度,以位元組方式儲存的十進位制數字來表示。在資料下行的過程中,Content-Length的方式要預先在伺服器中快取所有資料,然後所有資料再一股腦兒地發給客戶端。只有當瀏覽器使用持久HTTP連線時才需要這個資料。如果你想要利用持久連線的優勢,可以把輸出文件寫入ByteArrayOutputStram,完成後檢視其大小,然後把該值放入Content-Length頭,最後通過byteArrayStream.writeTo(response.getOutputStream()傳送內容。
例如: Content-Length: 19847
Content-Encoding:WEB伺服器表明自己使用了什麼壓縮方法(gzip,deflate)壓縮響應中的物件。只有在解碼之後才可以得到Content-Type頭指定的內容型別。利用gzip壓縮文件能夠顯著地減少HTML文件的下載時間。Java的GZIPOutputStream可以很方便地進行gzip壓縮,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支援它。因此,Servlet應該通過檢視Accept-Encoding頭(即request.getHeader("Accept-Encoding"))檢查瀏覽器是否支援gzip,為支援gzip的瀏覽器返回經gzip壓縮的HTML頁面,為其他瀏覽器返回普通頁面。
例如:Content-Encoding:gzip
Content-Language:WEB伺服器告訴瀏覽器自己響應的物件所用的自然語言。例如: Content-Language:da。沒有設定該域則認為實體內容將提供給所有的語言閱讀。
Server:指明HTTP伺服器用來處理請求的軟體資訊。例如:Server: Microsoft-IIS/7.5、Server:Apache-Coyote/1.1。此域能包含多個產品標識和註釋,產品標識一般按照重要性排序。
X-AspNet-Version:如果網站是用ASP.NET開發的,這個header用來表示ASP.NET的版本。
例如: X-AspNet-Version: 4.0.30319
X-Powered-By:表示網站是用什麼技術開發的。
例如: X-Powered-By: ASP.NET
Connection:
例如:Connection: keep-alive 當一個網頁開啟完成後,客戶端和伺服器之間用於傳輸HTTP資料的TCP連線不會關閉,如果客戶端再次訪問這個伺服器上的網頁,會繼續使用這一條已經建立的連線。
Connection: close 代表一個Request完成後,客戶端和伺服器之間用於傳輸HTTP資料的TCP連線會關閉,當客戶端再次傳送Request,需要重新建立TCP連線。
Location:用於重定向一個新的位置,包含新的URL地址。表示客戶應當到哪裡去提取文件。Location通常不是直接設定的,而是通過HttpServletResponse的sendRedirect方法,該方法同時設定狀態程式碼為302。Location響應報頭域常用在更換域名的時候。
Refresh:表示瀏覽器應該在多少時間之後重新整理文件,以秒計。除了重新整理當前文件之外,你還可以通過setHeader("Refresh", "5; URL=http://host/path")讓瀏覽器讀取指定的頁面。注意這種功能通常是通過設定HTML頁面HEAD區的<META HTTP-EQUIV="Refresh" CONTENT="5;URL=http://host/path">實現,這是因為,自動重新整理或重定向對於那些不能使用CGI或Servlet的HTML編寫者十分重要。但是,對於Servlet來說,直接設定Refresh頭更加方便。注意Refresh的意義是“N秒之後重新整理本頁面或訪問指定頁面”,而不是“每隔N秒重新整理本頁面或訪問指定頁面”。因此,連續重新整理要求每次都發送一個Refresh頭,而傳送204狀態程式碼則可以阻止瀏覽器繼續重新整理,不管是使用Refresh頭還是<META HTTP-EQUIV="Refresh" ...>。注意Refresh頭不屬於HTTP 1.1正式規範的一部分,而是一個擴充套件,但Netscape和IE都支援它。
WWW-Authenticate:該響應報頭域必須被包含在401(未授權的)響應訊息中,客戶端收到401響應訊息時候,併發送Authorization報頭域請求伺服器對其進行驗證時,服務端響應報頭就包含該報頭域。
eg:WWW-Authenticate:Basic realm="Basic Auth Test!" //可以看出伺服器對請求資源採用的是基本驗證機制。
七、解決HTTP無狀態的問題
7.1、通過Cookies儲存狀態資訊
通過Cookies,伺服器就可以清楚的知道請求2和請求1來自同一個客戶端。
7.2、通過Session儲存狀態資訊
Session機制是一種伺服器端的機制,伺服器使用一種類似於散列表的結構(也可能就是使用散列表)來儲存資訊。
當程式需要為某個客戶端的請求建立一個session的時候,伺服器首先檢查這個客戶端的請求裡是否已包含了一個session標識 - 稱為 session id,如果已包含一個session id則說明以前已經為此客戶端建立過session,伺服器就按照session id把這個 session檢索出來使用(如果檢索不到,可能會新建一個),如果客戶端請求不包含session id,則為此客戶端建立一個session並且生成一個與此session相關聯的session id,session id的值應該是一個既不會重複,又不容易被找到規律以仿造的字串,這個session id將被在本次響應中返回給客戶端儲存。
Session的實現方式:
1、使用Cookie來實現
伺服器給每個Session分配一個唯一的JSESSIONID,並通過Cookie傳送給客戶端。
當客戶端發起新的請求的時候,將在Cookie頭中攜帶這個JSESSIONID。這樣伺服器能夠找到這個客戶端對應的Session。
2、使用URL回寫來實現
URL回寫是指伺服器在傳送給瀏覽器頁面的所有連結中都攜帶JSESSIONID的引數,這樣客戶端點選任何一個連結都會把JSESSIONID帶會伺服器。如果直接在瀏覽器輸入服務端資源的url來請求該資源,那麼Session是匹配不到的。
Tomcat對Session的實現,是一開始同時使用Cookie和URL回寫機制,如果發現客戶端支援Cookie,就繼續使用Cookie,停止使用URL回寫。如果發現Cookie被禁用,就一直使用URL回寫。jsp開發處理到Session的時候,對頁面中的連結記得使用response.encodeURL() 。
Cookie和Session有以下明顯的不同點:
1)Cookie將狀態儲存在客戶端,Session將狀態儲存在伺服器端;
2)Cookies是伺服器在本地機器上儲存的小段文字並隨每一個請求傳送至同一個伺服器。Cookie最早在RFC2109中實現,後續RFC2965做了增強。網路伺服器用HTTP頭向客戶端傳送cookies,在客戶終端,瀏覽器解析這些cookies並將它們儲存為一個本地檔案,它會自動將同一伺服器的任何請求縛上這些cookies。Session並沒有在HTTP的協議中定義;
3)Session是針對每一個使用者的,變數的值儲存在伺服器上,用一個sessionID來區分是哪個使用者session變數,這個值是通過使用者的瀏覽器在訪問的時候返回給伺服器,當客戶禁用cookie時,這個值也可能設定為由get來返回給伺服器;
4)就安全性來說:當你訪問一個使用session 的站點,同時在自己機子上建立一個cookie,建議在伺服器端的SESSION機制更安全些。因為它不會任意讀取客戶儲存的資訊。
7.3、通過表單變數保持狀態
除了Cookies之外,還可以使用表單變數來保持狀態,比如Asp.net就通過一個叫ViewState的Input=“hidden”的框來保持狀態,比如:
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMjA0OTM4MTAwNGRkXUfhlDv1Cs7/qhBlyZROCzlvf5U=" />
這個原理和Cookies大同小異,只是每次請求和響應所附帶的資訊變成了表單變數。
7.4、通過QueryString保持狀態
QueryString通過將資訊儲存在所請求地址的末尾來向伺服器傳送資訊,通常和表單結合使用,一個典型的QueryString比如:www.xxx.com/xxx.aspx?var1=value&var2=value2
八、使用telnet進行http測試
在Windows下,可使用命令視窗進行http簡單測試。輸入cmd進入命令視窗,在命令列鍵入如下命令後按回車:
telnet www.baidu.com 80
而後在視窗中按下"Ctrl+]"後按回車可讓返回結果回顯。
接著開始發請求訊息,例如傳送如下請求訊息請求baidu的首頁訊息,使用的HTTP協議為HTTP/1.1:
GET /index.html HTTP/1.1
注意:copy如上的訊息到命令視窗後需要按兩個回車換行才能得到響應的訊息,第一個回車換行是在命令後鍵入回車換行,是HTTP協議要求的。第二個是確認輸入,傳送請求。
可看到,當採用HTTP/1.1時,連線不是在請求結束後就斷開的。若採用HTTP1.0,在命令視窗鍵入:
GET /index.html HTTP/1.0
此時可以看到請求結束之後馬上斷開。
讀者還可以嘗試在使用GET或POST等時,帶上頭域資訊,例如鍵入如下資訊:
GET /index.html HTTP/1.1
connection: close
Host: www.baidu.com
九、URL詳解
URL(Uniform Resource Locator) 地址用於描述一個網路上的資源, 基本格式如下
schema://host[:port#]/path/.../[;url-params][?query-string][#anchor]
scheme 指定低層使用的協議(例如:http, https, ftp)
host HTTP伺服器的IP地址或者域名
port# HTTP伺服器的預設埠是80,這種情況下埠號可以省略。如果使用了別的埠,必須指明,例如 http://www.cnblogs.com:8080/
path 訪問資源的路徑
url-params
query-string 傳送給http伺服器的資料
anchor- 錨
URL 的一個例子:
http://www.mywebsite.com/sj/test;id=8079?name=sviergn&x=true#stuff
Schema: http
host: www.mywebsite.com
path: /sj/test
URL params: id=8079
Query String: name=sviergn&x=true
Anchor: stuff
十、快取的實現原理
WEB快取(cache)位於Web伺服器和客戶端之間。
快取會根據請求儲存輸出內容的副本,例如html頁面,圖片,檔案,當下一個請求來到的時候:如果是相同的URL,快取直接使用副本響應訪問請求,而不是向源伺服器再次傳送請求。
HTTP協議定義了相關的訊息頭來使WEB快取儘可能好的工作。
10.1、快取的優點
減少相應延遲:因為請求從快取伺服器(離客戶端更近)而不是源伺服器被相應,這個過程耗時更少,讓web伺服器看上去相應更快。
減少網路頻寬消耗:當副本被重用時會減低客戶端的頻寬消耗;客戶可以節省頻寬費用,控制頻寬的需求的增長並更易於管理。
10.2、客戶端快取生效的常見流程
伺服器收到請求時,會在200OK中回送該資源的Last-Modified和ETag頭,客戶端將該資源儲存在cache中,並記錄這兩個屬性。當客戶端需要傳送相同的請求時,會在請求中攜帶If-Modified-Since和If-None-Match兩個頭。兩個頭的值分別是響應中Last-Modified和ETag頭的值。伺服器通過這兩個頭判斷本地資源未發生變化,客戶端不需要重新下載,返回304響應。
10.3、Web快取機制
HTTP/1.1中快取的目的是為了在很多情況下減少傳送請求,同時在許多情況下可以不需要傳送完整響應。前者減少了網路迴路的數量;HTTP利用一個“過期(expiration)”機制來為此目的。後者減少了網路應用的頻寬;HTTP用“驗證(validation)”機制來為此目的。
HTTP定義了3種快取機制:
1)Freshness:允許一個迴應訊息可以在源伺服器不被重新檢查,並且可以由伺服器和客戶端來控制。例如,Expires迴應頭給了一個文件不可用的時間。Cache-Control中的max-age標識指明瞭快取的最長時間;
2)Validation:用來檢查以一個快取的迴應是否仍然可用。例如,如果一個迴應有一個Last-Modified迴應頭,快取能夠使用If-Modified-Since來判斷是否已改變,以便判斷根據情況傳送請求;
3)Invalidation:在另一個請求通過快取的時候,常常有一個副作用。例如,如果一個URL關聯到一個快取迴應,但是其後跟著POST、PUT和DELETE的請求的話,快取就會過期。
十一、HTTP應用
11.1、斷點續傳的實現原理
HTTP協議的GET方法,支援只請求某個資源的某一部分;
206 Partial Content 部分內容響應;
Range 請求的資源範圍;
Content-Range 響應的資源範圍;
在連線斷開重連時,客戶端只請求該資源未下載的部分,而不是重新請求整個資源,來實現斷點續傳。
分塊請求資源例項:
Eg1:Range: bytes=306302- :請求這個資源從306302個位元組到末尾的部分;
Eg2:Content-Range: bytes 306302-604047/604048:響應中指示攜帶的是該資源的第306302-604047的位元組,該資源共604048個位元組;
客戶端通過併發的請求相同資源的不同片段,來實現對某個資源的併發分塊下載。從而達到快速下載的目的。目前流行的FlashGet和迅雷基本都是這個原理。
11.2、多執行緒下載的原理
下載工具開啟多個發出HTTP請求的執行緒;
每個http請求只請求資原始檔的一部分:Content-Range: bytes 20000-40000/47000;
合併每個執行緒下載的檔案。
11.3、http代理
http代理伺服器
代理伺服器英文全稱是Proxy Server,其功能就是代理網路使用者去取得網路資訊。形象的說:它是網路資訊的中轉站。
代理伺服器是介於瀏覽器和Web伺服器之間的一臺伺服器,有了它之後,瀏覽器不是直接到Web伺服器去取回網頁而是向代理伺服器發出請求,Request訊號會先送到代理伺服器,由代理伺服器來取回瀏覽器所需要的資訊並傳送給你的瀏覽器。
而且,大部分代理伺服器都具有緩衝的功能,就好象一個大的Cache,它有很大的儲存空間,它不斷將新取得資料儲存到它本機的儲存器上,如果瀏覽器所請求的資料在它本機的儲存器上已經存在而且是最新的,那麼它就不重新從Web伺服器取資料,而直接將儲存器上的資料傳送給使用者的瀏覽器,這樣就能顯著提高瀏覽速度和效率。更重要的是:Proxy Server(代理伺服器)是Internet鏈路級閘道器所提供的一種重要的安全功能,它的工作主要在開放系統互聯(OSI)模型的對話層。
http代理伺服器的主要功能:
1)突破自身IP訪問限制,訪問國外站點。如:教育網、169網等網路使用者可以通過代理訪問國外網站;
2)訪問一些單位或團體內部資源,如某大學FTP(前提是該代理地址在該資源的允許訪問範圍之內),使用教育網內地址段免費代理伺服器,就可以用於對教育 網開放的各類FTP下載上傳,以及各類資料查詢共享等服務;
3)突破中國電信的IP封鎖:中國電信使用者有很多網站是被限制訪問的,這種限制是人為的,不同Serve對地址的封鎖是不同的。所以不能訪問時可以換一個國外的代理伺服器試試;
4)提高訪問速度:通常代理伺服器都設定一個較大的硬碟緩衝區,當有外界的資訊通過時,同時也將其儲存到緩衝區中,當其他使用者再訪問相同的資訊時,則直接由緩衝區中取出資訊,傳給使用者,以提高訪問速度;
5)隱藏真實IP:上網者也可以通過這種方法隱藏自己的IP,免受攻擊。
對於客戶端瀏覽器而言,http代理伺服器相當於伺服器。
而對於Web伺服器而言,http代理伺服器又擔當了客戶端的角色。
11.4、虛擬主機
虛擬主機:是在網路伺服器上劃分出一定的磁碟空間供使用者放置站點、應用元件等,提供必要的站點功能與資料存放、傳輸功能。
所謂虛擬主機,也叫“網站空間”就是把一臺執行在網際網路上的伺服器劃分成多個“虛擬”的伺服器,每一個虛擬主機都具有獨立的域名和完整的Internet伺服器(支援WWW、FTP、E-mail等)功能。一臺伺服器上的不同虛擬主機是各自獨立的,並由使用者自行管理。但一臺伺服器主機只能夠支援一定數量的虛擬主機,當超過這個數量時,使用者將會感到效能急劇下降。
虛擬主機的實現原理
虛擬主機是用同一個WEB伺服器,為不同域名網站提供服務的技術。Apache、Tomcat等均可通過配置實現這個功能。
相關的HTTP訊息頭:Host。
例如:Host: www.baidu.com
客戶端傳送HTTP請求的時候,會攜帶Host頭,Host頭記錄的是客戶端輸入的域名。這樣伺服器可以根據Host頭確認客戶要訪問的是哪一個域名。
十二、HTTP認證方式
HTTP請求報頭: Authorization
HTTP響應報頭: WWW-Authenticate
HTTP認證是基於質詢/迴應(challenge/response)的認證模式。
12.1 基本認證 basic authentication(HTTP1.0提出的認證方法)
基本認證是一種用來允許Web瀏覽器或其他客戶端程式在請求時提供使用者名稱和口令形式的身份憑證的一種登入驗證方式。
把 "使用者名稱+冒號+密碼"用BASE64演算法加密後的字串放在http request 中的header Authorization中傳送給服務端。
客戶端對於每一個realm,通過提供使用者名稱和密碼來進行認證的方式。
包含密碼的明文傳遞。
當瀏覽器訪問使用基本認證的網站的時候, 瀏覽器會提示你輸入使用者名稱和密碼,如下圖:
假如使用者名稱密碼錯誤的話,伺服器會返回401,如下圖:
基本認證步驟:
1、客戶端訪問一個受http基本認證保護的資源。
2、伺服器返回401狀態,要求客戶端提供使用者名稱和密碼進行認證。(驗證失敗的時候,響應頭會加上WWW-Authenticate: Basic realm="請求域"。)
401 Unauthorized
WWW-Authenticate: Basic realm="WallyWorld"
3、客戶端將輸入的使用者名稱密碼用Base64進行編碼後,採用非加密的明文方式傳送給伺服器。
Authorization: Basic xxxxxxxxxx.
4、伺服器將Authorization頭中的使用者名稱密碼解碼並取出,進行驗證,如果認證成功,則返回相應的資源。如果認證失敗,則仍返回401狀態,要求重新進行認證。
特記事項:
1、Http是無狀態的,同一個客戶端對同一個realm內資源的每一個訪問會被要求進行認證。
2、客戶端通常會快取使用者名稱和密碼,並和authentication realm一起儲存,所以,一般不需要你重新輸入使用者名稱和密碼。
3、以非加密的明文方式傳輸,雖然轉換成了不易被人直接識別的字串,但是無法防止使用者名稱密碼被惡意盜用。雖然用肉眼看不出來,但用程式很容易解密。
優點:
基本認證的一個優點是基本上所有流行的網頁瀏覽器都支援基本認證。基本認證很少在可公開訪問的網際網路網站上使用,有時候會在小的私有系統中使用(如路由器
網頁管理介面)。後來的機制HTTP摘要認證是為替代基本認證而開發的,允許金鑰以相對安全的方式在不安全的通道上傳輸。
程式設計師和系統管理員有時會在可信網路環境中使用基本認證,使用Telnet或其他明文網路協議工具手動地測試Web伺服器。這是一個麻煩的過程,但是網路上傳輸的
內容是人可讀的,以便進行診斷。
缺點:
雖然基本認證非常容易實現,但該方案建立在以下的假設的基礎上,即:客戶端和伺服器主機之間的連線是安全可信的。特別是,如果沒有使用SSL/TLS這樣的傳輸
層安全的協議,那麼以明文傳輸的金鑰和口令很容易被攔截。該方案也同樣沒有對伺服器返回的資訊提供保護。
現存的瀏覽器儲存認證資訊直到標籤頁或瀏覽器被關閉,或者使用者清除歷史記錄。HTTP沒有為伺服器提供一種方法指示客戶端丟棄這些被快取的金鑰。這意味著服務
器端在使用者不關閉瀏覽器的情況下,並沒有一種有效的方法來讓使用者登出。
一個例子:
這一個典型的HTTP客戶端和HTTP伺服器的對話,伺服器安裝在同一臺計算機上(localhost),包含以下步驟:
客戶端請求一個需要身份認證的頁面,但是沒有提供使用者名稱和口令。這通常是使用者在位址列輸入一個URL,或是打開了一個指向該頁面的連結。服務端響應一個401應
答碼,並提供一個認證域。接到應答後,客戶端顯示該認證域(通常是所訪問的計算機或系統的描述)給使用者並提示輸入使用者名稱和口令。此時使用者可以選擇確定或取
消。使用者輸入了使用者名稱和口令後,客戶端軟體會在原先的請求上增加認證訊息頭(值是base64encode(username+":"+password)),然後重新發送再次嘗試。
在本例中,伺服器接受了該認證螢幕並返回了頁面。如果使用者憑據非法或無效,伺服器可能再次返回401應答碼,客戶端可以再次提示使用者輸入口令。
注意:客戶端有可能不需要使用者互動,在第一次請求中就傳送認證訊息頭。
客戶端請求(沒有認證資訊):
GET /private/index.html HTTP/1.0
Host: localhost
(跟隨一個換行,以回車(CR)加換行(LF)的形式)
服務端應答:
HTTP/1.0 401 Authorization Required
Server: HTTPd/1.0
Date: Sat, 27 Nov 2004 10:18:15 GMT
WWW-Authenticate: Basic realm="Secure Area"
Content-Type: text/html
Content-Length: 311
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<HTML>
<HEAD>
<TITLE>Error</TITLE>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1">
</HEAD>
<BODY><H1>401 Unauthorized.</H1></BODY>
</HTML>
客戶端的請求(使用者名稱“"Aladdin”,口令, password “open sesame”):
GET /private/index.html HTTP/1.0
Host: localhost
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
(跟隨一個空行,如上所述)
服務端的應答:
HTTP/1.0 200 OK
Server: HTTPd/1.0
Date: Sat, 27 Nov 2004 10:19:07 GMT
Content-Type: text/html
Content-Length: 10476
(跟隨一個空行,隨後是需憑據頁的HTML文字)。
HTTP OAuth認證
OAuth對於Http來說,就是放在Authorization header中的不是使用者名稱密碼, 而是一個token。微軟的Skydrive就是使用這樣的方式。
12.2、摘要認證 digest authentication(HTTP1.1提出的基本認證的替代方法)
這個認證可以看做是基本認證的增強版本,不包含密碼的明文傳遞。
引入了一系列安全增強的選項;“保護質量”(qop)、隨機數計數器由客戶端增加、以及客戶生成的隨機數。
在HTTP摘要認證中使用 MD5 加密是為了達成"不可逆的",也就是說,當輸出已知的時候,確定原始的輸入應該是相當困難的。如果密碼本身太過簡單,也許可以
通過嘗試所有可能的輸入來找到對應的輸出(窮舉攻擊),甚至可以通過字典或者適當的查詢表加快查詢速度。
示例及說明
下面的例子僅僅涵蓋了“auth”保護質量的程式碼,因為在撰寫期間,所知道的只有Opera和Konqueror網頁瀏覽器支援“auth-int”(帶完整性保護的認證)。
典型的認證過程包括如下步驟:
客戶端請求一個需要認證的頁面,但是不提供使用者名稱和密碼。通常這是由於使用者簡單的輸入了一個地址或者在頁面中點選了某個超連結。
伺服器返回401 "Unauthorized" 響應程式碼,並提供認證域(realm),以及一個隨機生成的、只使用一次的數值,稱為密碼隨機數 nonce。
此時,瀏覽器會向用戶提示認證域(realm)(通常是所訪問的計算機或系統的描述),並且提示使用者名稱和密碼。使用者此時可以選擇取消。
一旦提供了使用者名稱和密碼,客戶端會重新發送同樣的請求,但是添加了一個認證頭包括了響應程式碼。
注意:客戶端可能已經擁有了使用者名稱和密碼,因此不需要提示使用者,比如以前儲存在瀏覽器裡的。
客戶端請求 (無認證):
GET /dir/index.html HTTP/1.0
Host: localhost
(跟隨一個新行,形式為一個回車再跟一個換行)
伺服器響應:
HTTP/1.0 401 Unauthorized
Server: HTTPd/0.9
Date: Sun, 10 Apr 2005 20:26:47 GMT
WWW-Authenticate: Digest realm="[email protected]", //認證域
qop="auth,auth-int", //保護質量
nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", //伺服器密碼隨機數
opaque="5ccc069c403ebaf9f0171e9517f40e41"
Content-Type: text/html
Content-Length: 311
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<HTML>
<HEAD>
<TITLE>Error</TITLE>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1">
</HEAD>
<BODY><H1>401 Unauthorized.</H1></BODY>
</HTML>
客戶端請求 (使用者名稱 "Mufasa", 密碼 "Circle Of Life"):
GET /dir/index.html HTTP/1.0
Host: localhost
Authorization: Digest username="Mufasa",
realm="[email protected]",
nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
uri="/dir/index.html",
qop=auth,
nc=00000001, //請求計數
cnonce="0a4f113b", //客戶端密碼隨機數
response="6629fae49393a05397450978507c4ef1",
opaque="5ccc069c403ebaf9f0171e9517f40e41"
(跟隨一個新行,形式如前所述)。
伺服器響應:
HTTP/1.0 200 OK
Server: HTTPd/0.9
Date: Sun, 10 Apr 2005 20:27:03 GMT
Content-Type: text/html
Content-Length: 7984
(隨後是一個空行,然後是所請求受限制的HTML頁面)
response 值由三步計算而成。當多個數值合併的時候,使用冒號作為分割符:
1、對使用者名稱、認證域(realm)以及密碼的合併值計算 MD5 雜湊值,結果稱為 HA1。
2、對HTTP方法以及URI的摘要的合併值計算 MD5 雜湊值,例如,"GET" 和 "/dir/index.html",結果稱為 HA2。
3、對HA1、伺服器密碼隨機數(nonce)、請求計數(nc)、客戶端密碼隨機數(cnonce)、保護質量(qop)以及 HA2 的合併值計算 MD5 雜湊值。結果即為客戶端提供的
response 值。
因為伺服器擁有與客戶端同樣的資訊,因此伺服器可以進行同樣的計算,以驗證客戶端提交的 response 值的正確性。在上面給出的例子中,結果是如下計算的。
(MD5()表示用於計算MD5雜湊值的函式;“\”表示接下一行;引號並不參與計算)
HA1 = MD5( "Mufasa:[email protected]:Circle Of Life" )
= 939e7578ed9e3c518a452acee763bce9
HA2 = MD5( "GET:/dir/index.html" )
= 39aff3a2bab6126f332b942af96d3366
Response = MD5( "939e7578ed9e3c518a452acee763bce9:\
dcd98b7102dd2f0e8b11d0f600bfb0c093:\
00000001:0a4f113b:auth:\
39aff3a2bab6126f332b942af96d3366" )
= 6629fae49393a05397450978507c4ef1
此時客戶端可以提交一個新的請求,重複使用伺服器密碼隨機數(nonce)(伺服器僅在每次“401”響應後發行新的nonce),但是提供新的客戶端密碼隨機數(cnonce)。在後續的請求中,十六進位制請求計數器(nc)必須比前一次使用的時候要大,否則攻擊者可以簡單的使用同樣的認證資訊重放老的請求。由伺服器來確保在每個發出的密碼隨機數nonce時,計數器是在增加的,並拒絕掉任何錯誤的請求。顯然,改變HTTP方法和/或計數器數值都會導致不同的 response值。
伺服器應當記住最近所生成的伺服器密碼隨機數nonce的值。也可以在發行每一個密碼隨機數nonce後,記住過一段時間讓它們過期。如果客戶端使用了一個過期的值,伺服器應該響應“401”狀態號,並且在認證頭中新增stale=TRUE,表明客戶端應當使用新提供的伺服器密碼隨機數nonce重發請求,而不必提示使用者其它使用者名稱和口令。
伺服器不需要儲存任何過期的密碼隨機數,它可以簡單的認為所有不認識的數值都是過期的。伺服器也可以只允許每一個伺服器密碼隨機數nonce使用一次,當然,這樣就會迫使客戶端在傳送每個請求的時