一、Cookie
概念: Cookie是一種客戶端技術,將服務器的數據以Key-Value的形式保存在所屬的客戶端中。當再次訪問服務器時,將會帶着Cookie中的數據去訪問.
特點:
<1> 存儲位置。設置了過期時間的Cookie,數據存儲在用戶瀏覽器上,客戶端的Cookies文件夾內;沒有設置過期時間的Cookie,則保存在內存中.
<2> 存儲限制。閱覽器對Cookie的大小、數量存在限制,各個瀏覽器限制.
各瀏覽器之間對cookie的不同限制:
IE6.0 | IE7.0/8.0/9.0+ | Opera | Firefox | Safari | Chrome | |
cookie個數 | 每個域爲20個 | 每個域爲50個 | 每個域爲30個 | 每個域爲50個 | 沒有個數限制 | 每個域爲53個 |
cookie大小 | 4095個字節 | 4095個字節 | 4096個字節 | 4097個字節 | 4097個字節 | 4097個字節 |
超過大小限制 | 忽略 | 忽略 | 忽略 | 忽略 | 忽略 | 忽略 |
超過數量限制 | 過期最老的 | 過期最老的 | 過期最老的 | 隨機過期 | 無限制 | 過期最老的 |
數量方面可以記爲IE6.0最小20個,其他一般爲50個,Safari最大無限制。Cookie大小方面一般爲4k。
<3> 一種寫入客戶端的手段。Cookie是一種服務器端往客戶端寫入數據的手段,應該也是客戶端僅支持的一種方式。
<4> Cookie可以被客戶端禁用。
擴展: 當Cookie被禁用時,可以使用URL重寫來解決.
在不能用Cookie的系統中,可以將服務端的SessionID動態的添加進生成Html頁面的各超鏈接或轉發地址中。
具體步驟:
Java中提供兩個方法response.encodeRedirectURL()和response.encodeURL()對URL進行重寫。這兩個方法主要區別是,response.encodeURL()使用在本應用級別,response.encodeRedirectURL()跨應用級別(PS:這裏我查了資料,還是不太理解它具體所致,有了解的談一下☺);它們都會爲URL追加一個Jsessionid的參數。
String url = response.encodeRedirectURL("/home");
PrintWriter.println("<a href='"+url+"'>主頁</a>");
<5> Cookie安全性較差。因爲保存在本地,可以分析存放在本地的COOKIE並進行COOKIE欺騙,所以它固有安全上的弱點,因此Cookie不能用來保存保密信息,例如密碼、卡號等信息。對於敏感數據應加密後使用。直接拷貝Cookie文件到瀏覽器下是不行的,需要騙過閱覽器的保證時間。
<6> 存儲數據類型。僅能保存ASCII字符串類型,如果使用UTF-8格式需要轉碼。Java代碼實例:
//保存
Cookie cookie = newCookie("userName", URLEncoder.encode("Cookie測試","UTF-8"));
response.addCookie(cookie);
//讀取
URLDecoder.decode(cookies[i].getValue(),"UTF-8")
<7> 生命週期方面。該Cookie爲服務器自動生成的,它的maxAge屬性一般爲-1,表示僅當前瀏覽器內有效;每個Cookie都有自己的過期時間,超過了過期時間後失效,如果要Cookie永久存在,可以在代碼中如下設置:
cookie.setMaxAge(Integer.MAX_VALUE);
<8> 瀏覽器間可共享。對於保存在閱覽器文件夾中的Cookie,多個閱覽器間可以共享。而對於保存在內存中的Cookie,不同預覽器其處理不一致。
二、Session
<1> 存儲位置。Session將文件存儲在服務器端,默認保存在文件中。放在文件、數據庫、內存中都可以,例如默認保存在文件中,也可以統一保存在Mysql、Redis。
<2> 無存儲限制。理論上不存在任何存儲限制,可以保存任意長度的數據。
<3> 安全性好。由於保存在服務器端,所以Session數據更加安全。
<4> Session失效機制。
(1) 設置Session的失效時間,當客戶端過期時間內無再次訪問,則失效。若再次訪問,則刷新Session的時間。
容器中設置超時時間,以tomcat爲例,在tomcat-7.0\conf\web.xml中設置。默認超時時間爲30分鐘,負數或0位永久有效,時間以服務器時間爲參,時間單位爲分鐘:
<session-config>
<session-timeout>30</session-timeout>
</session-config>
在項目中設置web.xml,以分鐘爲單位:
<session-config>
<session-timeout>15</session-timeout>
</session-config>
通過Java代碼控制,以秒爲單位:
session.setMaxInactiveInterval(30*60);
(2) 調用Session的invalidate方法。
(3) 關閉閱覽器,當Cookie設置爲默認內存存儲,關閉閱覽器Cookie則失效。服務器端依然會保存Session,但是該Session一般無法被再次觸發,在過期時間之後,會被自動清除。相當於Session已經無效。
<5>存儲數據類型。可以存儲任意的數據類型,Integer、String、Object等。
三、比較
通過上面認識Cookie和Session的特性,那麼我可以得出如下比較:
<1> 存儲位置不同:Cookie存儲於用戶閱覽器中,默認保存在內存中,可以設置爲保存Cookie文件夾中;Session存儲於服務器端,默認保存於文件中,可以保存在文件、數據庫、內存。
<2> 是否客戶端可以禁用:Cookie可以被客戶端禁用;Session不能被客戶端禁用。
<3> 安全性不同:Cookie因存儲於客戶端,容易存在安全性問題;而Session存儲於服務器端,相對來說更加安全。
<4> 生命週期不同:Cookie的生命週期是連續的,設置爲20分鐘,20分鐘後會失效。而Session的生命週期是間斷的,設置爲20分鐘,若再次訪問,則重新開始計時。
<5> 存儲數據支持不同:Cookie僅支持String;Session支持String、Integer、Object等多種數據格式。
<6> 存儲限制不同:Cookie存在閱覽器的存儲限制;而Session基本不存在限制,主要看服務器的物理內存、存儲設備大小 。
四、總結
說一下個人的理解,上面所說的Session我認爲可以說是一種狹義的Session,一般是指服務器端一種會話存儲的手段。但是從根本上來講,會話的存在是因爲HTTP本身是無狀態的,所以Session廣義上是一個維持用戶狀態的會話機制。而Cookie則是實現會話的一種客戶端技術手段。例如你可以用下面這些技術方式實現會話機制:
(1) 使用加密的Cookie方式。尤其是在大量併發時,因爲Session存儲在服務器端,所以大量的用戶狀態會造成服務性能降低,所以可以使用純Cookie來保存用戶狀態,而用加密來保障安全性。
(2) 使用Cookie+Servlet Session方式。在考慮到瀏覽器限制時,可以將用戶信息保存在Session,而Cookie保存SessionId。
(3) 使用Cookie+Redis方式。在分佈式時,多臺機器如何維護會話狀態,可以考慮使用Redis作爲專門的會話維護的服務器。可以看出會話你可以當做是一種概念,而Cookie則是一種實現會話的技術手段,而我們常常說的Session也可以看做是一種實現會話的手段。