簡(jiǎn)單來說,session與cookie是為了滿足HTTP協(xié)議1.1所不能滿足需求,應(yīng)運(yùn)而生。但是這對(duì)好基友卻不是協(xié)議層面的實(shí)事物,他們從本質(zhì)上,是對(duì)HTTP協(xié)議的一種擴(kuò)展,HTTP協(xié)議是無狀態(tài)的,而session與cookie則是分別從服務(wù)器端與瀏覽器端去維護(hù)訪問狀態(tài)。
1 關(guān)于Session
由于HTTP協(xié)議是無狀態(tài)的協(xié)議,所以服務(wù)端需要記錄用戶的狀態(tài)時(shí),就需要用某種機(jī)制來識(shí)具體的用戶,所以服務(wù)端要為特定的用戶創(chuàng)建了特定的Session,用于標(biāo)識(shí)這個(gè)用戶,并且跟蹤用戶。這個(gè)Session是保存在服務(wù)端的,有一個(gè)唯一標(biāo)識(shí)。在服務(wù)端保存Session的方法很多,內(nèi)存、數(shù)據(jù)庫、文件都有。
它的基本原理是服務(wù)端為每一個(gè)session維護(hù)一份會(huì)話信息數(shù)據(jù),而客戶端和服務(wù)端依靠一個(gè)全局唯一的標(biāo)識(shí)來訪問會(huì)話信息數(shù)據(jù)。用戶訪問web應(yīng)用時(shí),服務(wù)端程序決定何時(shí)創(chuàng)建session,創(chuàng)建session可以概括為三個(gè)步驟:
(1)生成全局唯一標(biāo)識(shí)符(sessionid)。
(2)開辟數(shù)據(jù)存儲(chǔ)空間。
一般會(huì)在內(nèi)存中創(chuàng)建相應(yīng)的數(shù)據(jù)結(jié)構(gòu)。但是!這種情況下,系統(tǒng)一旦斷電,所有的會(huì)話數(shù)據(jù)就會(huì)丟失,如果是電子商務(wù)網(wǎng)站,這種事故會(huì)造成嚴(yán)重的后果。不過也可以寫到文件里甚至存儲(chǔ)在數(shù)據(jù)庫中,這樣雖然會(huì)增加I/O開銷,但session可以實(shí)現(xiàn)某種程度的持久化,而且更有利于session的共享。
(3) 將sessionid發(fā)送給客戶端。
發(fā)送sessionid又有兩種方式:cookie和URL重寫
cookie:服務(wù)端只要設(shè)置Set-cookie頭就可以將session的標(biāo)識(shí)符傳送到客戶端,而客戶端此后的每一次請(qǐng)求都會(huì)帶上這個(gè)標(biāo)識(shí)符,由于cookie可以設(shè)置失效時(shí)間,所以一般包含session信息的cookie會(huì)設(shè)置失效時(shí)間為0,即瀏覽器進(jìn)程有效時(shí)間。至于瀏覽器怎么處理這個(gè)0,每個(gè)瀏覽器都有自己的方案,但差別都不會(huì)太大(一般體現(xiàn)在新建瀏覽器窗口的時(shí)候)
URL重寫:就如字面意思那樣。在返回用戶請(qǐng)求的頁面之前,將頁面內(nèi)所有的URL后面全部以get參數(shù)的方式加上session標(biāo)識(shí)符,這樣用戶在收到響應(yīng)之后,無論點(diǎn)擊哪個(gè)鏈接或提交表單,都會(huì)在再帶上session的標(biāo)識(shí)符,從而就實(shí)現(xiàn)了會(huì)話的保持。
如果客戶端禁用了cookie的話,URL重寫將會(huì)是首選。
過程大致是這樣的:當(dāng)你訪問某網(wǎng)址的時(shí)候,服務(wù)器返回的響應(yīng)頭里會(huì)有Set-cookie JSESSIONID="xx";Path="xx";name="xx";expires="xx";domain="xx";name="xx";
這個(gè)JSESSIONID里面的就是sessionid了,這就是服務(wù)器創(chuàng)建了seesion,記錄了訪問狀態(tài),并且告訴客戶端瀏覽器以sessionid為唯一標(biāo)示符,創(chuàng)建cookie。并且每次發(fā)出請(qǐng)求前都要去匹配所有cookie的Path屬性,將相匹配的cookie以下面這種形式發(fā)送到服務(wù)端:
Cookie: JSESSIONID="xx";name="xx"; Path="xx";
服務(wù)端在識(shí)別cookie中的sessionid后會(huì)在服務(wù)端調(diào)用匹配的session對(duì)訪問請(qǐng)求進(jìn)行處理,再次返回的響應(yīng)里就不會(huì)帶有涉及session或者cookie的信息。
cookie和session都有可以設(shè)置有效期,一般來說session中默認(rèn)有效期都是短時(shí)效的,例如Tomcat中Session的默認(rèn)失效時(shí)間為30分鐘,cookie的有效期。當(dāng)然,也可以在有效期期間清除session或cookie,如手動(dòng)清除cookie或session,關(guān)閉瀏覽器后引發(fā)session超時(shí)等。
有關(guān)session的手動(dòng)銷毀,這里有個(gè)小知識(shí)。當(dāng)服務(wù)端銷毀session后,客戶端依舊發(fā)送cookie,這時(shí)服務(wù)端在找不到匹配的sessionid的情況下會(huì)重新創(chuàng)建新的session,并告知客戶端更新sessionid開始保持新的會(huì)話。
2 關(guān)于Cookie
服務(wù)端如何識(shí)別特定的客戶?
每次HTTP請(qǐng)求的時(shí)候,客戶端都會(huì)發(fā)送相應(yīng)的Cookie信息到服務(wù)端。實(shí)際上大多數(shù)的應(yīng)用都是用 Cookie 來實(shí)現(xiàn)Session跟蹤的,第一次創(chuàng)建Session的時(shí)候,服務(wù)端會(huì)在HTTP協(xié)議中告訴客戶端,需要在 Cookie 里面記錄一個(gè)Session ID,以后每次請(qǐng)求把這個(gè)會(huì)話ID發(fā)送到服務(wù)器,服務(wù)器就知道你是誰了。有人問,如果客戶端的瀏覽器禁用了 Cookie 怎么辦?一般這種情況下,會(huì)使用一種叫做URL重寫的技術(shù)來進(jìn)行會(huì)話跟蹤,即每次HTTP交互,URL后面都會(huì)被附加上一個(gè)諸如 sid=xxxxx 這樣的參數(shù),服務(wù)端據(jù)此來識(shí)別用戶。
eg:Cookie其實(shí)還可以用在一些方便用戶的場(chǎng)景下,設(shè)想你某次登陸過一個(gè)網(wǎng)站,下次登錄的時(shí)候不想再次輸入賬號(hào)了,怎么辦?這個(gè)信息可以寫到Cookie里面,訪問網(wǎng)站的時(shí)候,網(wǎng)站頁面的腳本可以讀取這個(gè)信息,就自動(dòng)幫你把用戶名給填了,能夠方便一下用戶。
Cookie是瀏覽器保存信息的一種方式,可以理解為一個(gè)文件,保存到客戶端了啊,服務(wù)器可以通過響應(yīng)瀏覽器的set-cookie的標(biāo)頭,得到Cookie的信息。你可以給這個(gè)文件設(shè)置一個(gè)期限,這個(gè)期限呢,不會(huì)因?yàn)闉g覽器的關(guān)閉而消失!
一般來說:無論使用何種服務(wù)端技術(shù),只要發(fā)送回的HTTP響應(yīng)中包含如下形式的頭,則視為服務(wù)器要求設(shè)置一個(gè)cookie:
Set-cookie:name=name;expires=date;path=path;domain=domain
支持cookie的瀏覽器都會(huì)對(duì)此作出反應(yīng),即創(chuàng)建cookie文件并保存(也可能是內(nèi)存cookie),用戶以后在每次發(fā)出請(qǐng)求時(shí),瀏覽器都要判斷當(dāng)前所有的cookie中有沒有沒失效(根據(jù)expires屬性判斷)并且匹配了path屬性的cookie信息,如果有的話,會(huì)以下面的形式加入到請(qǐng)求頭中發(fā)回服務(wù)端:
Cookie: name="zj"; Path="/linkage"
服務(wù)端的動(dòng)態(tài)腳本會(huì)對(duì)其進(jìn)行分析,并做出相應(yīng)的處理,當(dāng)然也可以選擇直接忽略。需要注意的是,出于安全性的考慮,cookie可以被瀏覽器禁用。
3 relationship
Session是在服務(wù)端保存的一個(gè)數(shù)據(jù)結(jié)構(gòu),用來跟蹤用戶的狀態(tài),這個(gè)數(shù)據(jù)可以保存在集群、數(shù)據(jù)庫、文件中。
Cookie是客戶端保存用戶信息的一種機(jī)制,也是實(shí)現(xiàn)Session的一種方式。可以理解為一個(gè)文件,不會(huì)因?yàn)闉g覽器的關(guān)閉而消失。
安全性
cookie將信息保存在客戶端,如果不進(jìn)行加密的話,安全性很差,即使加密也很容易就會(huì)被竊取。而session只會(huì)將信息存儲(chǔ)在服務(wù)端,如果存儲(chǔ)在文件或數(shù)據(jù)庫中,也有被竊取的可能。session安全性方面比較突出的是存在會(huì)話劫持的問題,當(dāng)sessionid被盜用,由于HTTP協(xié)議的無狀態(tài)性,服務(wù)器無法得知session是否被劫持,但總的來講安全性要高于cookie。
大小限制
Cookie的處理在開發(fā)中沒有session方便。而且cookie在客戶端是有數(shù)量和大小的限制的,而session的大小只以硬件為限制,能存儲(chǔ)的數(shù)據(jù)大了很多。