有些時候對cookie和session理解比較混亂,而且頗有可能在面試的時候,也被常常提起cookie和session的區別以及使用。通過查閱一些資料,整理出如下文檔java
1、cookie和session的概念面試
一、 cookieredis
當一個用戶經過Http協議訪問一個服務器的時候,服務器會將一些key/value這樣的一些鍵值對返回給客戶端瀏覽器,並給這些數據加上一些限制條件,在相關的條件符合的狀況下,瀏覽器再訪問服務器的時候,又會把這些數據完整的帶上,返回給服務器。因爲HTTP協議是無狀態協議,經過cookie的這種方式,服務器就能知道客戶端從哪裏來的。而且在一些很短的時間呢,用戶的一些信息若是被頻繁訪問,這樣服務器就能夠作一些緩存等優化,保證訪問的速度。apache
Http協議中並無規定相關對cookie大小等的限制,可是因爲各家瀏覽器在實現的過程當中的不一樣,cookie的大小也不一樣,可是大概爲4K ,大多數瀏覽器對每一個站點限制通常爲20個cookie,當超過這個數量的時候,老的cookie將會被覆蓋掉。Cookie在生成的時候,會指定一個expire的值,指定cookie的過時時間,時間超過之後,此Cookie將不能再被使用。必須生成新的cookie,在咱們訪問網站的時候,一般會見到保存密碼多長時間這個選項,以下圖:瀏覽器
實際上咱們登陸的這些信息被存儲到了客戶端瀏覽器中,而後經過這個cookie來保存咱們我的的登陸信息,這樣咱們在下次訪問的時候就不須要再從新輸入用戶名和密碼進行登錄。可是當超過設置的expire時間之後,就沒法再使用。緩存
在java程序中,咱們能夠以下代碼設置和使用cookietomcat
public String getCookie(Cookie[] cookies,String key){ if(cookies!=null){ for(Cookie cookie:cookies){ if(cookie.getName().equals(key)){ returncookie.getValue(); } } } retur nnull; } publicvoiddoHello(HttpServletRequest request,HttpServletResponse response){ Cookie[]cookies= request.getCookies(); StringuserName= getCookie(cookies,"username"); if(userName==null){ response.addCookie(new Cookie("username","zhangsan")); } response.getHeader("Set-Cookie"); }
Tomcat建立Set-cookie相應頭的時序圖安全
從以上時序圖中咱們能夠看出,在咱們經過response.addCooke建立多個Cookie,咱們在每次建立Cookie時,都會建立一個以name爲Set-Cookie的MimeHeaders.而且在服務器返回給客戶端的時候也不會對相同Header標識的Set-Cookie進行合併。Tomcat源碼中能夠看出,這段代碼位於org.apache.coyote.http11.Http11Processor類的prepareResponse方法中。以下:服務器
Int size = headers.size(); for(int i=0;i<size;i++){ outputBuffer.setHeader(headers.getName(i),headers.getValue(i)); }
這段代碼清楚的表示,在構建Http返回字節流時,是將Header中的全部項順序的寫出,沒有作任何修改,因此能夠想象瀏覽器在接受HTTP協議返回的數據時是分別解析每個Header項的。cookie
二、 session
cookie可讓服務端程序跟蹤每一個客戶的訪問,可是每次客戶端的訪問都必須回傳這些cookie的值,若是cookie不少,這樣就無形的增長了客戶端與服務端的數據量傳輸,而Session的出現正是爲了解決這個問題。
同一個客戶端每次和服務端進行交互時,不須要每次都須要回傳全部的Cookie的值,而只須要傳回一個ID,這個ID是客戶端在第一次訪問服務端的時候生成的,而每一個客戶端都是惟一的,這樣每個客戶端就生成了一個惟一的ID,客戶端只須要傳回這個ID就好了,這個ID一般是NAME爲JSSIONID的一個Cookie.因此說Session一般是基於Cookie來工做的,固然當客戶端禁用cookie的時候,還有其餘的方式進行實現Session,可是就Session和Cookie的關係來講,Session基於Cookie進行工做。
2、session的調用過程
有了Session ID 的服務端就能夠建立HttpSession對象,第一次觸發經過調用rquest.getSession()方法,若是當前的Session ID尚未對應的HttpSession對象,則會建立一個HttpSession對象。並將這個對象加到org.apache.catalina.Manager
的session容器中保存,Manager類將會管理全部Session的生命週期,Session過時將會被銷燬,服務器關閉,Session將會被序列化到磁盤等。只要這個HttpSession對象存在,用戶就能夠根據SessionId來獲取這個對象,也就達到了狀態保持的問題。如下是Session建立的時序圖
3、cookie的安全問題
雖然Cookie和Session都是能夠跟蹤客戶端的訪問記錄,可是他們的工做方式顯然是不一樣的。Cookie經過把全部要保存的數據經過HTTP西醫的頭部從客戶端傳遞到服務器,又從服務器傳遞給客戶端,全部的數據都存儲到客戶端的瀏覽器裏。因此這些Cookie數據是能夠被訪問到的。咱們經過Firefox是能夠訪問到記錄到瀏覽器端的用戶名和密碼的。例如個人百度帳號,以下圖:
不只能夠查看Cookie,咱們甚至能夠經過一些工具添加,修改Cookie,因此Cooike的安全性是不可保證的。相比較而言,Session的安全性要高不少,由於Session是將數據保存在服務端,指示經過Cookie傳遞一個JSESSIONID而已。因此Session更適合存儲用戶隱私和重要數據。
4、分佈式session實現思路
在咱們應用在進行部署的時候,如今大多數狀況均不是單機部署,而是進行集羣的部署,可是這樣會致使客戶端訪問的時候,若是一臺服務器掛掉,這樣保存在這臺服務器上的session就會消失,致使客戶登陸等相關信息丟失,下降了客戶體驗的良好性。爲了解決以上問題,基本上會有下面兩種思路:
在各臺服務器間session複製共享
Session複製共享,主要指在集羣環境下,各臺應用服務器之間進行同步session,使得session保持一致。當一臺服務器出現問題時候,負載均衡服務器會把請求負載到另外的一臺服務器,因爲每臺服務器均存儲全部服務器的session,這樣能夠保證請求的連續性。
可是這種方案會有如下不足
技術比較複雜,必須在同一種中間件中進行實現,例如tomcat
Session的複製一定會帶來性能上的損失,特別是當應用服務器比較多,session存儲的內容比較大時。
Session內容的序列化,會致使服務器性能降低
Session經過廣播或者其餘形式同步到其餘服務器。不論是內網仍是外網,一樣對網絡會形成壓力,使之成爲瓶頸。
使用session服務器,基於redis等緩存服務器
這種思想是在服務器本機存儲一份session,而後再在緩存服務器中存儲一份session,當服務器發生故障,在本機找不到session時,能夠去緩存服務器中去尋找,再複製到本地,此種爲業界經常使用思路。
本文出自 「走在將來的路上」 博客,請務必保留此出處http://wtf0313.blog.51cto.com/1093061/1687219