HTTP協議之處理Cookie
“由於工作需要,最近在學習HTTP協議相關的一些知識,在登陸一個jsp網站時,POST過去的請求被拒絕了,通過抓包分析可以看到此網站需要設定Cookie,這裡找打一篇文章寫得很不錯,只截抄了關於Cookie協議的一部分”
大多數的 Web 應用程式都要求維護某種會話狀態,如使用者購物車的內容。這種會話狀態的保持很多情況下需要藉助於Cookie或者Session的幫助。本文結合線上頁面翻譯 (Machine Translation System)專案中對於Cookie的處理方法,探討一下如何在HTTP應用代理中正確處理Cookie的傳遞和管理問題。讀者定位為具有Java和Web開發經驗的開發和設計人員。
讀者可以學習到關於Cookie的工作原理和Cookie協議的細節,以及在一個HTTP應用代理的場景下Cookie的管理和處理思想,並可以直接使用文中的程式碼和思路,提高工作效率。
隨著越來越多的系統移植到了Web上,HTTP協議具有了比以前更廣泛的應用。不同的系統對WEB實現提出了不同的要求,基於HTTP協議的網路應用正趨於複雜化和多元化。很多應用需要把使用者請求的頁面進行處理後再返回給使用者,比如頁面關鍵字過濾,頁面內容快取、內容搜尋、頁面翻譯等等。這些應用在實際效果上類似於一個HTTP應用代理:它們首先接受使用者的請求,根據使用者請求的URL去真正的目標伺服器取回目標頁面,再根據不同應用的要求做出相應處理後返回給使用者。這樣使用者直接面對的就是這個HTTP應用代理,而通過它與其他頁面進行互動。Cookie或Session技術的應用,解決了HTTP協議的一個問題 -- 無法保持客戶狀態,因此它現在被廣泛應用於各種Web站點中。上面提到的那些應用如果不能處理好Cookie和Session的傳遞、更新和廢除等問題,就會極大的限制它們所能處理站點的範圍,因此如何在HTTP應用代理中正確處理Cookie,成為一個必須解決的問題。本文結合在頁面翻譯(Machine Translation System)專案中對於Cookie的處理方法,探討一下這方面的解決方案。
Machine Translation System(以下簡稱MTS)是一個線上實時頁面翻譯系統,為使用者線上提供把英文頁面翻譯成其他9種語言的服務。使用者通過向MTS系統提交一個類似下面的URL使用此服務,其中引數url指明瞭使用者所需要翻譯的目標地址,引數language指明瞭所需翻譯成的目標語言,www.mts.com是假想中提供MTS服務的站點。
一個完整的MTS系統處理過程可以分解成以下幾個步驟:
•使用者向MTS提交合適的URL。 •MTS在接到使用者的請求後,解析出使用者需要翻譯的目標地址和目標語言,根據使用者請求的目標地址,把請求轉發到目標伺服器。 •MTS接受來自目標伺服器的應答,包括頁面資訊和HTTP頭資訊。 •MTS在確定得到正確的目標頁面後,把頁面內容送入WebSphere Translation Server進行翻譯。 •把翻譯後的頁面連同修改後的HTTP頭資訊提交給使用者。
MTS邏輯圖
當然,這其中涉及到很多的應用處理。比如與各種HTTP/HTTPS站點建立聯結、根據HTTP頭資訊進行頁面跳轉和錯誤處理、為始終保持使用者在翻譯模式下而對目標的HTML頁面進行分析和修改,根據系統設定對某些DNT(Do Not Translate)的頁面進行過濾和跳轉,當然還有對Cookie的處理等等。其他問題跟這篇文章關聯不大,我們重點討論在這種情況下的Cookie處理。Cookie跟隨目標伺服器的HTTP頭資訊被MTS接收到,經過MTS整理之後發給客戶端瀏覽器。MTS在接到下一次使用者對同一個站點的翻譯請求時,再把從客戶端得到的Cookie傳送給目標伺服器。
在以上的場景中,MTS充當的作用類似於一種HTTP應用代理伺服器,它代替使用者取得目標頁面,並在作出相應處理後再提交給使用者。當然,這種代理伺服器不需要使用者修改瀏覽器的代理伺服器引數或者網路配置,而只是簡單的在瀏覽器的位址列中輸入一個MTS能夠識別的URL即可。此篇文章也是在這樣一個應用場景的基礎上,展開對HTTP應用代理伺服器如何處理Cookie的討論。
問題的產生
在MTS系統中,目標伺服器的Cookie在兩個地方會產生問題。當MTS接收目標伺服器應答的時候,Cookie隨著HTTP頭資訊被MTS接收到的。這時候目標伺服器認為MTS就是最終客戶,因此它賦予了Cookie與目標伺服器相符的屬性。而如果MTS把這些Cookie原封不動的儲存在HTTP頭資訊中,傳給真正的終端使用者的話,使用者的瀏覽器會因為這些Cookie不合法而忽略它們。同理,當Cookie從瀏覽器端傳回目標伺服器的時候,也會遇到相同的問題。因此有必要對Cookie進行一些處理,以保證使用者的瀏覽器能真正識別和利用這些Cookie。
但是為何使用者瀏覽器無法識別從目標伺服器傳過來的原始Cookie呢?這是因為出於安全性的考慮,Cookie規範制定的時候對Cookie的產生和接受設定了一些嚴格的規範,不符合這些規範的Cookie,瀏覽器和伺服器都將予以忽略。下面我們從Cookie規範入手進行介紹。
目前有以下幾種Cookie規範:
•Netscape cookie草案:是最早的cookie規範,基於rfc2109。儘管這個規範與rc2109有較大的差別,但是很多伺服器都與之相容。 •rfc2109, 是w3c釋出的第一個官方cookie規範。理論上講,所有的伺服器在處理cookie(版本1)時,都要遵循此規範。遺憾的是,這個規範太嚴格了,以致很多伺服器不正確的實施了該規範或仍在使用Netscape規範。 •rfc2965規範定義了cookie版本2,並說明了cookie版本1的不足。 rfc2965規範的使用,目前並不多。rfc2109規範相應要嚴格得多,在實際應用上,並不是所有的瀏覽器和Web伺服器都嚴格遵守。因此相比較而言,Netscape cookie草案倒是一個比較簡潔和被廣泛支援的Cookie規範,因此我們在這裡以Netscape cookie草案為基礎進行討論,對於其他兩種規範,我們的討論和程式碼具有相同的意義。關於Netscape cookie草案的細節,大家可以參照Netscape官方站點,這裡我們列舉一些和我們討論有關的內容。
根據Netscape cookie草案的描述,Cookie 是Web 伺服器向用戶的瀏覽器傳送的一段ASCII碼文字。一旦收到Cookie,瀏覽器會把Cookie的資訊片斷以"名/值"對(name-value pairs)的形式儲存儲存在本地。這以後,每當向同一個Web 伺服器請求一個新的文件時,Web 瀏覽器都會發送之站點以前儲存在本地的Cookie。建立Cookie的最初目的是想讓Web伺服器能夠通過多個HTTP請求追蹤客戶。有些複雜的網路應用需要在不同的網頁之間保持一致,它們需要這種會話狀態的保持能力。
瀏覽器與Web伺服器通過HTTP協議進行通訊,而Cookie就是儲存在HTTP協議的請求或者應答頭部(在HTTP協議中,資料包括兩部分,一部分是頭部,由一些名值對構成,用來描述要被傳輸資料的一些資訊。一部分是主體(body),是真正的資料(如HTML頁面等))進行傳送的。
在HTML文件被髮送之前,Web伺服器通過傳送HTTP 包頭中的Set-Cookie 訊息把一個cookie 傳送到使用者的瀏覽器中。下面是一個遵循Netscape cookie草案的完整的Set-Cookie 頭:
Set-Cookie:customer=huangxp; path=/foo; domain=.ibm.com; expires= Wednesday, 19-OCT-05 23:12:40 GMT; [secure]
Set-Cookie的每個屬性解釋如下:
•Customer=huangxp 一個"名稱=值"對,把名稱customer設定為值"huangxp",這個屬性在Cookie中必須有。 •path=/foo 控制哪些訪問能夠觸發cookie 的傳送。如果沒有指定path,cookie 會在所有對此站點的HTTP 傳送時傳送。如果path=/directory,只有訪問/directory 下面的網頁時,cookie才被髮送。在這個例子中,使用者在訪問目錄/foo下的內容時,瀏覽器將傳送此cookie。如果指定了path,但是path與當前訪問的url不符,則此cookie將被忽略。 •domain=.ibm.com 指定cookie被髮送到哪臺計算機上。正常情況下,cookie只被送回最初向用戶傳送cookie 的計算機。在這個例子中,cookie 會被髮送到任何在.ibm.com域中的主機。如果domain 被設為空,domain 就被設定為和提供cookie 的Web 伺服器相同。如果domain不為空,並且它的值又和提供cookie的Web伺服器域名不符,這個Cookie將被忽略。 •expires= Wednesday, 19-OCT-05 23:12:40 GMT 指定cookie 失效的時間。如果沒有指定失效時間,這個cookie 就不會被寫入計算機的硬碟上,並且只持續到這次會話結束。 •secure 如果secure 這個詞被作為Set-Cookie 頭的一部分,那麼cookie 只能通過安全通道傳輸(目前即SSL通道)。否則,瀏覽器將忽略此Cookie。 一旦瀏覽器接收了cookie,這個cookie和對遠端Web伺服器的連續請求將一起被瀏覽器傳送。例如 前一個cookie 被存入瀏覽器並且瀏覽器試圖請求 URL http://www.ibm.com/foo/index.html 時,下面的HTTP 包頭就被髮送到遠端的Web伺服器。
GET /foo/index.html HTTP/1.0Cookie:customer=huangxp
在瞭解了Cookie協議的一些基本內容之後,讓我們看看一次典型的網路瀏覽過程中瀏覽器如何識別和處理Cookie:
•瀏覽器對於Web伺服器應答包頭中Cookie的操作步驟:1. 從Web伺服器的應答包頭中提取所有的cookie。2. 解析這些cookie的組成部分(名稱,值,路徑等等)。3. 判定主機是否允許設定這些cookie。允許的話,則把這些Cookie儲存在本地。 •瀏覽器對Web伺服器請求包頭中所有的Cookie進行篩選的步驟:1. 根據請求的URL和本地儲存cookie的屬性,判斷那些Cookie能被髮送給Web伺服器。2. 對於多個cookie,判定傳送的順序。3. 把需要傳送的Cookie加入到請求HTTP包頭中一起傳送。 以上我們瞭解了在一個典型的瀏覽器與Web伺服器互動的時候,Cookie的傳遞過程。下面我們將看到,如果在MTS代理網路瀏覽的過程中,不對Cookie進行修改,上面的Cookie傳遞過程將無法實現。
:
2. MTS接收使用者的請求,連線遠端目標伺服器 http://www.ibm.com/foo/index.html。目標伺服器做出應答,返回HTTP頭和HTML頁面內容。其中,典型的HTTP頭內容如下:
HTTP/1.1 200 OKDate: Mon, 24 Oct 2005 06:54:41 GMTServer: IBM_HTTP_ServerCache-Control: no-cacheContent-Length: 19885Connection: closeSet-Cookie:customer=huangxp; path=/foo; domain=.ibm.com; expires= Wednesday, 19-OCT-05 23:12:40 GMTContent-Type: text/html
3. MTS不對Set-Cookie後的內容作任何處理,直接把它加到使用者瀏覽器的應答頭上傳送給瀏覽器。
另外,在瀏覽器傳送Cookie的時候也會遇到同樣的問題,同樣如上例,如果瀏覽器裡本來已經儲存了http://www.ibm.com/foo/的Cookie,但由於使用者要通過MTS訪問此站點,瀏覽器經不會把已經儲存的Cookie上轉到MTS中,MTS也就無法把之傳遞到http://ibm.com/foo/上。
基於上面Cookie規範的介紹和例證,我們能看出,瀏覽器在接受某一個站點的Cookie的時候,需要檢查Cookie的引數domain、path、secure,看是否與當前的站點和URL相符,如果不符的話,就會忽略。另一方面。瀏覽器在上傳Cookie的時候,也會根據當前所訪問站點的屬性,上傳相關的Cookie,而其他的Cookie則不予上傳。
至此,我們討論了需要修改Cookie的根本原因在於Cookie規範的限制。