1. 程式人生 > >深入理解Session和cookie原理

深入理解Session和cookie原理

一、概述

Session 與 Cookie 的作用都是為了保持訪問使用者與後端伺服器的互動狀態。它們有各自的優點,也有各自的缺陷,然而具有諷刺意味的是它們的優點和它們的使用場景又是矛盾的。例如,使用 Cookie 來傳遞資訊時,隨著 Cookie 個數的增多和訪問量的增加,它佔用的網路頻寬也很大,試想假如 Cookie 佔用 200 個位元組,如果一天的 PV 有幾億,它要佔用多少頻寬?所以有大訪問量的時候希望用 Session,但是 Session 的致命弱點是不容易在多臺伺服器之間共享,所以這也限制了 Session 的使用。

Cookie 的作用我想大家都知道,通俗地說就是當一個使用者通過 HTTP 協議訪問一個伺服器的時候,這個伺服器會將一些 Key/Value 鍵值對返回給客戶端瀏覽器,並給這些資料加上一些限制條件,在條件符合時這個使用者下次訪問這個伺服器的時候,資料又被完整地帶回給伺服器。這個作用就像您去超市購物時,第一次給您辦張購物卡,這個購物卡里存放了一些您的個人資訊,下次您再來這個連鎖超市時,超市會識別您的購物卡,下次直接購物就好了。

當初 W3C 在設計 Cookie 時實際上考慮的是為了記錄使用者在一段時間內訪問 Web 應用的行為路徑。由於 HTTP 協議是一種無狀態協議,當用戶的一次訪問請求結束後,後端伺服器就無法知道下一次來訪問的還是不是上次訪問的使用者,在設計應用程式時,我們很容易想到兩次訪問是同一人訪問與不同的兩個人訪問對程式設計和效能來說有很大的不同。例如,在一個很短的時間內,如果與使用者相關的資料被頻繁訪問,可以針對這個資料做快取,這樣可以大大提高資料的訪問效能。Cookie 的作用正是在此,由於是同一個客戶端發出的請求,每次發出的請求都會帶有第一次訪問時服務端設定的資訊,這樣服務端就可以根據 Cookie 值來劃分訪問的使用者了。

1、Cookie 屬性項

當前 Cookie 有兩個版本:Version 0 和 Version 1。通過它們有兩種設定響應頭的標識,分別是 “Set-Cookie”和“Set-Cookie2”。這兩個版本的屬性項有些不同。

  • Version 0 屬性項介紹

這裡寫圖片描述

  • Version 1 屬性項介紹

這裡寫圖片描述
以上兩個版本的 Cookie 中設定的 Header 頭的識別符號是不同的,我們常用的是 Set-Cookie:userName=“junshan”; Domain=“xulingbo.net”,這是 Version 0 的形式。針對 Set-Cookie2 是這樣設定的:Set-Cookie2:userName=“junshan”; Domain=“xulingbo.net”; Max-Age=1000

。但是在 Java Web 的 Servlet 規範中並不支援 Set-Cookie2 響應頭,在實際應用中 Set-Cookie2 的一些屬性項卻可以設定在 Set-Cookie 中,如這樣設定:Set-Cookie:userName=“junshan”; Version=“1”;Domain=“xulingbo.net”;Max-Age=1000

2、Cookie 如何工作

當我們用如下方式建立 Cookie 時:

 String getCookie(Cookie[] cookies, String key) { 
        if (cookies != null) { 
            for (Cookie cookie : cookies) { 
                if (cookie.getName().equals(key)) { 
                    return cookie.getValue(); 
                } 
            } 
        } 
        return null; 
    } 

    @Override 
    public void doGet(HttpServletRequest request, 
                      HttpServletResponse response) 
            throws IOException, ServletException { 
        Cookie[] cookies = request.getCookies(); 
        String userName = getCookie(cookies, "userName"); 
        String userAge = getCookie(cookies, "userAge"); 
        if (userName == null) { 
            response.addCookie(new Cookie("userName", "junshan")); 
        } 
        if (userAge == null) { 
            response.addCookie(new Cookie("userAge", "28")); 
        } 
        response.getHeaders("Set-Cookie"); 
 }

Cookie 是如何加到 HTTP 的 Header 中的?當我們用 Servlet 3.0 規範來建立一個 Cookie 物件時,該 Cookie 既支援 Version 0 又支援 Version 1,如果您設定了 Version 1 中的配置項,即使您沒有設定版本號,Tomcat 在最後構建 HTTP 響應頭時也會自動將 Version 的版本設定為 1。下面看一下 Tomcat 是如何呼叫 addCookie 方法。真正構建 Cookie 是在 org.apache.catalina.connector. Response 類中完成的,呼叫 generateCookieString 方法將 Cookie 物件構造成一個字串,構造的字串的格式如 userName=“junshan”;Version=“1”; Domain=“xulingbo.net”; Max-Age=1000。然後將這個字串命名為 Set-Cookie 新增到 MimeHeaders 中。

在這裡有幾點需要注意:

  • 建立的 Cookie 的 NAME 不能和 Set-Cookie 或者 Set-Cookie2 的屬性項值一樣,如果一樣會拋 IllegalArgumentException 異常。

  • 建立 Cookie 的 NAME 和 VALUE 的值不能設定成非 ASSIC 字元,如果要使用中文,可以通過 URLEncoder 將其編碼,否則將會拋 IllegalArgumentException 異常。

  • 當 NAME 和 VALUE 的值出現一些 TOKEN 字元(如“\”、“,”等)時,構建返回頭會將該 Cookie 的 Version 自動設定為 1。

  • 當該 Cookie 的屬性項中出現 Version 為 1 的屬性項時,構建 HTTP 響應頭同樣會將 Version 設定為 1。

當我們通過 response.addCookie 建立多個 Cookie 時,這些 Cookie 最終是在一個 Header 項中還是以獨立的 Header 存在的?通俗地說也就是我們每次建立 Cookie 時是否都是建立一個以 NAME 為 Set-Cookie 的 MimeHeaders ?答案是肯定的。每次呼叫 addCookie 的時候,最終都會建立一個 Header,但是我們還不知道最終在請求返回時構造 HTTP 響應頭是否將相同 Header 標識的 Set-Cookie 值進行合併。
我們找到 Tomcat 最終構造 HTTP 響應頭的程式碼,這段程式碼位於 org.apache.coyote.http11. Http11Processor 類的 prepareResponse 方法中,如下所示:

 int size = headers.size(); 
 for (int i = 0; i < size; i++) { 
    outputBuffer.sendHeader(headers.getName(i), headers.getValue(i)); 
 }

這段程式碼清楚地表示,在構建 HTTP 返回位元組流時是將 Header 中所有的項順序地寫出,而沒有進行任何修改。所以可以想象瀏覽器在接收 HTTP 協議返回的資料時是分別解析每一個 Header 項的。

前面主要介紹了服務端如何建立 Cookie,下面看一下如何從客戶端獲取 Cookie。
當我們請求某個 URL 路徑時,瀏覽器會根據這個 URL 路徑將符合條件的 Cookie 放在 Request 請求頭中傳回給服務端,服務端通過 request.getCookies() 來取得所有 Cookie。

Cookie 是 HTTP 協議頭中的一個欄位,雖然 HTTP 協議本身對這個欄位並沒有多少限制,但是 Cookie 最終還是儲存在瀏覽器裡,所以不同的瀏覽器對 Cookie 的儲存都有一些限制。
這裡寫圖片描述

三、理解 Session

前面已經介紹了 Cookie 可以讓服務端程式跟蹤每個客戶端的訪問,但是每次客戶端的訪問都必須傳回這些 Cookie,如果 Cookie 很多,這無形地增加了客戶端與服務端的資料傳輸量,而 Session 的出現正是為了解決這個問題。
同一個客戶端每次和服務端互動時,不需要每次都傳回所有的 Cookie 值,而是隻要傳回一個 ID,這個 ID 是客戶端第一次訪問伺服器的時候生成的,而且每個客戶端是唯一的。這樣每個客戶端就有了一個唯一的 ID,客戶端只要傳回這個 ID 就行了,這個 ID 通常是 NANE 為 JSESIONID 的一個 Cookie。

下面詳細講一下 Session 如何基於 Cookie 來工作。實際上有三種方式能可以讓 Session 正常工作:

  • 基於 URL Path Parameter,預設支援。

  • 基於 Cookie,如果沒有修改 Context 容器的 cookies 標識,預設也是支援的。

  • 基於 SSL,預設不支援,只有 connector.getAttribute("SSLEnabled") 為 TRUE 時才支援。

第一種情況下,當瀏覽器不支援 Cookie 功能時,瀏覽器會將使用者的 SessionCookieName 重寫到使用者請求的 URL 引數中,它的傳遞格式如 /path/Servlet;name=value;name2=value2? Name3=value3,其中“Servlet;”後面的 K-V(name=value;name2=value2) 就是要傳遞的 Path Parameters,伺服器會從這個 Path Parameters 中拿到使用者配置的 SessionCookieName。關於這個 SessionCookieName,如果在 web.xml 中配置 session-config 配置項,其 cookie-config 下的 name 屬性就是這個 SessionCookieName 值。如果沒有配置了 session-config 配置項,預設的 SessionCookieName 就是大家熟悉的“JSESSIONID”。需要說明的一點是,與 Session 關聯的 Cookie 與其他 Cookie 沒有什麼不同。接著 Request 根據這個 SessionCookieName 到 Parameters 中拿到 Session ID 並設定到 request.setRequestedSessionId 中。
請注意,如果客戶端也支援 Cookie,Tomcat 仍然會解析 Cookie 中的 Session ID,並會覆蓋 URL 中的 Session ID。
如果是第三種情況,將會根據 javax.servlet.request.ssl_session 屬性值設定 Session ID。

2、Session 如何工作

有了 Session ID 服務端就可以建立 HttpSession 物件了,第一次觸發通過 request.getSession() 方法。如果當前的 Session ID 還沒有對應的 HttpSession 物件,那麼就建立一個新的,並將這個物件加到 org.apache.catalina. Manager 的 sessions 容器中儲存。Manager 類將管理所有 Session 的生命週期,Session 過期將被回收,伺服器關閉,Session 將被序列化到磁碟等。只要這個 HttpSession 物件存在,使用者就可以根據 Session ID 來獲取這個物件,也就達到了狀態的保持。
StandardManager 類負責 Servlet 容器中所有的 StandardSession 物件的生命週期管理。當 Servlet 容器重啟或關閉時 StandardManager 負責持久化沒有過期的 StandardSession 物件,它會將所有的 StandardSession 物件持久化到一個以“SESSIONS.ser”為檔名的檔案中。到 Servlet 容器重啟時,也就是 StandardManager 初始化時,會重新讀取這個檔案解析出所有 Session 物件,重新儲存在 StandardManager 的 sessions 集合中。Session 恢復狀態圖如圖:
這裡寫圖片描述
當 Servlet 容器關閉時 StandardManager 類會呼叫 unload 方法將 sessions 集合中的 StandardSession 物件寫到“SESSIONS.ser”檔案中,然後在啟動時再按照上面的狀態圖重新恢復,注意要持久化儲存 Servlet 容器中的 Session 物件,必須呼叫 Servlet 容器的 stop 和 start 命令,而不能直接結束(kill)Servlet 容器的程序,因為直接結束程序,Servlet 容器沒有機會呼叫 unload 方法來持久化這些 Session 物件。

另外,StandardManager 中的 sessions 集合中的 StandardSession 物件並不是永遠儲存的,否則 Servlet 容器的記憶體將很容易被消耗盡,所以必須給每個 Session 物件定義一個有效時間,超過這個時間 Session 物件將被清除。在 Tomcat 中這個有效時間是 60(maxInactiveInterval 屬性控制)秒,超過 60 秒該 Session 將會過期。檢查每個 Session 是否失效是在 Tomcat 的一個後臺執行緒中完成的(backgroundProcess() 方法中)。過期 Session 狀態圖如圖 :
這裡寫圖片描述
除了後臺程序檢查 Session 是否失效外,當呼叫 request.getSession() 時也會檢查該 Session 是否過期。值得注意的是,request.getSession() 方法呼叫的 StandardSession 永遠都會存在,即使與這個客戶端關聯的 Session 物件已經過期。如果過期,又會重新建立一個全新的 StandardSession 物件,但是以前設定的 Session 值將會丟失。如果您取到了 Session 物件但是通過 session.getAttribute 取不到前面設定的 Session 值,請不要奇怪,因為很可能它已經失效了,請檢查一下 <Manager pathname="" maxInactiveInterval="60" />maxInactiveInterval 配置項的值,如果不想讓 Session 過期可以設定為 -1。但是您要仔細評估一下,網站的訪問量和設定的 Session 的大小,防止將您的 Servlet 容器記憶體撐爆。如果不想自動建立 Session 物件,也可以通過 request.getSession(boolean create) 方法來判斷該客戶端關聯的 Session 物件是否存在。

四、Cookie 安全問題

雖然 Cookie 和 Session 都可以跟蹤客戶端的訪問記錄,但是它們的工作方式顯然是不同的,Cookie 通過把所有要儲存的資料通過 HTTP 協議的頭部從客戶端傳遞到服務端,又從服務端再傳回到客戶端,所有的資料都儲存在客戶端的瀏覽器裡,所以這些 Cookie 資料可以被訪問到,就像我們前面通過 Firefox 的外掛 HttpFox 可以看到所有的 Cookie 值。不僅可以檢視 Cookie,甚至可以通過 Firecookie 外掛新增、修改 Cookie,所以 Cookie 的安全性受到了很大的挑戰。
相比較而言 Session 的安全性要高很多,因為 Session 是將資料儲存在服務端,只是通過 Cookie 傳遞一個 SessionID 而已,所以 Session 更適合儲存使用者隱私和重要的資料。

五、分散式 Session 框架

從前面的分析可知,Session 和 Cookie 各自有優點和缺點。在大型網際網路系統中,單獨使用 Cookie 和 Session 都是不可行的,原因很簡單。因為如果使用 Cookie,可以很好地解決應用的分散式部署問題,大型網際網路應用系統一個應用有上百臺機器,而且有很多不同的應用系統協同工作,由於 Cookie 是將值儲存在客戶端的瀏覽器裡,使用者每次訪問都會將最新的值帶回給處理該請求的伺服器,所以也就解決了同一個使用者的請求可能不在同一臺伺服器處理而導致的 Cookie 不一致的問題。

1、存在哪些問題

這種“誰家的孩子誰抱走”的處理方式的確是大型網際網路的一個比較簡單但是的確可以解決問題的處理方式,但是這種處理方式也會帶來了很多其他問題,如:

  • 客戶端 Cookie 儲存限制。隨著應用系統的增多 Cookie 數量也快速增加,但瀏覽器對於使用者 Cookie 的儲存是有限制的。例如,IE7 之前的 IE 瀏覽器,Cookie 個數的限制是 20 個,後續的版本,包括 Firefox 等,Cookie 個數的限制都是 50 個。總大小不超過 4KB,超過限制就會出現丟棄 Cookie 的現象發生,這會嚴重影響應用系統的正常使用。

  • Cookie 管理的混亂。在大型網際網路應用系統中,如果每個應用系統都自己管理每個應用使用的 Cookie,將會導致混亂,由於通常應用系統都在同一個域名下,Cookie 又有上面一條提到的限制,所以沒有統一管理很容易出現 Cookie 超出限制的情況。

  • 安全令人擔憂。雖然可以通過設定 HttpOnly 屬性防止一些私密 Cookie 被客戶端訪問,但是仍然不能保證 Cookie 無法被篡改。為了保證 Cookie 的私密性通常會對 Cookie 進行加密,但是維護這個加密 Key 也是一件麻煩的事情,無法保證定期來更新加密 Key 也是帶來安全性問題的一個重要因素。

當以上問題不能再容忍下去的時候,就不得不想其他辦法處理了。

2、可以解決哪些問題

既然 Cookie 有以上這些問題,Session 也有它的好處,為何不結合使用 Session 和 Cookie 呢?下面是分散式 Session 框架可以解決的問題:

  • Session 配置的統一管理。

  • Cookie 使用的監控和統一規範管理。

  • Session 儲存的多元化。

  • Session 配置的動態修改。

  • Session 加密 key 的定期修改。

  • 充分的容災機制,保持框架的使用穩定性。

  • Session 各種儲存的監控和報警支援。

  • Session 框架的可擴充套件性,相容更多的 session 機制如 wapSession。

  • 跨域名 Session 與 Cookie 如何共享,現在同一個網站可能存在多個域名,如何將 Session 和 Cookie 在不同的域名之間共享是一個具有挑戰性的問題。

3、總體實現思路

分散式 Session 框架的架構圖如圖所示。
這裡寫圖片描述
為了達成上面所說的幾點目標,我們需要一個服務訂閱伺服器,在應用啟動時可以從這個訂閱伺服器訂閱這個應用需要的可寫 Session 項和可寫 Cookie 項,這些配置的 Session 和 Cookie 可以限制這個應用能夠使用哪些 Session 和 Cookie,甚至可以控制 Session 和 Cookie 可讀或者可寫。這樣可以精確地控制哪些應用可以操作哪些 Session 和 Cookie,可以有效控制 Session 的安全性和 Cookie 的數量。統一通過訂閱伺服器推送配置可以有效地集中管理資源,所以可以省去每個應用都來配置 Cookie,簡化 Cookie 的管理。如果應用要使用一個新增 Cookie,可以通過一個統一的平臺來申請,申請通過才將這個配置項增加到訂閱伺服器。如果是一個所有應用都要使用的全域性 Cookie,那麼只需將這個 Cookie 通過訂閱伺服器統一推送過去就行了,省去了要在每個應用中手動增加 Cookie 的配置。

關於這個訂閱伺服器現在有很多開源的配置伺服器,如 Zookeeper 叢集管理伺服器,可以統一管理所有伺服器的配置檔案。

由於應用是一個叢集,所以不可能將建立的 Session 都儲存在每臺應用伺服器的記憶體中,因為如果每臺伺服器有幾十萬的訪問使用者,伺服器的記憶體肯定不夠用,即使記憶體夠用,這些 Session 也無法同步到這個應用的所有伺服器中。所以要共享這些 Session 必須將它們儲存在一個分散式快取中,可以隨時寫入和讀取,而且效能要很好才能滿足要求。當前能滿足這個要求的系統有很多,如 MemCache 或者淘寶的開源分散式快取系統 Tair 都是很好的選擇。

解決了配置和儲存問題,下面看一下如何存取 Session 和 Cookie。
既然是一個分散式 Session 的處理框架,必然會重新實現 HttpSession 的操作介面,使得應用操作 Session 的物件都是我們實現的 InnerHttpSession 物件,這個操作必須在進入應用之前完成,所以可以配置一個 filter 攔截使用者的請求。
我們可以在應用的 web.xml 中配置一個 SessionFilter,用於在請求到達 MVC 框架之前封裝 HttpServletRequest 和 HttpServletResponse 物件,並建立我們自己的 InnerHttpSession 物件,把它設定到 request 和 response 物件中。這樣應用系統通過 request.getHttpSession() 返回的就是我們建立的 InnerHttpSession 物件了,我們可以攔截 response 的 addCookies 設定的 Cookie。應用建立的所有 Session 物件都會儲存在 InnerHttpSession 物件中,當用戶的這次訪問請求完成時,Session 框架將會把這個 InnerHttpSession 的所有內容再更新到分散式快取中,以便於這個使用者通過其他伺服器再次訪問這個應用系統。另外,為了保證一些應用對 Session 穩定性的特殊要求可以將一些非常關鍵的 Session 再儲存到 Cookie 中,如當分散式快取存在問題時,可以將部分 Session 儲存到 Cookie 中,這樣即使分散式快取出現問題也不會影響關鍵業務的正常執行。

還有一個非常重要的問題就是如何處理跨域名來共享 Cookie 的問題。我們知道 Cookie 是有域名限制的,也就是一個域名下的 Cookie 不能被另一個域名訪問,所以如果在一個域名下已經登入成功,如何訪問到另外一個域名的應用且保證登入狀態仍然有效,這個問題大型網站應該經常會遇到。如何解決這個問題呢?答案是使用SSO單點登入系統。
這裡寫圖片描述
以上方案就是要把信任關係儲存在單獨的SSO系統裡,說起來只是簡單地從客戶端移到了服務端,但其中幾個問題需要重點解決:
1、如何高效儲存大量臨時性的信任資料;
2、如何防止資訊傳遞過程被篡改;
3、如何讓SSO系統信任登入系統和免登系統。
對於第一個問題,一般可以採用類似與Redis的分散式快取的方案,既能提供可擴充套件資料量的機制,也能提供高效訪問。對於第二個問題,一般採取數字簽名的方法,要麼通過數字證書籤名,要麼通過像md5的方式,這就需要SSO系統返回免登URL的時候對需驗證的引數進行md5加密,並帶上token一起返回,最後需免登的系統進行驗證信任關係的時候,需把這個token傳給SSO系統,SSO系統通過對token的驗證就可以辨別資訊是否被改過。對於最後一個問題,可以通過白名單來處理,說簡單點只有在白名單上的系統才能請求生產信任關係,同理只有在白名單上的系統才能被免登入。

六、表單重複提交問題

網站中在很多地方都有表單重複提交問題,一種情況是使用者在網速慢的情況下可能會重複提交表單,還有就是惡意使用者通過程式來發送惡意請求,在這些情況下都要設計一個防止表單重複提交的機制。

要能夠防止表單重複提交,就要標識使用者的每一次訪問請求,使得每一次訪問對服務端來說都是唯一確定的。為了標識使用者的每次訪問請求,可以在使用者請求一個表單域時增加一個隱藏表單項,這個表單項的值每次都是唯一的 token,如:

 <form id=”form” method=”post”> 
 <input type=hidden name=“crsf_tokenvalue=“xxxx”/> 
 </form>

當用戶在請求時生成這個唯一的 token 時,同時將這個 token 儲存在使用者的 Session 中,等使用者提交請求時檢查這個 token 和當前的 Session 中儲存的 token 是否一致。如果一致,說明沒有重複提交,否則使用者提交上來的 token 已經不是當前的這個請求的合法 token。其工作過程如圖所示。
這裡寫圖片描述
生成唯一的 token 需要一個演算法,最簡單的就是可以根據一個種子作為 key 生成一個隨機數,並儲存在 Session 中,等下次使用者提交表單時做驗證。驗證表單的過程如圖所示。
這裡寫圖片描述

七、Cookie和Session的區別

Cookie與Session都能夠進行會話跟蹤,但是完成的原理不太一樣。普通狀況下二者均能夠滿足需求,但有時分不能夠運用Cookie,有時分不能夠運用Session。下面經過比擬闡明二者的特性以及適用的場所。

1 .存取方式的不同

Cookie中只能保管ASCII字串,假如需求存取Unicode字元或者二進位制資料,需求先進行編碼。Cookie中也不能直接存取Java物件。若要儲存略微複雜的資訊,運用Cookie是比擬艱難的。
而Session中能夠存取任何型別的資料,包括而不限於String、Integer、List、Map等。Session中也能夠直接保管Java Bean乃至任何Java類,物件等,運用起來十分便當。能夠把Session看做是一個Java容器類。

2 .隱私策略的不同

Cookie儲存在客戶端閱讀器中,對客戶端是可見的,客戶端的一些程式可能會窺探、複製以至修正Cookie中的內容。而Session儲存在伺服器上,對客戶端是透明的,不存在敏感資訊洩露的風險。
假如選用Cookie,比較好的方法是,敏感的資訊如賬號密碼等儘量不要寫到Cookie中。最好是像Google、Baidu那樣將Cookie資訊加密,提交到伺服器後再進行解密,保證Cookie中的資訊只要本人能讀得懂。而假如選擇Session就省事多了,反正是放在伺服器上,Session裡任何隱私都能夠有效的保護。

3.有效期上的不同

使用過Google的人都曉得,假如登入過Google,則Google的登入資訊長期有效。使用者不用每次訪問都重新登入,Google會持久地記載該使用者的登入資訊。要到達這種效果,運用Cookie會是比較好的選擇。只需要設定Cookie的過期時間屬性為一個很大很大的數字。

由於Session依賴於名為JSESSIONID的Cookie,而Cookie JSESSIONID的過期時間默許為–1,只需關閉了閱讀器該Session就會失效,因而Session不能完成資訊永世有效的效果。運用URL地址重寫也不能完成。而且假如設定Session的超時時間過長,伺服器累計的Session就會越多,越容易招致記憶體溢位。

4.伺服器壓力的不同

Session是保管在伺服器端的,每個使用者都會產生一個Session。假如併發訪問的使用者十分多,會產生十分多的Session,耗費大量的記憶體。因而像Google、Baidu、Sina這樣併發訪問量極高的網站,是不太可能運用Session來追蹤客戶會話的。

而Cookie保管在客戶端,不佔用伺服器資源。假如併發閱讀的使用者十分多,Cookie是很好的選擇。關於Google、Baidu、Sina來說,Cookie或許是唯一的選擇。

5 .瀏覽器支援的不同

Cookie是需要客戶端瀏覽器支援的。假如客戶端禁用了Cookie,或者不支援Cookie,則會話跟蹤會失效。關於WAP上的應用,常規的Cookie就派不上用場了。

假如客戶端瀏覽器不支援Cookie,需要運用Session以及URL地址重寫。需要注意的是一切的用到Session程式的URL都要進行URL地址重寫,否則Session會話跟蹤還會失效。關於WAP應用來說,Session+URL地址重寫或許是它唯一的選擇。

假如客戶端支援Cookie,則Cookie既能夠設為本瀏覽器視窗以及子視窗內有效(把過期時間設為–1),也能夠設為一切閱讀器視窗內有效(把過期時間設為某個大於0的整數)。但Session只能在本閱讀器視窗以及其子視窗內有效。假如兩個瀏覽器視窗互不相干,它們將運用兩個不同的Session。(IE8下不同視窗Session相干)

6.跨域支援上的不同

Cookie可以通過如下方式實現跨域名訪問,例如將domain屬性設定為“.xxx.com”,則“a.xxx.com”和“b.xxx.com”均能夠訪問該Cookie。事實上只要是以”.xxx.com”結尾的域名均可訪問。跨域名Cookie如今被普遍用在網路中,例如Google、Baidu、Sina等。而Session則不會支援跨域名訪問。Session僅在他所在的域名內有效。

僅運用Cookie或者僅運用Session可能完成不了理想的效果。這時應該嘗試一下同時運用Cookie與Session。Cookie與Session的搭配運用在實踐專案中會完成很多意想不到的效果。

參考文獻

《深入分析JavaWeb技術內幕》 許令波著