基本概念
對於許多人來說,都知道的是,cookie是存儲在客戶端的,可以用來放需要長期使用的內容,例如用戶密碼、用戶賬戶等等,服務器是可以獲取到cookie的內容的;而session則是存儲在服務器端,通過唯一的session_id來區別用戶,用於保存用戶的登錄狀態和請求等,客戶是不能獲取到其內容的。
這對於許多人來說都是比較基礎的內容,也是表現形式上的區別,在這里我們深入的了解一下兩者。
為什么需要cookie?
對於web程序,有一個需要考慮的問題是如何跟蹤用戶的會話,照常理來說,一個用戶的行為只能對應於一個會話,比如開發購物車應用,就要考慮到用戶的購物車中的內容,一個用戶的購物車總不能裝的是別人的商品吧?跟蹤用戶的會話就是用來區分不同用戶的各自所挑選的商品。
但是Web應用是基於HTTP協議來傳輸數據的,而HTTP協議是無狀態的,在完成傳輸數據之后,客戶端與服務器端的連接就會關閉,對於不同用戶發生“將商品放入購物車”的動作時,不能夠判斷哪一件商品對應哪一位用戶。在這里需要使用cookie,來解決HTTP協議在跟蹤會話上的不足。
cookie是服務器端給客戶端分發的一種憑證,客戶端要請求服務,就需要在發送數據時的同時發送cookie,服務器端通過識別cookie的內容,得知用戶的身份,就可以知道用戶的購物車是那一輛,再將商品放進去就可以了。
cookie的內容
要查看cookie可以在地址欄輸入 javascript: alert(document.cookie); 就可以看到網站分發的cookie了。下面是百度上的cookie內容,在有使用cookie的網站使用才可行。
cookie的內容就是這樣的字符串,服務器通過讀取這樣的長長的加密過的cookie來獲取用戶的信息,這里有BAIDUID(即我的百度賬號),以及其他的信息。
cookie的分類
實際上cookie也分為兩種,分別是停留在瀏覽器所占內容的臨時性的cookie,在頁面窗口關閉之后就被刪除,被稱為session cookie;而另外一種是通過存放在硬盤空間中長期存在的cookie,這種cookie稱為persistent cookie,也就是我們通常意義上所講的cookie。
通常session是依賴於session cookie來與客戶端交互的,當然session的工作方式不僅僅限於這一種,還有其他的方式在下文會說到。
cookie的屬性
以下表格是cookie的比較常用的屬性及其說明:
屬性名 | 描述 |
String name | 該Cookie的名稱。Cookie一旦創建,名稱便不可更改 |
Object value | 該Cookie的值。如果值為Unicode字符,需要為字符編碼。如果值為二進制數據,則需要使用BASE64編碼 |
int maxAge | 該Cookie失效的時間,單位秒。如果為正數,則該Cookie在maxAge秒之后失效。如果為負數,該Cookie為臨時Cookie,關閉瀏覽器即失效,瀏覽器也不會以任何形式保存該Cookie。如果為0,表示刪除該Cookie。默認為–1 |
boolean secur | 該Cookie是否僅被使用安全協議傳輸。安全協議。安全協議有HTTPS,SSL等,在網絡上傳輸數據之前先將數據加密。默認為false |
String path | 該Cookie的使用路徑。如果設置為“/sessionWeb/”,則只有contextPath為“/sessionWeb”的程序可以訪問該Cookie。如果設置為“/”,則本域名下contextPath都可以訪問該Cookie。注意最后一個字符必須為“/” |
String domain | 可以訪問該Cookie的域名。如果設置為“.google.com”,則所有以“google.com”結尾的域名都可以訪問該Cookie。注意第一個字符必須為“.” |
要注意到cookie的名稱是無法修改的,同時cookie並不提供修改和刪除的操作,如果說要修改cookie 的內容,則可以新建一個同名的cookie覆蓋掉原來的即可;要刪除cookie的話則新建一個同名的cookie,並設置其maxAge為0即可。
需要考慮cookie中maxAge的一些特殊值所代表的含義,如果maxAge為負值,則表示cookie僅僅在當前瀏覽器窗口以及其打開的子窗口中有效,關閉時則失效,這也是cookie的默認maxAge值;如果maxAge為0,則說明刪除該cookie,由於並沒有刪除cookie的操作,這里是需要通過cookie的maxAge來進行刪除操作的。
seesion的出現
對於cookie是存儲在客戶端的,這種存儲在客戶端的信息往往是不安全的,所以后來又有了session,客戶端瀏覽器向服務器發送請求的時候,服務器將客戶端的信息以某種形式存儲在服務器上,這種存儲在服務器端的信息在客戶第二次訪問服務器的時候被使用,用來確定用戶的狀態等信息。打個比方而言,就相當於這是一張記錄客戶信息的表格,客戶只要表明身份,服務器就能從這個表格中來獲取客戶的信息,根據信息進行服務。
session的使用
服務器會在客戶端第一次請求服務的時候創建session對象,與cookie類似,session對象也是以鍵值對的形式存儲的。每個session對象都有獨立的session_id,對於特定的客戶,就賦予特定的session,可以區分不同的用戶。需要注意的是,通常是在用戶請求具體服務的時候才會創建session,單純的訪問靜態的內容(如HTML)並不會創建session。而在創建之后的每一次客戶訪問服務器都會更新session的內容,比如session的最后訪問時間等等。
還有一點是session的內容應該盡量的精簡,因為session是存儲在服務器端的,需要占用到寶貴的服務器資源(一般放在服務器內存里),所以這里在有大量客戶訪問的時候,會導致服務器的資源不夠用。此外還會給session設置有效期,對於長時間沒有活躍的session會從內存中刪除,這也是我們用一些Web應用時會有說“登錄超時”的情況出現。
session的依賴實現
對於上面所說的session,它對於用戶來說是透明的,在客戶請求服務的時候,客戶端需要有一個標示自己身份的憑證,但是僅僅是標示自己的身份,所以這個標示會比較小。通過這個身份,服務器才能從內存中的多個session中知道用戶是對應於哪一個session。
一般來說session是要依賴於cookie來實現,這一點在上面講到cookie的分類時說到,這時候生成的cookie就是上文提到的session cookie,而cookie的內容就是session的特定的id,這個cookie在瀏覽器關閉的時候就會失效。
因此同一個機器上的兩個瀏覽器窗口訪問服務器的時候會生成兩個不同的session。但是如果兩個窗口是由同一個父窗口打開的話,子窗口會共享父窗口的cookie,所以這時候是共享一個session。
如果禁用了cookie,那要怎么實現session?
這個問題有時候會在面試的時候問到,在瀏覽器禁用cookie或者不支持cookie的時候,通常會采取一種叫做“URL重寫”的方式來實現session,也就是以類似於GET方式,將session_id寫在URL的后面,這樣服務器也能獲取到客戶的session_id,通過這個獨立的id就能識別特定的用戶了。
參考資料: Cookie/Session機制詳解 作者:fangaoxin
老生常談session,cookie的區別,安全性 作者:海底蒼鷹