會話(Session)跟蹤是Web程序中經常使用的技術,用來跟蹤用戶的整個會話。經常使用的會話跟蹤技術是Cookie與Session。Cookie經過在客戶端記錄信息肯定用戶身份,Session經過在服務器端記錄信息肯定用戶身份。常常有人會疑惑:Session會話與Cookies的區別是什麼?用戶登陸的原理是什麼?網站是如何認證的?它怎麼知道是哪一個用戶從哪兒登陸進來的?下面將對這些問題進行一一解答。web
Cookie機制
在程序中,會話跟蹤是很重要的事情。理論上,一個用戶的全部請求操做都應該屬於同一個會話,而另外一個用戶的全部請求操做則應該屬於另外一個會話,兩者不能混淆。例如,用戶A在超市購買的任何商品都應該放在A的購物車內,不管是用戶A什麼時間購買的,這都是屬於同一個會話的,不能放入用戶B或用戶C的購物車內,這不屬於同一個會話。而Web應用程序是使用HTTP協議傳輸數據的。HTTP協議是無狀態的協議。一旦數據交換完畢,客戶端與服務器端的鏈接就會關閉,再次交換數據須要創建新的鏈接。這就意味着服務器沒法從鏈接上跟蹤會話。即用戶A購買了一件商品放入購物車內,當再次購買商品時服務器已經沒法判斷該購買行爲是屬於用戶A的會話仍是用戶B的會話了。要跟蹤該會話,必須引入一種機制。Cookie就是這樣的一種機制。它能夠彌補HTTP協議無狀態的不足。在Session出現以前,基本上全部的網站都採用Cookie來跟蹤會話。redis
什麼是Cookie
Cookie意爲"甜餅",是由W3C組織提出,最先由Netscape社區發展的一種機制。目前Cookie已經成爲標準,全部的主流瀏覽器如IE、Netscape、Firefox、Opera等都支持Cookie。因爲HTTP是一種無狀態的協議,服務器單從網絡鏈接上無從知道客戶身份。怎麼辦呢?就給客戶端們頒發一個通行證吧,每人一個,不管誰訪問都必須攜帶本身通行證。這樣服務器就能從通行證上確認客戶身份了。這就是Cookie的工做原理。Cookie其實是一小段的文本信息。客戶端請求服務器,若是服務器須要記錄該用戶狀態,就使用response向客 戶端瀏覽器頒發一個Cookie。客戶端瀏覽器會把Cookie保存起來。當瀏覽器再請求該網站時,瀏覽器把請求的網址連同該Cookie一同提交給服務 器。服務器檢查該Cookie,以此來辨認用戶狀態。服務器還能夠根據須要修改Cookie的內容。瀏覽器
Cookie的有效期
Cookie的maxAge決定着Cookie的有效期,單位爲秒(Second)。Cookie中經過getMaxAge()方法與setMaxAge(int maxAge)方法來讀寫maxAge屬性。若是maxAge屬性爲正數,則表示該Cookie會在maxAge秒以後自動失效。瀏覽器會將maxAge爲正數的 Cookie持久化,即寫到對應的Cookie文件中。不管客戶關閉了瀏覽器仍是電腦,只要還在maxAge秒以前,登陸網站時該Cookie仍然有效。 下面代碼中的Cookie信息將永遠有效。緩存
Session機制
除了使用Cookie,Web應用程序中還常用Session來記錄客戶端狀態。Session是服務器端使用的一種記錄客戶端狀態的機制,使用上比Cookie簡單一些,相應的也增長了服務器的存儲壓力。tomcat
什麼是Session
Session是另外一種記錄客戶狀態的機制,不一樣的是Cookie保存在客戶端瀏覽器中,而Session保存在服務器上。客戶端瀏覽器訪問服務器的時候,服務器把客戶端信息以某種形式記錄在服務器上。這就是Session。客戶端瀏覽器再次訪問時只須要從該Session中查找該客戶的狀態就能夠了。若是說Cookie機制是經過檢查客戶身上的「通行證」來肯定客戶身份的話,那麼Session機制就是經過檢查服務器上的「客戶明細表」來確認客戶身份。Session至關於程序在服務器上創建的一份客戶檔案,客戶來訪的時候只須要查詢客戶檔案表就能夠了。Session的使用比Cookie方便,可是過多的Session存儲在服務器內存中,會對服務器形成壓力。安全
Session的生命週期
Session保存在服務器端。爲了得到更高的存取速度,服務器通常把Session放在內存裏。每一個用戶都會有一個獨立的Session。若是Session內容過於複雜,當大量客戶訪問服務器時可能會致使內存溢出。所以,Session裏的信息應該儘可能精簡。Session在用戶第一次訪問服務器的時候自動建立。須要注意只有訪問JSP、Servlet等程序時纔會建立Session,只訪問HTML、IMAGE等靜態資源並不會建立Session。若是還沒有生成Session,也可使用request.getSession(true)強制生成Session。Session生成後,只要用戶繼續訪問,服務器就會更新Session的最後訪問時間,並維護該Session。用戶每訪問服務器一次,不管是否讀寫Session,服務器都認爲該用戶的Session「活躍(active)」了一次。服務器
Session的有效期
因爲會有愈來愈多的用戶訪問服務器,所以Session也會愈來愈多。爲防止內存溢出,服務器會把長時間內沒有活躍的Session從內存刪除。這個時間就是Session的超時時間。若是超過了超時時間沒訪問過服務器,Session就自動失效了。Session的超時時間爲maxInactiveInterval屬性,能夠經過對應的getMaxInactiveInterval()獲取,經過setMaxInactiveInterval(longinterval)修改。Session的超時時間也能夠在web.xml中修改。另外,經過調用Session的invalidate()方法可使Session失效。cookie
session與cookie的簡單區別
session和cookie本質上確實是兩個東西,但cookie同時也是session id的載體,cookie保存session id。網絡
cookie數據存放在用戶的瀏覽器上,session數據放在網站的服務器上。
session保存在服務器端與瀏覽器設置無關,cookie在客戶端並受瀏覽器設置限制。
cookie是在你的電腦瀏覽器上保存的,session是在網站服務器上的. 也就是說你換一個電腦你的cookie就不起做用了, 而session只要你的瀏覽器不關就還能訪問到.
一般的都是二者結合着用的. cookie的話你本身就能夠經過對瀏覽器的設置禁用掉.這樣就不起做用了session
cookie不是很安全,別人能夠分析存放在本地的cookie並進行cookie欺騙,考慮到安全應當使用session。
session是服務器端緩存,cookie是客戶端緩存。
cookie機制採用的是在客戶端保持狀態的方案,而session機制採用的是在服務器端保持狀態的方案
session會在必定時間內保存在服務器上。當訪問增多,會比較佔用你服務器的性能,考慮到減輕服務器性能方面,應當使用cookie。
session是服務器保持客戶端狀態信息的方案,通常是保存在服務器中的一塊內存中,session超時時間在服務器端進行設置。
cookie是客戶端保持用戶信息的方案,通常是文件形式保存,cookie清空時間是在客戶端瀏覽器設置。
從開發角度說,session信息能夠經過技術方案寫到客戶端保存,cookie中的用戶信息,也能夠在用戶訪問該網站時,經過技術手段自動更新用戶的session信息。
單個cookie保存的數據不能超過4K,不少瀏覽器都限制一個站點最多保存20個cookie。
建議:將登錄信息等重要信息存放爲session;其餘信息若是須要保留,能夠放在cookie中.
用戶登陸的原理是什麼?
每次用戶在網站的登陸頁面中輸入用戶名和密碼時,這些信息都會發送到服務器。服務器隨後會將你的密碼與服務器中的密碼進行驗證。
若是二者不匹配,則你會獲得一個錯誤密碼的提示。若是二者匹配,則成功登陸。
用戶登陸時發生了什麼?
登陸後,web 服務器會初始化一個會話session並在你的瀏覽器中設置一個 cookie 變量。該 cookie 變量用於做爲新建會話的一個引用。
搞暈了?讓咱們說的再簡單一點。
會話的原理是什麼?
服務器在用戶名和密碼都正確的狀況下會初始化一個會話。會話的定義很複雜,能夠把它理解爲「關係的開始」。
認證經過後,服務器就開始跟用戶展開一段關係了。因爲服務器不能象咱們人類同樣看東西,它會在咱們的瀏覽器中設置一個 cookie 來將咱們的關係從其餘人與服務器的關係標識出來。
Cookie是幹什麼的?
cookie 是網站在用戶的瀏覽器中存儲的一小段數據。當用戶登陸後,服務器爲用戶建立一段關係或者說一個會話,而後將惟一標識這個會話的會話 id 以 cookie 的形式存儲在用戶的瀏覽器中。全部這些東西存在的緣由在於識別出用戶來,這樣當用戶寫評論或者發推時,服務器能知道是誰在發評論,是誰在發推。當用戶登陸後,會產生一個包含會話 id 的 cookie。這樣,這個會話 id 就被賦予了那個輸入正確用戶名和密碼的人了。也就是說,會話 id 被賦予給了擁有這個帳戶的人了。以後,全部在網站上產生的行爲,服務器都能經過他們的會話 id 來判斷是由誰發起的。
如何讓用戶保持登陸狀態?
會話有必定的時間限制。這一點與現實生活中不同,現實生活中的關係能夠在不見面的狀況下持續很長一段時間,而會話具備時間限制。用戶必需要不斷地經過一些動做來告訴服務器用戶還在線。不然的話,服務器會關掉這個會話,而用戶會被登出。不過在某些網站上能夠啓用"保持登陸"功能,這樣服務器會將另外一個惟一變量以 cookie 的形式保存到咱們的瀏覽器中。這個惟一變量會經過與服務器上的變量進行對比來實現自動登陸。如有人盜取了這個惟一標識(咱們稱之爲 cookie stealing),他們就能訪問用戶的帳戶了。
其餘
1) 因爲Http協議是無狀態的,服務端如何識別客戶端請求呢,只能依靠http報文中新增部分頭字段來實現請求識別(如何在請求body或這參數中設置會員參數,服務器端會話就與自定義的會員識別綁定到一塊兒)
2) 基於瀏覽器的web應用,請求都是有瀏覽器發起的,貌似也不能手動隨便添加請求頭(僅有XMLHttpRequest能夠手動設置請求頭),哪有沒有一種能夠由服務端生成,客戶端請求是自動在請求中設置對應頭字段的技術呢,這就是cookie
Cookie:
cookie是在客戶端負責保存的,既能夠客戶端生成,也能夠服務器端生成,Cookie老是保存在客戶端中,按在客戶端中的存儲位置,可分爲內存Cookie和硬盤Cookie:
1)內存Cookie由瀏覽器維護,保存在內存中,瀏覽器關閉後就消失了,其存在時間是短暫的
2)硬盤Cookie保存在硬盤裏,有一個過時時間,除非用戶手工清理或到了過時時間,硬盤Cookie不會被刪除
3)cookie一些重要的屬性,path,domain,maxAge,secure,httponly,能夠本身去研究一下
4)服務端生成cookie的響應頭爲 Set-Cookie:JSESSIONID=164A9B3B768FD959AA20505D4C09; Path=/; HttpOnly
5)客戶端發送http請求帶的cookie請求頭 Cookie:AMCV_niwodai%40AdobeOrg=-15069…7-badf-4795-9c64-eb9960c23d48
Session的實現原理:
1)服務端首先查找對應的cookie的值(sessionid)
2)根據sessionid,從服務器端session存儲中獲取對應id的session數據,進行返回
3)若是找不到sessionid,服務器端就建立session,生成sessionid對應的cookie,寫入到響應頭中
session共享實現(如tomcat session會話共享)
傳統的session由服務器端生成並存儲,當應用進行分佈式集羣部署的時候,如何保證不一樣服務器上session信息可以共享呢?
兩種實現方式:1.session集中存儲(redis,memcached,hbase等),2. 不一樣服務器上session數據進行復制,兩種方式的優缺點,你們應該一目瞭然
基於session集中存儲的實現方案:
1)新增Filter,攔截請求,包裝HttpServletRequest
2)改寫getSession方法,從session存儲中獲取session數據,返回自定義的HttpSession實現
3)在生成新Session後,寫入sessionid到cookie中
Redis存儲session的須要考慮問題:
1) session數據如何在Redis中存儲?
2) session屬性變動什麼時候觸發存儲?
實現思路:考慮到session中數據相似map的結構,採用redis中hash存儲session數據比較合適,若是使用單個value存儲session數據,不加鎖的狀況下,就會存在session覆蓋的問題,所以使用hash存儲session,每次只保存本次變動session屬性的數據,避免了鎖處理,性能更好;若是每改一個session的屬性就觸發存儲,在變動較多session屬性時會觸發屢次redis寫操做,對性能也會有影響,咱們是在每次請求處理完後,作一次session的寫入,而且之寫入變動過的屬性若是本次沒有作session的更改, 是不會作redis寫入的,僅當沒有變動的session超過一個時間閥值(不變動session刷新過時時間的閥值),就會觸發session保存,以便session可以延長有效期