Web 應用中的 Session 介紹

目錄

一、術語session

二、HTTP協議與狀態保持

三、cookie

四、理解session機制

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

六、HttpSession常見問題

七、Session的用法

 

 

一、Session術語

Session,中文經常翻譯爲會話,其本來的含義是指有始有終的一系列動作/消息,比如打電話時從拿起電話撥號到掛斷電話這中間的一系列過程可以稱之爲一個session。有時候我們可以看到這樣的話在一個瀏覽器會話期間,…”,這裏的會話一詞用的就是其本義,是指從一個瀏覽器窗口打開到關閉這個期間。

鑑於http是無狀態的協議,當完成客戶端和服務器的傳遞信息後,就斷開之間的聯繫,這樣就造成了怎麼樣在幾個頁面之間傳遞信息,比如客戶端信息,或者假如是寫一個購物程序,就要記得購物車裏面的信息,jsp提供了四種方法來跟蹤客戶的狀態

1:建立匿名的表格字段

2:使用url傳遞

3:使用持久化的cookies

4:使用session 的會話機制

相對於安全級別來說第四種最高了,session是指在一段時間內客戶端和服務器之間的一連串的相關的交互過程。在一個session中客戶可能會訪問不同的服務器資源,也可能會多次訪問同一個頁面

Session在我們的網絡應用中就是一種客戶端與服務器端保持狀態的解決方案,有時候session也用來指這種解決方案的存儲結構,如xxx保存在session。由於各種用於web開發的語言在一定程度上都提供了對這種解決方案的支持,所以在某種特定語言的語境下,session也被用來指代該語言的解決方案,比如經常把Java裏提供的 javax.servlet.http.HttpSession簡稱爲session

 

二、HTTP協議與狀態保持

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

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

 

三、Cookie

1.什麼是cookies

大家都知道,瀏覽器與WEB服務器之間是使用HTTP協議進行通信的,當某個用戶發出頁面請求時,WEB服務器只是簡單的進行響應,然後就關閉與該用戶的連接。因此當一個請求發送到WEB服務器時,無論其是否是第一次來訪,服務器都會把它當作第一次來對待,這樣的不好之處可想而知。爲了彌補這個缺陷,Netscape開發出了cookie這個有效的工具來保存某個用戶的識別信息,因此人們暱稱爲“小甜餅”。cookies是一種WEB服務器通過瀏覽器在訪問者的硬盤上存儲信息的手段:Netscape Navigator使用一個名爲cookies.txt本地文件保存從所有站點接收的Cookie信息;而IE瀏覽器把Cookie信息保存在類似於C://windows//cookies的目錄下。當用戶再次訪問某個站點時,服務端將要求瀏覽器查找並返回先前發送的Cookie信息,來識別這個用戶。

  Cookies給網站和用戶帶來的好處非常多:

  (1)Cookie能使站點跟蹤特定訪問者的訪問次數、最後訪問時間和訪問者進入站點的路徑

  (2)Cookie能告訴在線廣告商廣告被點擊的次數,從而可以更精確的投放廣告

  (3)Cookie有效期限未到時,Cookie能使用戶在不鍵入密碼和用戶名的情況下進入曾經瀏覽過的一些站點

  (4)Cookie能幫助站點統計用戶個人資料以實現各種各樣的個性化服務

JSP,我們也可以使用Cookie,來編寫一些功能強大的應用程序。怎麼來創建Cookie:

JSP是使用如下的語法格式來創建cookie的:

Cookie cookie_name =new Cookie("Parameter","Value");例如:Cookie newCookie =new Cookie("username","waynezheng"); response.addCookie(newCookie); 

解釋:JSP是調用Cookie對象相應的構造函數Cookie(name,value)用合適的名字和值來創建Cookie,然後 Cookie可以通過HttpServletResponseaddCookie方法加入到Set-Cookie應答頭,本例中Cookie對象有兩個字符串參數:username,waynezheng。注意,名字和值都不能包含空白字符以及下列字符: @ : ;? , " / [ ] ( ) =

2Cookie機制

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

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

cookie的使用是由瀏覽器按照一定的原則在後臺自動發送給服務器的。瀏覽器檢查所有存儲的cookie,如果某個cookie所聲明的作用範圍大於等於將要請求的資源所在的位置,則把該cookie附在請求資源的HTTP請求頭上發送給服務器。意思是麥當勞的會員卡只能在麥當勞的店裏出示,如果某家分店還發行了自己的會員卡,那麼進這家店的時候除了要出示麥當勞的會員卡,還要出示這家店的會員卡。

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;對於Mozilla Firefox0.8,所有的進程和標籤頁都可以共享同樣的cookie。一般來說是用javascriptwindow.open打開的窗口會與原窗口共享內存cookie。瀏覽器對於會話cookie的這種只認cookie不認人的處理方式經常給採用session機制的web應用程序開發者造成很大的困擾。

 

四、Session機制

session機制採用的是在服務器端保持狀態的方案。而cookie機制採用的是在客戶端保持狀態的方案。

當客戶端訪問到一個程序時,程序要爲客戶創建一個session,在創建這個session的時候,服務器首先檢查這個客戶端的請求裏是否已包含了一個session標識(session id),如果已包含一個session id則說明之前已經爲此客戶端創建過session,服務器就按照session id把這個session檢索出來使用(如果檢索不到,可能會新建一個),如果客戶端請求不包含session id,則爲此客戶端創建一個session並且生成一個與此session相關聯的session idsession id的值應該是一個既不會重複,又不容易被找到規律以仿造的字符串,這個session id將被在本次響應中返回給客戶端保存。保存這個session id的方式可以採用cookie,這樣在交互過程中瀏覽器可以自動的按照規則把這個標識發送給服務器。

由於cookie可以被人爲的禁止,必須有其他機制以便在cookie被禁止時仍然能夠把session id傳遞迴服務器。經常被使用的一種技術叫做URL重寫就是把session id直接附加在URL路徑的後面一種是作爲URL路徑的附加信息,表現形式爲http://…../xxx; jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764另一種是作爲查詢字符串附加在URL後面,表現形式爲http://…../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764

Session只有在下列情況下被刪除:

1.程序調用HttpSession.invalidate();

2.距離上一次收到客戶端發送的session id時間間隔超過了session的超時設置;

3.服務器進程被停止(非持久session

我們常說的在一個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保存到硬盤上,當服務器進程重新啓動或這些信息將能夠被再次使用。

常常有這樣的情況,一個大項目被分割成若干小項目開發,爲了能夠互不干擾,要求每個小項目作爲一個單獨的web應用程序開發,可是到了最後突然發現某幾個小項目之間需要共享一些信息,或者想使用session來實現SSO (single sign on),在session中保存login的用戶信息,最自然的要求是應用程序間能夠訪問彼此的session

然而按照Servlet規範,session的作用範圍應該僅僅限於當前應用程序下,不同的應用程序之間是不能夠互相訪問對方的session的。各個應用服務器從實際效果上都遵守了這一規範,但是實現的細節卻可能各有不同,因此解決跨應用程序session共享的方法也各不相同。

首先來看一下Tomcat是如何實現web應用程序之間session的隔離的,從Tomcat設置的cookie路徑來看,它對不同的應用程序設置的cookie路徑是不同的,這樣不同的應用程序所用的session id是不同的,因此即使在同一個瀏覽器窗口裏訪問不同的應用程序,發送給服務器的session id也可以是不同的。

根據這個特性,我們可以推測Tomcatsession的內存結構大致如下。

Tomcat版本3上,我們還可以有一些手段來共享session。對於版本4以上的 Tomcat,只能藉助於第三方的力量,比如使用文件、數據庫、JMS或者客戶端cookieURL參數或者隱藏字段等手段

 

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

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

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

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

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

由於HTTP協議是無狀態的,而出於種種考慮也不希望使之成爲有狀態的,因此,後面兩種方案就成爲現實的選擇。具體來說cookie機制採用的是在客戶端保持狀態的方案,而session機制採用的是在服務器端保持狀態的方案。同時我們也看到,由於採用服務器端保持狀態的方案在客戶端也需要保存一個標識,所以session機制可能需要藉助於cookie機制來達到保存標識的目的,但實際上它還有其他選擇。

具體來說cookie機制採用的是在客戶端保持狀態的方案。它是在用戶端的會話狀態的存貯機制,他需要用戶打開客戶端的cookie支持。cookie的作用就是爲了解決HTTP協議無狀態的缺陷所作的努力.

session機制採用的是一種在客戶端與服務器之間保持狀態的解決方案。同時我們也看到,由於採用服務器端保持狀態的方案在客戶端也需要保存一個標識,所以session機制可能需要藉助於cookie機制來達到保存標識的目的。而session提供了方便管理全局變量的方式

session是針對每一個用戶的,變量的值保存在服務器上,用一個sessionID來區分是哪個用戶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

 

六、HttpSession常見問題

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中放置一個不可序列化的對象在控制檯上會收到一個警告。我所用過的某個iPlanet版本如果session中有不可序列化的對象,在session銷燬時會有一個Exception,很奇怪。

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中配置。

 

七、Session的用法

Session 對象

可以使用 Session 對象存儲特定用戶會話所需的信息。這樣,當用戶在應用程序的 Web 頁之間跳轉時,存儲在 Session 對象中的變量將不會丟失,而是在整個用戶會話中一直存在下去。

當用戶請求來自應用程序的 Web 頁時,如果該用戶還沒有會話,則 Web 服務器將自動創建一個 Session 對象。當會話過期或被放棄後,服務器將終止該會話。

Session 對象最常見的一個用法就是存儲用戶的首選項。例如,如果用戶指明不喜歡查看圖形,就可以將該信息存儲在 Session 對象中。

注意:會話狀態僅在支持 cookie 的瀏覽器中保留。

語法

Session.collection|property|method

集合

Contents 包含已用腳本命令添加到會話中的項目。

StaticObjects 包含通過 <OBJECT> 標記創建的並給定了會話作用域的對象。

屬性

CodePage 將用於符號映射的代碼頁。

LCID 現場標識。

SessionID 返回用戶的會話驗證。

Timeout 應用程序會話狀態的超時時限,以分鐘爲單位。

方法

Abandon 該方法破壞 Session 對象並釋放其資源。

事件

asa 文件中聲明下列事件的腳本。

Session_OnEnd

Session_OnStart

註釋

您可以在 Session 對象中存儲值。存儲在 Session 對象中的信息在會話及會話作用域內有效

 
發佈了11 篇原創文章 · 獲贊 6 · 訪問量 27萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章