2011年12月23日 星期五

WEB應用中的SESSION知多少?


一、Session
二、Cookies
三、Cookies機制
四、Session機制
五、Cookies機制與Session機制的區別和聯繫
六、常見問題
七、Session的用法

SessionWEB上有效的資訊交互手段,因其使用方便、穩定、安全、可靠而被眾多WEB開發者所認知。尤其在互聯網身份驗證、網上電子購物等方面的應用更為廣泛。下面就著重來介紹下Session

一、Session

Session,在漢語中表示通話、會話、對話()、話路[對談時間]的意思,其本來的含義一個終端使用者與交互系統進行通信的時間(間隔),通常是指從註冊(進入系統)到登出(退出系統)之間所經過的時間。比如打電話時從拿起電話撥號到掛斷電話這中間的一系列過程可以稱之為一個Session。有時候我們可以看到這樣的話在一個流覽器會話期間,…”,這裡的會話一詞用的就是這個意思,是指從一個流覽器視窗打開到關閉這個期間。Session在我們的網路應用中就是一種用戶端與伺服器端保持狀態的解決方案,有時候Session也用來指這種解決方案的存儲結構,
 
Session物件,就是用戶端流覽器與伺服器之間建立的互動資訊狀態。每一個不同的用戶連接將得到不同的Session,也就是說Session與用戶之間是一種一對一的關係。Session在用戶進入網站時由伺服器自動產生,並在用戶正常離開網站時釋放。使用Session的好處就在於,可以將很多與使用者相關的資訊,例如使用者的帳號、昵稱等保存到Session中;利用Session,可以跟蹤用戶在網站上的活動。例如:當你上網進入一個網站時,如果你沒有登陸,無論你訪問哪幾個頁面都會跳轉回登陸頁。還有就是你在購物時,不可能把你的東西放到別人的購物車裡去,這就得用一個資訊變數來判斷!

如果能夠提供一些按需生成的動態資訊會使web變得更加有用,就像給有線電視加上點播功能一樣。這種需求一方面迫使HTML逐步添加了表單、腳本、DOM等用戶端行為,另一方面在伺服器端則出現了CGI規範以回應用戶端的動態請求,作為傳輸載體的HTTP協議也添加了檔上載、cookie這些特性。其中cookie的作用就是為了解決HTTP協定無狀態的缺陷所作出的努力。至於後來出現的Session機制則是又一種在用戶端與伺服器之間保持狀態的解決方案。


二、Cookies

CookieWEB上最常用的跟蹤使用者會話方式,當 Cookie被禁止後,一般都用URL重寫來跟蹤會話。Cookie是一種由伺服器發送給客戶的片段資訊,存儲在客戶環境中,並在客戶所有的對伺服器的請求中都要發回它。就好比我們在用IE登陸某個電子購物商城時,IE在得到商品清單頁面的 同時還收到Set-Cookie應答頭資訊,我們打開一個Cookie檔,我們所看到的格式一般都是:
 
CookieNAME=VALUEComment=COMMENTDomain=DOMAINNMAMMax-age=SECONDSPath=PATHsecureVersion=1*DIGIT
其中NAME值對(值對間用分號分隔)是必須的,其餘都是可選的。最重要的資訊當然也在所必須的值對裡了,VALUENAME的值,也是這個Cookie的標識,Max-age定義了Cookie的最長生存時間,其它幾個可選值對可參閱http://www.faqs.org/rfcs/rfc2109.html。當我們選購了某種商品,向伺服器發送選購清單時,會自動在你的請求資訊頭裡加上NAME值對,如果Cookie被禁止,則用URL重寫方式在URL請求位址上附加NAME值對。當Web伺服器收到這個請求後,會檢查該Cookie是否存在,然後相應的跟蹤會話。從以上分析不難理解,其實Web伺服器跟蹤會話就靠Set-Cookie頭資訊,跟蹤NAME值對進行身份驗證。假如我們用非Web終端接收Web伺服器的響應資訊,從中解析出Cookie頭資訊,當再次向Web伺服器發送請求時附加上解析出的Cookie資訊,Web伺服器據此不就可以進行身份認證了嗎?
 
Cookies中文是餅乾的意思,對於為何引用Cookies,從網上查找了一些資料:
在流覽器與WEB伺服器之間是使用HTTP協議進行通信的,當某個使用者發出頁面請求時,WEB伺服器只是簡單的進行回應,然後就關閉與該用戶的連接。因此當一個請求發送到WEB伺服器時,無論其是否是第一次來訪,伺服器都會把它當作第一次來對待,這樣的不好之處可想而知。為了彌補這個缺陷,Netscape開發出了cookie這個有效的工具來保存某個使用者的識別資訊,因此人們昵稱為小甜餅cookies是一種WEB伺服器通過流覽器在訪問者的硬碟上存儲資訊的手段:Netscape Navigator使用一個名為cookies.txt本地檔保存從所有網站接收的Cookie資訊;而IE流覽器把Cookie資訊保存在類似於c:\Internet 暫存檔案\的目錄下。當使用者再次訪問某個網站時,服務端將要求流覽器查找並返回先前發送的Cookie資訊,來識別這個使用者。Cookies給網站和用戶帶來的好處:
  (1)Cookie能使網站跟蹤特定訪問者的訪問次數、最後存取時間和訪問者進入網站的路徑
  (2)Cookie能告訴線上廣告商廣告被點擊的次數,從而可以更精確的投放廣告
  (3)Cookie有效期限未到時,Cookie能使使用者在不鍵入密碼和用戶名的情況下進入曾經流覽過的一些網站
  (4)Cookie能幫助網站統計用戶個人資料以實現各種各樣的個性化服務,其實,cookie的作用就是為了解決HTTP協定無狀態的缺陷所作的努力.

三.Cookie機制
Cookie機制採用的是在用戶端保持狀態的方案。

Cookie機制,就是當伺服器對訪問它的用戶生成了一個Session的同時伺服器通過在HTTP的回應頭中加上一行特殊的指示以提示流覽器按照指示生成相應的cookie,保存在用戶端,裡面記錄著使用者當前的資訊,當使用者再次訪問伺服器時,流覽器檢查所有存儲的cookie,如果某個cookie所聲明的作用範圍大於等於將要請求的資源所在的位置也就是對應的Cookie檔。 若存在,則把該cookie附在請求資源的HTTP請求頭上發送給伺服器,例如:當我們登陸了一個網站,並且填寫了有關資料,以本站會員的名義登陸上了有關網頁,這時你把流覽器關閉,再重啟進入該網站的某一個頁面時是以你登陸過的會員進去的,當然,不是所有網站都是這樣,我們知道,cookie的保存有臨時性的和持久性的,大多都是臨時性的,也就是cookie只保存在用戶端的記憶體中,而沒有保存在硬碟上,當關閉流覽器,cookie也就銷毀。以下是有關cookie機制的一些具體說明:

cookie的內容主要包括:名字,值,過期時間,路徑和域。
其中域可以指定某一個域比如.google.com,相當於總店招牌,比如寶潔公司,也可以指定一個域下的具體某台機器比如www.google.com或者froogle.google.com,可以用飄柔來做比。
路徑就是跟在功能變數名稱後面的URL路徑,比如/或者/foo等等,可以用某飄柔專櫃做比。路徑與域合在一起就構成了cookie的作用範圍。
如果不設置過期時間,則表示這個cookie的生命期為流覽器會話期間,只要關閉流覽器窗口,cookie就消失了。這種生命期為流覽器會話期的 cookie被稱為會話cookie。會話cookie一般不存儲在硬碟上而是保存在記憶體裡,當然這種行為並不是規範規定的。如果設置了過期時間,流覽器就會把cookie保存到硬碟上,關閉後再次打開流覽器,這些cookie仍然有效直到超過設定的過期時間。
存儲在硬碟上的cookie可以在不同的流覽器進程間共用,比如兩個IE視窗。而對於保存在記憶體裡的cookie,不同的流覽器有不同的處理方式。對於微軟的IE流覽器,在一個打開的視窗上按Ctrl-N(或者從檔功能表)打開的視窗可以與原視窗共用,而使用其他方式新開的IE進程則不能共用已經打開的視窗的記憶體cookie;對於火狐狸firefox流覽器,所有的進程和標籤頁都可以共用同樣的cookie。一般來說是用javascriptwindow.open打開的視窗會與原視窗共用記憶體cookie。流覽器對於會話cookie的這種只認cookie不認人的處理方式經常給採用Session機制的web應用程式開發者造成很大的困擾。


四、Session機制

Session機制採用的是在伺服器端保持狀態的方案。
當用戶訪問到一個伺服器,伺服器就要為該用戶創建一個SESSION,在創建這個SESSION的時候,伺服器首先檢查這個用戶發來的請求裡是否包含了一個SESSIONID,如果包含了一個SESSIONID則說明之前該用戶已經登陸過並為此用戶創建過SESSION,那伺服器就按照這個SESSIONID把這個SESSION在伺服器的記憶體中查找出來(如果查找不到,就有可能為他新創建一個),如果用戶端請求裡不包含有SESSIONID,則為該用戶端創建一個SESSION並生成一個與此SESSION相關的SESSIONID。這個SESSIONID是唯一的、不重複的、不容易找到規律的字串,這個SESSIONID將被在本次回應中返回到用戶端保存,而保存這個SESSIONID的正是COOKIE,這樣在交互過程中流覽器可以自動的按照規則把這個標識發送給伺服器。
我們知道在IE中,我們可以在工具的internet選項中把COOKIE禁止,那麼會不會出現把用戶端的COOKIE禁止了,SESSIONID就無法再用了呢?找了一些資料說明,可以有其他機制在COOKIE被禁止時仍然能夠把Session id傳遞回伺服器。經常被使用的一種技術叫做URL重寫,就是把Session id直接附加在URL路徑的後面一種是作為URL路徑的附加資訊,表現形式為:
http://…./xxx;jSession=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
http://…./xxx;jSession=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
另一種是作為查詢字串附加在URL後面,表現形式為:
http://…../xxx?jSession=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
http://…../xxx?jSession=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
還有一種就是表單隱藏欄位。就是伺服器會自動修改表單,添加一個隱藏欄位,以便在表單提交時能夠把Session id傳遞回伺服器。這裡就不介紹了。
我們常說的在一個IE被打開是創建一個Session,當關閉IESession也就被刪除,事實上,除非程式通知伺服器刪除Session,否則Session會被伺服器一直保留,直到Session的失效時間到了自動刪除。伺服器不知道IE被關閉,IE不會主動在其關閉之前通知伺服器它將要關閉。程式一般都是在使用者做註銷時刪除Session。我們產生這種錯覺的原因是:一般Session機制都使用cookie來保存Session id,而一旦關閉IE流覽器,Session id就不存在了,再連接伺服器時找不到原來的Session.如果伺服器設置的cookie被保存到硬碟上,或者使用某種手段改寫流覽器發出的 HTTP請求頭,把原來的Session id發送給伺服器,則再次打開流覽器仍然能夠找到原來的Session。恰恰是由於關閉流覽器不會導致Session被刪除,迫使伺服器為seesion設置了一個失效時間,當距離用戶端上一次使用Session的時間超過這個失效時間時,伺服器就可以認為用戶端已經停止了活動,才會把Session刪除以節省存儲空間。
一般情況下,Session都是存儲在記憶體裡,當伺服器進程被停止或者重啟的時候,記憶體裡的Session也會被清空,如果設置了Session的持久化特性,伺服器就會把Session保存到硬碟上,當伺服器進程重新開機或這些資訊將能夠被再次使用。


五、cookie機制與Session機制的區別和聯繫

具體來說cookie機制採用的是在用戶端保持狀態的方案,而Session機制採用的是在伺服器端保持狀態的方案。同時我們也看到,由於在伺服器端保持狀態的方案在用戶端也需要保存一個標識,所以Session機制可能需要借助於cookie機制來達到保存標識的目的,但實際上還有其他選擇。例如,我們經常用到的會員卡,也就相當於這種情況。消費到了一定程度就有獎,就如下面例子說明:
1.
發給顧客一張卡片,上面記錄著消費的數量,一般還有個有效期限。每次消費時,如果顧客出示這張卡片,則此次消費就會與以前或以後的消費相聯繫起來。這種做法就是在用戶端保持狀態。

2、發給顧客一張會員卡,除了卡號之外什麼資訊也不紀錄,每次消費時,如果顧客出示該卡片,則店員在店裡的紀錄本上找到這個卡號對應的紀錄添加一些消費資訊。這種做法就是在伺服器端保持狀態。
以下是一些關於兩者的區別與聯繫:
具體來說cookie機制採用的是在用戶端保持狀態的方案。它是在使用者端的會話狀態的存貯機制,他需要使用者打開用戶端的cookie支援。cookie的作用就是為了解決HTTP協定無狀態的缺陷所作的努力.Session機制採用的是一種在用戶端與伺服器之間保持狀態的解決方案。同時我們也看到,由於採用伺服器端保持狀態的方案在用戶端也需要保存一個標識,所以Session機制可能需要借助於cookie機制來達到保存標識的目的。而Session提供了方便管理全域變數的方式。

Session是針對每一個使用者的,變數的值保存在伺服器上,用一個Session來區分是哪個使用者Session變數,這個值是通過用戶的流覽器在訪問的時候返回給伺服器,當客戶禁用cookie時,這個值也可能設置為由get來返回給伺服器。
就安全性來說:當你訪問一個使用Session 的網站,同時在自己機子上建立一個cookie,建議在伺服器端的SESSION機制更安全些.因為它不會任意讀取客戶存儲的資訊。
正統的cookie分發是通過擴展HTTP協議來實現的,伺服器通過在HTTP的回應頭中加上一行特殊的指示以提示流覽器按照指示生成相應的cookie
從網路服務器觀點看所有HTTP請求都獨立於先前請求。就是說每一個HTTP回應完全依賴於相應請求中包含的資訊.
狀態管理機制克服了HTTP的一些限制並允許網路用戶端端及伺服器端維護請求間的關係。在這種關係維持的期間叫做會話(Session)

Cookies是伺服器在本地機器上存儲的小段文本並隨每一個請求發送至同一個伺服器。IETF RFC 2965 HTTP State Management Mechanism 是通用cookie規範。網路服務器用HTTP頭向用戶端發送cookies,在客戶終端,流覽器解析這些cookies並將它們保存為一個本地檔,它會自動將同一伺服器的任何請求縛上這些cookies
來看一下Tomcat是如何實現web應用程式之間session的隔離的,從Tomcat設置的cookie路徑來看,它對不同的應用程式設置的cookie路徑是不同的,這樣不同的應用程式所用的session id是不同的,因此即使在同一個流覽器視窗裡訪問不同的應用程式,發送給伺服器的session id也可以是不同的。


六、常見問題

1Session在何時被創建

Session在有用戶端訪問時就被創建,然而事實是直到某server端程式調用HttpServletRequest.getSession(true)這樣的語句時才被創建,注意如果JSP沒有顯示的使用 <%@page Session=”false”%> 關閉Session,則JSP檔在編譯成Servlet時將會自動加上這樣一條語句HttpSession Session = HttpServletRequest.getSession(true);這也是JSP中隱含的Session物件的來歷。由於Session會消耗記憶體資源,因此,如果不打算使用Session,應該在所有的JSP中關閉它。

2Session何時被刪除
綜合前面的討論,Session在下列情況下被刪除:

a.程式調用HttpSession.invalidate();

b.距離上一次收到用戶端發送的Session id時間間隔超過了Session的超時設置;
.
c.伺服器進程被停止(非持久Session)。

3、如何做到在流覽器關閉時刪除Session
嚴格的講,做不到這一點。可以做一點努力的辦法是在所有的用戶端頁面裡使用javascript代碼window.oncolose來監視流覽器的關閉動作,然後向伺服器發送一個請求來刪除Session。但是對於流覽器崩潰或者強行殺死進程這些非常規手段仍然無能為力。
 
4、有個HttpSessionListener是怎麼回事
你可以創建這樣的listener去監控Session的創建和銷毀事件,使得在發生這樣的事件時你可以做一些相應的工作。注意是Session的創建和銷毀動作觸發listener,而不是相反。類似的與HttpSession有關的listener還有HttpSessionBindingListenerHttpSessionActivationListener HttpSessionAttributeListener
 
5、存放在Session中的物件必須是可序列化的嗎
不是必需的。要求物件可序列化只是為了Session能夠在集群中被複製或者能夠持久保存或者在必要時server能夠暫時把Session交換出記憶體。在Weblogic ServerSession中放置一個不可序列化的物件在控制台上會收到一個警告。
 
6、開兩個流覽器視窗訪問應用程式會使用同一個Session還是不同的Session
Session來說是只認id不認人,因此不同的流覽器,不同的視窗打開方式以及不同的cookie存儲方式都會對這個問題的答案有影響。
 
7、如何防止使用者打開兩個流覽器視窗操作導致的Session混亂
這個問題與防止表單多次提交是類似的,可以通過設置用戶端的權杖來解決。就是在伺服器每次生成一個不同的id返回給用戶端,同時保存在Session裡,用戶端提交表單時必須把這個id也返回伺服器,程式首先比較返回的id與保存在Session裡的值是否一致,如果不一致則說明本次操作已經被提交過了。可以參看《J2EE核心模式》關於展示層模式的部分。需要注意的是對於使用javascript window.open打開的視窗,一般不設置這個id,或者使用單獨的id,以防主視窗無法操作,建議不要再window.open打開的視窗裡做修改操作,這樣就可以不用設置。
 
8、為什麼Session不見了
排除Session正常失效的因素之外,伺服器本身的可能性應該是微乎其微的;理論上防火牆或者代理伺服器在cookie處理上也有可能會出現問題。出現這一問題的大部分原因都是程式的錯誤,最常見的就是在一個應用程式中去訪問另外一個應用程式。
 
9、伺服器關掉後,當前Session會丟掉嗎
這個取決於你使用什麼樣的web伺服器以及web伺服器是如何配置的。tomcatshutdown前默認會自動將Session保存到指定的目錄中,重新開機是重新載入,因此tomcat重新啟動後,Session是可以繼續使用的。此外,你還何以將Session保存到資料庫中,這個要在server.xml中配置。
 
10Cookie的過期和Session的超時有什麼區別
會話的超時由伺服器來維護,它不同於Cookie的失效日期。首先,會話一般基於駐留記憶體的cookie不是持續性的cookie,因而也就沒有截至日期。即使截取到JSESSION cookie,並為它設定一個失效日期發送出去。流覽器會話和伺服器會話也會截然不同。


七、Session的用法

Session 對象
可以使用 Session 物件存儲特定使用者會話所需的資訊。這樣,當使用者在應用程式的 Web 頁之間跳轉時,存儲在 Session 物件中的變數將不會丟失,而是在整個用戶會話中一直存在下去。
當使用者請求來自應用程式的 Web 頁時,如果該用戶還沒有會話,則 Web 伺服器將自動創建一個 Session 物件。當會話過期或被放棄後,伺服器將終止該會話。
Session
Session 物件最常見的一個用法就是存儲使用者的首選項。例如,如果使用者指明不喜歡查看圖形,就可以將該資訊存儲在 Session 物件中。
注意:會話狀態僅在支援 cookie 的流覽器中保留。
語法
Session.collection|property|method
Session.collection|property|method
集合
Contents
Contents 包含已用指令碼命令添加到會話中的項目。
StaticObjects
StaticObjects 包含通過 <OBJECT> 標記創建的並給定了會話作用域的物件。
屬性
CodePage
CodePage 將用於符號映射的內碼表。
LCID
LCID 現場標識。
SessionID
SessionID 返回用戶的會話驗證。
Timeout
Timeout 應用程式會話狀態的超時時限,以分鐘為單位。
方法
Abandon
Abandon 該方法破壞 Session 物件並釋放其資源。
事件
asa
asa 檔中聲明下列事件的腳本。
Session_OnEnd
Session_OnStart
Session_OnEnd
Session_OnStart
注釋
您可以在 Session 物件中存儲值。存儲在 Session 物件中的資訊在會話及會話作用域內有效。


1 則留言:

李碩軒 提到...

字體有點小,閱讀起來有點吃力,但還是非常感謝您的教學