cookie機(jī)制
當(dāng)你訪問(wèn)一個(gè)支持cookie的網(wǎng)站時(shí),用戶把用戶名等信息提交到服務(wù)器,接著,服務(wù)器在向客戶端回傳相應(yīng)的超文本的同時(shí)也會(huì)發(fā)回這些個(gè)人信息,當(dāng)然這些信息并不是存放在HTTP響應(yīng)體(Response Body)中的,而是存放于HTTP響應(yīng)頭(Response Header),當(dāng)客戶端瀏覽器接收到來(lái)自服務(wù)器的響應(yīng)之后,瀏覽器會(huì)將這些信息存放在一個(gè)統(tǒng)一的位置,對(duì)于Windows操作系統(tǒng)而言,我們可以從: [系統(tǒng)盤]:\Documents and Settings[用戶名]\Cookies目錄中找到存儲(chǔ)的Cookie;自此,客戶端再向服務(wù)器發(fā)送請(qǐng)求的時(shí)候,都會(huì)把相應(yīng)的Cookie再次發(fā)回至服務(wù)器。而這次,Cookie信息則存放在HTTP請(qǐng)求頭(Request Header)了。有了Cookie這樣的技術(shù)實(shí)現(xiàn),服務(wù)器在接收到來(lái)自客戶端瀏覽器的請(qǐng)求之后,就能夠通過(guò)分析存放于請(qǐng)求頭的Cookie得到客戶端特有的信息,從而動(dòng)態(tài)生成與該客戶端相對(duì)應(yīng)的內(nèi)容。通常,我們可以從很多網(wǎng)站的登錄界面中看到“請(qǐng)記住我”這樣的選項(xiàng),如果你勾選了它之后再登錄,那么在下一次訪問(wèn)該網(wǎng)站的時(shí)候就不需要進(jìn)行重復(fù)而繁瑣的登錄動(dòng)作了,而這個(gè)功能就是通過(guò)Cookie實(shí)現(xiàn)的。
HTTP協(xié)議是無(wú)狀態(tài)的協(xié)議。一旦數(shù)據(jù)交換完畢,客戶端與服務(wù)器端的連接就會(huì)關(guān)閉,再次交換數(shù)據(jù)需要建立新的連接。這就意味著服務(wù)器無(wú)法從連接上跟蹤會(huì)話。Cookie就是這樣的一種機(jī)制。它可以彌補(bǔ)HTTP協(xié)議無(wú)狀態(tài)的不足。在Session出現(xiàn)之前,基本上所有的網(wǎng)站都采用Cookie來(lái)跟蹤會(huì)話。
本質(zhì)上cookies就是http的一個(gè)擴(kuò)展,有兩個(gè)http頭部是專門負(fù)責(zé)設(shè)置以及發(fā)送cookie的,它們分別是Set-Cookie以及Cookie。當(dāng)服務(wù)器返回給客戶端一個(gè)http響應(yīng)信息時(shí),其中如果包含Set-Cookie這個(gè)頭部時(shí),意思就是指示客戶端建立一個(gè)cookie,并且在后續(xù)的http請(qǐng)求中自動(dòng)發(fā)送這個(gè)cookie到服務(wù)器端,直到這個(gè)cookie過(guò)期,至此可以發(fā)現(xiàn)cookie的設(shè)置以及發(fā)送過(guò)程其實(shí)分為以下四步:
1、客戶端發(fā)送一個(gè)http請(qǐng)求到服務(wù)器端
2、服務(wù)器端發(fā)送一個(gè)http響應(yīng)到客戶端,其中包含Set-Cookie頭部
3、客戶端發(fā)送一個(gè)http請(qǐng)求到服務(wù)器端,其中包含Cookie頭部
4、服務(wù)器端發(fā)送一個(gè)http響應(yīng)到客戶端


由于用戶可能再應(yīng)用程序交互過(guò)程中禁用cookie,除了cookie,客戶端可以用傳遞數(shù)據(jù)到服務(wù)器端的方式將數(shù)據(jù)包含在http請(qǐng)求的內(nèi)容區(qū)域內(nèi),
我們可以將SESSID包含在http請(qǐng)求的url中,就像下面的例子一樣
GET /index.php?PHPSESSID=12345 HTTP/1.1 Host: example.org
Cookie的有效期
Cookie的maxAge決定著Cookie的有效期,單位為秒(Second)。Cookie中通過(guò)getMaxAge()方法與setMaxAge(int maxAge)方法來(lái)讀寫maxAge屬性。 如果maxAge屬性為正數(shù),則表示該Cookie會(huì)在maxAge秒之后自動(dòng)失效。瀏覽器會(huì)將maxAge為正數(shù)的Cookie持久化,即寫到對(duì)應(yīng)的Cookie文件中。無(wú)論客戶關(guān)閉了瀏覽器還是電腦,只要還在maxAge秒之前,登錄網(wǎng)站時(shí)該Cookie仍然有效。
如果maxAge為負(fù)數(shù),則表示該Cookie僅在本瀏覽器窗口以及本窗口打開(kāi)的子窗口內(nèi)有效,關(guān)閉窗口后該Cookie即失效。maxAge為負(fù)數(shù)的Cookie,為臨時(shí)性Cookie,不會(huì)被持久化,不會(huì)被寫到Cookie文件中。Cookie信息保存在瀏覽器內(nèi)存中,因此關(guān)閉瀏覽器該Cookie就消失了。Cookie默認(rèn)的maxAge值為–1。
如果maxAge為0,則表示刪除該Cookie。Cookie機(jī)制沒(méi)有提供刪除Cookie的方法,因此通過(guò)設(shè)置該Cookie即時(shí)失效實(shí)現(xiàn)刪除Cookie的效果。失效的Cookie會(huì)被瀏覽器從Cookie文件或者內(nèi)存中刪除:
Cookie cookie = new Cookie("username","helloweenvsfei"); // 新建
Cookiecookie.setMaxAge(0); // 設(shè)置生命周期為0,不能為負(fù)數(shù)
response.addCookie(cookie); // 必須執(zhí)行這一句
注意:從客戶端讀取Cookie時(shí),包括maxAge在內(nèi)的其他屬性都是不可讀的,也不會(huì)被提交。瀏覽器提交Cookie時(shí)只會(huì)提交name與value屬性。maxAge屬性只被瀏覽器用來(lái)判斷Cookie是否過(guò)期。
session機(jī)制
除了使用Cookie,Web應(yīng)用程序中還經(jīng)常使用Session來(lái)記錄客戶端狀態(tài)。Session是服務(wù)器端使用的一種記錄客戶端狀態(tài)的機(jī)制,使用上比Cookie簡(jiǎn)單一些,相應(yīng)的也增加了服務(wù)器的存儲(chǔ)壓力。
Session技術(shù)則是服務(wù)端的解決方案,它是通過(guò)服務(wù)器來(lái)保持狀態(tài)的。由于Session這個(gè)詞匯包含的語(yǔ)義很多,因此需要在這里明確一下 Session的含義。首先,我們通常都會(huì)把Session翻譯成會(huì)話,因此我們可以把客戶端瀏覽器與服務(wù)器之間一系列交互的動(dòng)作稱為一個(gè) Session。從這個(gè)語(yǔ)義出發(fā),我們會(huì)提到Session持續(xù)的時(shí)間,會(huì)提到在Session過(guò)程中進(jìn)行了什么操作等等;其次,Session指的是服務(wù)器端為客戶端所開(kāi)辟的存儲(chǔ)空間,在其中保存的信息就是用于保持狀態(tài)。從這個(gè)語(yǔ)義出發(fā),我們則會(huì)提到往Session中存放什么內(nèi)容,如何根據(jù)鍵值從 Session中獲取匹配的內(nèi)容等。要使用Session,第一步當(dāng)然是創(chuàng)建Session了。那么Session在何時(shí)創(chuàng)建呢?當(dāng)然還是在服務(wù)器端程序運(yùn)行的過(guò)程中創(chuàng)建的,不同語(yǔ)言實(shí)現(xiàn)的應(yīng)用程序有不同創(chuàng)建Session的方法,而在Java中是通過(guò)調(diào)用HttpServletRequest的getSession方法(使用true作為參數(shù))創(chuàng)建的。在創(chuàng)建了Session的同時(shí),服務(wù)器會(huì)為該Session生成唯一的Session id,而這個(gè)Session id在隨后的請(qǐng)求中會(huì)被用來(lái)重新獲得已經(jīng)創(chuàng)建的Session;在Session被創(chuàng)建之后,就可以調(diào)用Session相關(guān)的方法往Session中增加內(nèi)容了,而這些內(nèi)容只會(huì)保存在服務(wù)器中,發(fā)到客戶端的只有Session id;當(dāng)客戶端再次發(fā)送請(qǐng)求的時(shí)候,會(huì)將這個(gè)Session id帶上,服務(wù)器接受到請(qǐng)求之后就會(huì)依據(jù)Session id找到相應(yīng)的Session,從而再次使用之。正式這樣一個(gè)過(guò)程,用戶的狀態(tài)也就得以保持了。
Session是另一種記錄客戶狀態(tài)的機(jī)制,不同的是Cookie保存在客戶端瀏覽器中,而Session保存在服務(wù)器上??蛻舳藶g覽器訪問(wèn)服務(wù)器的時(shí)候,服務(wù)器把客戶端信息以某種形式記錄在服務(wù)器上。這就是Session??蛻舳藶g覽器再次訪問(wèn)時(shí)只需要從該Session中查找該客戶的狀態(tài)就可以了。
如果說(shuō)Cookie機(jī)制是通過(guò)檢查客戶身上的“通行證”來(lái)確定客戶身份的話,那么Session機(jī)制就是通過(guò)檢查服務(wù)器上的“客戶明細(xì)表”來(lái)確認(rèn)客戶身份。Session相當(dāng)于程序在服務(wù)器上建立的一份客戶檔案,客戶來(lái)訪的時(shí)候只需要查詢客戶檔案表就可以了。
Session的有效期
由于會(huì)有越來(lái)越多的用戶訪問(wèn)服務(wù)器,因此Session也會(huì)越來(lái)越多。為防止內(nèi)存溢出,服務(wù)器會(huì)把長(zhǎng)時(shí)間內(nèi)沒(méi)有活躍的Session從內(nèi)存刪除。這個(gè)時(shí)間就是Session的超時(shí)時(shí)間。如果超過(guò)了超時(shí)時(shí)間沒(méi)訪問(wèn)過(guò)服務(wù)器,Session就自動(dòng)失效了。
Session的超時(shí)時(shí)間為maxInactiveInterval屬性,可以通過(guò)對(duì)應(yīng)的getMaxInactiveInterval()獲取,通過(guò)setMaxInactiveInterval(longinterval)修。
Session的超時(shí)時(shí)間也可以在web.xml中修改。另外,通過(guò)調(diào)用Session的invalidate()方法可以使Session失效。
Session對(duì)瀏覽器的要求
雖然Session保存在服務(wù)器,對(duì)客戶端是透明的,它的正常運(yùn)行仍然需要客戶端瀏覽器的支持。這是因?yàn)镾ession需要使用Cookie作為識(shí)別標(biāo)志。HTTP協(xié)議是無(wú)狀態(tài)的,Session不能依據(jù)HTTP連接來(lái)判斷是否為同一客戶,因此服務(wù)器向客戶端瀏覽器發(fā)送一個(gè)名為JSESSIONID的Cookie,它的值為該Session的id(也就是HttpSession.getId()的返回值)。Session依據(jù)該Cookie來(lái)識(shí)別是否為同一用戶。
該Cookie為服務(wù)器自動(dòng)生成的,它的maxAge屬性一般為–1,表示僅當(dāng)前瀏覽器內(nèi)有效,并且各瀏覽器窗口間不共享,關(guān)閉瀏覽器就會(huì)失效。
因此同一機(jī)器的兩個(gè)瀏覽器窗口訪問(wèn)服務(wù)器時(shí),會(huì)生成兩個(gè)不同的Session。但是由瀏覽器窗口內(nèi)的鏈接、腳本等打開(kāi)的新窗口(也就是說(shuō)不是雙擊桌面瀏覽器圖標(biāo)等打開(kāi)的窗口)除外。這類子窗口會(huì)共享父窗口的Cookie,因此會(huì)共享一個(gè)Session。
注意:新開(kāi)的瀏覽器窗口會(huì)生成新的Session,但子窗口除外。子窗口會(huì)共用父窗口的Session。例如,在鏈接上右擊,在彈出的快捷菜單中選擇“在新窗口中打開(kāi)”時(shí),子窗口便可以訪問(wèn)父窗口的Session。
如果客戶端瀏覽器將Cookie功能禁用,或者不支持Cookie怎么辦?例如,絕大多數(shù)的手機(jī)瀏覽器都不支持Cookie。Java Web提供了另一種解決
方案:URL地址重寫
URL地址重寫是對(duì)客戶端不支持Cookie的解決方案。URL地址重寫的原理是將該用戶Session的id信息重寫到URL地址中。服務(wù)器能夠解析重寫后的URL獲取Session的id。這樣即使客戶端不支持Cookie,也可以使用Session來(lái)記錄用戶狀態(tài)。HttpServletResponse類提供了encodeURL(Stringurl)實(shí)現(xiàn)URL地址重寫,例如:
對(duì)于WAP程序,由于大部分的手機(jī)瀏覽器都不支持Cookie,WAP程序都會(huì)采用URL地址重寫來(lái)跟蹤用戶會(huì)話。
如示例,在登錄接口中,后臺(tái)返回sessionid,登錄后,調(diào)接口時(shí)都在url中攜帶sessionid


在談?wù)搒ession機(jī)制的時(shí)候,常常聽(tīng)到這樣一種誤解“只要關(guān)閉瀏覽器,session就消失了”。其實(shí)可以想象一下會(huì)員卡的例子,除非顧客主動(dòng)對(duì)店家提出銷卡,否則店家絕對(duì)不會(huì)輕易刪除顧客的資料。對(duì)session來(lái)說(shuō)也是一樣的,除非程序通知服務(wù)器刪除一個(gè)session,否則服務(wù)器會(huì)一直保留,程序一般都是在用戶做log off的時(shí)候發(fā)個(gè)指令去刪除session。然而瀏覽器從來(lái)不會(huì)主動(dòng)在關(guān)閉之前通知服務(wù)器它將要關(guān)閉,因此服務(wù)器根本不會(huì)有機(jī)會(huì)知道瀏覽器已經(jīng)關(guān)閉,之所以會(huì)有這種錯(cuò)覺(jué),是大部分session機(jī)制都使用會(huì)話cookie來(lái)保存session id,而關(guān)閉瀏覽器后這個(gè) session id就消失了,再次連接服務(wù)器時(shí)也就無(wú)法找到原來(lái)的session。如果服務(wù)器設(shè)置的cookie被保存到硬盤上,或者使用某種手段改寫瀏覽器發(fā)出的HTTP請(qǐng)求頭,把原來(lái)的session id發(fā)送給服務(wù)器,則再次打開(kāi)瀏覽器仍然能夠找到原來(lái)的session。
恰恰是由于關(guān)閉瀏覽器不會(huì)導(dǎo)致session被刪除,迫使服務(wù)器為seesion設(shè)置了一個(gè)失效時(shí)間,當(dāng)距離客戶端上一次使用session的時(shí)間超過(guò)這個(gè)失效時(shí)間時(shí),服務(wù)器就可以認(rèn)為客戶端已經(jīng)停止了活動(dòng),才會(huì)把session刪除以節(jié)省存儲(chǔ)空間。
Cookie與Session的區(qū)別
1、cookie數(shù)據(jù)存放在客戶的瀏覽器上,session數(shù)據(jù)放在服務(wù)器上;
2、cookie不是很安全,別人可以分析存放在本地的COOKIE并進(jìn)行COOKIE欺騙,考慮到安全應(yīng)當(dāng)使用session;
3、session會(huì)在一定時(shí)間內(nèi)保存在服務(wù)器上。當(dāng)訪問(wèn)增多,會(huì)比較占用你服務(wù)器的性能??紤]到減輕服務(wù)器性能方面,應(yīng)當(dāng)使用COOKIE;
4、單個(gè)cookie在客戶端的限制是3K,就是說(shuō)一個(gè)站點(diǎn)在客戶端存放的COOKIE不能超過(guò)3K;