Session機制

Session:在計算機中,尤其是在網路套用中,稱為“會話”。它具體是指一個終端用戶與互動系統進行通信的時間間隔,通常指從註冊進入系統到註銷退出系統之間所經過的時間。Session實際上是一個特定的時間概念。

術語session

在我的經驗里,session這個詞被濫用的程度大概僅次於transaction,更加有趣的是transaction與session在某些語境下的含義是相同的。

session其本來的含義是指有始有終的一系列動作/訊息,比如打電話時從拿起電話撥號到掛斷電話這中間的一系列過程可以稱之為一個 session。有時候我們可以看到這樣的話“在一個瀏覽器會話期間,...”,這裡的會話一詞用的就是其本義,是指從一個瀏覽器視窗打開到關閉這個期間 ①。

最混亂的是“用戶(客戶端)在一次會話期間”這樣一句話,它可能指用戶的一系列動作(一般情況下是同某個具體目的相關的一系列動作,比如從登錄到選購商品到結賬登出這樣一個網上購物的過程,有時候也被稱為一個transaction),然而有時候也可能僅僅是指一次連線,也有可能是指含義①,其中的差別只能靠上下文來推斷②。

然而當session一詞與網路協定相關聯時,它又往往隱含了“面向連線”和/或“保持狀態”這樣兩個含義, “面向連線”指的是在通信雙方在通信之前要先建立一個通信的渠道,比如打電話,直到對方接了電話通信才能開始,與此相對的是寫信,在你把信發出去的時候你並不能確認對方的地址是否正確,通信渠道不一定能建立,但對發信人來說,通信已經開始了。“保持狀態”則是指通信的一方能夠把一系列的訊息關聯起來,使得訊息之間可以互相依賴,比如一個服務員能夠認出再次光臨的老顧客並且記得上次這個顧客還欠店裡一塊錢。這一類的例子有“一個TCP session”或者 “一個POP3 session”③。

而到了web伺服器蓬勃發展的時代,session在web開發語境下的語義又有了新的擴展,它的含義是指一類用來在客戶端與伺服器之間保持狀態的解決方案④。有時候session也用來指這種解決方案的存儲結構,如“把xxx保存在session 里”⑤。

由於各種用於web開發的語言在一定程度上都提供了對這種解決方案的支持,所以在某種特定語言的語境下,session也被用來指代該語言的解決方案,比如 經常把Java里提供的javax.servlet.http.HttpSession簡稱為session⑥。

鑒於這種混亂已不可改變,本文中session一詞的運用也會根據上下文有不同的含義,請大家注意分辨。

在本文中,使用中文“瀏覽器會話期間”來表達含義①,使用“session機制”來表達含義④,使用“session”表達含義⑤,使用具

體的“HttpSession”來表達含義⑥

PHP Session 變數

PHP session 變數用於存儲關於用戶會話(session)的信息,或者更改用戶會話(session)的設定。Session 變數存儲單一用戶的信息,並且對於應用程式中的所有頁面都是可用的。

您在計算機上操作某個應用程式時,您打開它,做些更改,然後關閉它。這很像一次對話(Session)。計算機知道您是誰。它清楚您在何時打開和關閉應用程式。然而,在網際網路上問題出現了:由於 HTTP 地址無法保持狀態,Web 伺服器並不知道您是誰以及您做了什麼。

PHP session 解決了這個問題,它通過在伺服器上存儲用戶信息以便隨後使用(比如用戶名稱、購買商品等)。然而,會話信息是臨時的,在用戶離開網站後將被刪除。如果您需要永久存儲信息,可以把數據存儲在資料庫中。

Session 的工作機制是:為每個訪客創建一個唯一的 id (UID),並基於這個 UID 來存儲變數。UID 存儲在 cookie 中,或者通過 URL 進行傳導。

HTTP協定與狀態保持

HTTP 協定本身是無狀態的,這與HTTP協定本來的目的是相符的,客戶端只需要簡單的向伺服器請求下載某些檔案,無論是客戶端還是伺服器都沒有必要紀錄彼此過去的行為,每一次請求之間都是獨立的,好比一個顧客和一個自動售貨機或者一個普通的(非會員制)

大賣場之間的關係一樣。

然而聰明(或者貪心?)的人們很快發現如果能夠提供一些按需生成的動態信息會使web變得更加有用,就像給有線電視加上點播功能一樣。這種需求一方面迫使HTML逐步添加了表單、腳本、DOM等客戶端行為,另一方面在伺服器端則出現了CGI規範以回響客戶端的

動態請求,作為傳輸載體的HTTP協定也添加了檔案上載、 cookie這些特性。其中cookie的作用就是為了解決HTTP協定無狀態的缺陷。至於後來出現的session機制則是又一種在客戶端與伺服器之間保持狀態的解決方案。

讓我們用幾個例子來描述一下cookie和session機制之間的區別與聯繫。筆者曾經常去的一家咖啡店有喝5杯咖啡免費贈一杯咖啡的優惠,然而一次性消費5杯咖啡的機會微乎其微,這時就需要某種方式來紀錄某位顧客的消費數量。想像一下其實也無外乎下面的幾種方案:

1、該店的店員很厲害,能記住每位顧客的消費數量,只要顧客一走進咖啡店,店員就知道該怎么對待了。這種做法就是協定本身支持狀態。

2、發給顧客一張卡片,上面記錄著消費的數量,一般還有個有效期限。每次消費時,如果顧客出示這張卡片,則此次消費就會與以前或以後的消費相聯繫起來。這種做法就是在客戶端保持狀態。

3、發給顧客一張會員卡,除了卡號之外什麼信息也不紀錄,每次消費時,如果顧客出示該卡片,則店員在店裡的紀錄本上找到這個卡號對應的紀錄添加一些消費信息。這種做法就是在伺服器端保持狀態。

由於HTTP協定是無狀態的,而出於種種考慮也不希望使之成為有狀態的,因此,後面兩種方案就成為現實的選擇。具體來說cookie機制

採用的是在客戶端保持狀態的方案,而session機制採用的是在伺服器端保持狀態的方案。同時我們也看到,由於採用伺服器端保持狀態的方案在客戶端也需要保存一個標識,所以session機制可能需要藉助於cookie機制來達到保存標識的目的,但實際上它還有其他選擇。

理解cookie機制

cookie機制的基本原理就如上面的例子一樣簡單,但是還有幾個問題需要解決:“會員卡”如何分發;“會員卡”的內容;以及客戶

如何使用“會員卡”。

正統的cookie分發是通過擴展HTTP協定來實現的,伺服器通過在HTTP的回響頭中加上一行特殊的指示以提示瀏覽器按照指示生成相應的cookie。然而純粹的客戶端腳本如JavaScript或者VBScript也可以生成cookie。

而cookie 的使用是由瀏覽器按照一定的原則在後台自動傳送給伺服器的。瀏覽器檢查所有存儲的cookie,如果某個cookie所聲明的作用範圍大於等於將要請求的資源所在的位置,則把該cookie附在請求資源的HTTP請求頭上傳送給伺服器。意思是麥當勞的會員卡

只能在麥當勞的店裡出示,如果某家分店還發行了自己的會員卡,那么進這家店的時候除了要出示麥當勞的會員卡,還要出示這家店的會員卡。

cookie的內容主要包括:名字,值,過期時間,路徑和域。

路徑就是跟在域名後面的URL路徑,比如/或者/foo等等,可以用某飛柔專櫃做比。

路徑與域合在一起就構成了cookie的作用範圍。

如果不設定過期時間,則表示這個cookie的生命期為瀏覽器會話期間,只要關閉瀏覽器視窗,cookie就消失了。這種生命期為

瀏覽器會話期的 cookie被稱為會話cookie。會話cookie一般不存儲在硬碟上而是保存在記憶體里,當然這種行為並不是規範規定的。

如果設定了過期時間,瀏覽器就會把cookie保存到硬碟上,關閉後再次打開瀏覽器,這些cookie仍然有效直到超過設定的過期時間。

存儲在硬碟上的cookie 可以在不同的瀏覽器進程間共享,比如兩個IE視窗。而對於保存在記憶體里的cookie,不同的瀏覽器有不同的處理方式。對於IE,在一個打開的視窗上按 Ctrl-N(或者從檔案選單)打開的視窗可以與原視窗共享,而使用其他方式新開的

IE進程則不能共享已經打開的視窗的記憶體cookie;對於 Mozilla Firefox0.8,所有的進程和標籤頁都可以共享同樣的cookie。

一般來說是用javascript的window.open打開的視窗會與原視窗共享記憶體cookie。瀏覽器對於會話cookie的這種只認cookie不認人的處理方式經常給採用session機制的web應用程式開發者造成很大的困擾。

理解session機制

session機制是一種伺服器端的機制,伺服器使用一種類似於散列表的結構(也可能就是使用散列表)來保存信息。

當程式需要為某個客戶端的請求創建一個session的時候,伺服器首先檢查這個客戶端的請求里是否已包含了一個session標識 - 稱為session id,如果已包含一個session id則說明以前已經為此客戶端創建過session,伺服器就按照session id把這個 session檢索出來使用(如果檢索不到,可能會新建一個),如果客戶端請求不包含session id,則為此客戶端創建一個session並且生成一個與

此session相關聯的session id,session id的值應該是一個既不會重複,又不容易被找到規律以仿造的字元串,這個 session id將被在本次回響中返回給客戶端保存。

保存這個session id的方式可以採用cookie,這樣在互動過程中瀏覽器可以自動的按照規則把這個標識發揮給伺服器。一般這個

cookie的名字都是類似於SEEESIONID,而。比如weblogic對於web應用程式生成的cookie,

JSESSIONID= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764,它的名字就是 JSESSIONID。

由於cookie可以被人為的禁止,必須有其他機制以便在cookie被禁止時仍然能夠把session id傳遞迴伺服器。經常被使用的一種技術叫做URL重寫,就是把session id直接附加在URL路徑的後面,附加方式也有兩種,一種是作為URL路徑的附加信息,表現形式為

http://...../xxx;jsessionid= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764

另一種是作為查詢字元串附加在URL後面,表現形式為

http://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764

這兩種方式對於用戶來說是沒有區別的,只是伺服器在解析的時候處理的方式不同,採用第一種方式也有利於把session id的信息和正常程式參數區分開來。

為了在整個互動過程中始終保持狀態,就必須在每個客戶端可能請求的路徑後面都包含這個session id。

理解javax.servlet.http.HttpSession

HttpSession是Java平台對session機制的實現規範,因為它僅僅是個接口,具體到每個web套用伺服器的提供商,除了對規範支持之外,仍然會有一些規範里沒有規定的細微差異。這裡我們以BEA的Weblogic Server8.1作為例子來演示。

首先,Weblogic Server提供了一系列的參數來控制它的HttpSession的實現,包括使用cookie的開關選項,使用URL重寫的開關選項,

session持久化的設定,session失效時間的設定,以及針對cookie的各種設定,比如設定cookie的名字、路徑、域, cookie的生存時間等。

一般情況下,session都是存儲在記憶體里,當伺服器進程被停止或者重啟的時候,記憶體里的session也會被清空,如果設定了session

的持久化特性,伺服器就會把session保存到硬碟上,當伺服器進程重新啟動或這些信息將能夠被再次使用, Weblogic Server支持的持久性方式包括檔案、資料庫、客戶端cookie保存和複製。

複製嚴格說來不算持久化保存,因為session實際上還是保存在記憶體里,不過同樣的信息被複製到各個cluster內的伺服器進程中,這樣即使某個伺服器進程停止工作也仍然可以從其他進程中取得session。

cookie生存時間的設定則會影響瀏覽器生成的cookie是否是一個會話cookie。默認是使用會話cookie。有興趣的可以用它來試驗

我們在第四節里提到的那個誤解。

cookie的路徑對於web應用程式來說是一個非常重要的選項,Weblogic Server對這個選項的默認處理方式使得它與其他伺服器有明顯的區別。後面我們會專題討論。

相關詞條

相關搜尋

熱門詞條

聯絡我們