因為http,https是無狀態的,也就是當我們連續兩次訪問同一個web網站,網站是無法分辨這兩次訪問是來自同一個人。對於它來說,這兩次訪問是沒有關係的。 就像是,我們進入了澡堂洗澡,中途要從入口出來接電話,可是當我們再次進去的時候,人家就不認識你了,還管著問你要貴賓卡呢!那麼怎麼讓這個門口迎賓能認 ...
一:為什麼需要session
因為http,https是無狀態的,也就是當我們連續兩次訪問同一個web網站,網站是無法分辨這兩次訪問是來自同一個人。對於它來說,這兩次訪問是沒有關係的。
就像是,我們進入了澡堂洗澡,中途要從入口出來接電話,可是當我們再次進去的時候,人家就不認識你了,還管著問你要貴賓卡呢!那麼怎麼讓這個門口迎賓能認出你是VIP呢?
答案當然是VIP的卡嘛!就類似於令牌。每次進澡堂子就分配一個。這樣不管你中途出來接多少次電話,只要這VIP卡不過期,人家都會對你客客氣氣,讓你有一種賓至如歸的感覺!
所以我們知道session的第一個作用是令牌,讓網站記住我們的訪問。
如果你覺得session的作用只有這樣,那你就太天真了!我們還是從去澡堂子聊起。去過澡堂子的人都知道,我們是穿著衣服去澡堂子的,還會有手機,沒準身份證什麼的。這些東西都得有地方存放!
那這時候我們的貴賓卡就起到作用了,一般澡堂子都會有一個跟卡對應的柜子,可以用卡刷開。這個柜子可以放我們所有的個人物品。那麼聰明的你,是不是想到了session之於網站的相似功能呢?沒錯,
session在我們登錄之後,就可以手動存放你所有想放入的一切。包括用戶的基本信息,許可權等。(但是切忌不要存太多東西,畢竟澡堂子的柜子都不會太大,也不會太多!太大,太多會把澡堂子撐爆的!)。
那麼這個存放東西的柜子在web網站的哪裡呢?答案是web網站的記憶體中。這個存取需要你手動進行。所以,你就知道了session的第二個作用是,存東西。
二:session的作用原理
當我們的請求到達自伺服器的時候,伺服器並不一定為我們分配session。只有當我們顯式調用getSession()或者getSession(true)才會真的產生。因為伺服器保存session是需要開銷的,只有當你真的
顯示去調用這個方法,伺服器才知道你有這個需求。但是很多情況下我們似乎並沒有顯式去調用這個方法,卻能看到cookie這個請求頭中有jsessionid,這是為什麼呢?你們有沒有發現,我們的jsp頭部會預設有
一個session=true的屬性?有這個屬性後,伺服器將jsp轉為servlet後,裡面就會有顯式的調用這個方法,所以也同樣會產生session。
上面說了產生session的時機,那麼當顯式調用後,伺服器就會生成一個按照'隨機數+時間+jvmid'的規則生成的sessionId,tomcat伺服器中叫jsessionId。併在伺服器記憶體中開闢一個記憶體區域,與這個sessionId對應。
sessionId是這個記憶體區域唯一的存取憑證。
那麼session到底是一個什麼樣的數據結構呢?相信聰明的你,通過根據sessionId去獲取session就會猜想session的結構是一個MAP.事實確實如此,session的數據結構是ConcurrentHashMap<String,ConcurrentHashMap<String,Object>>
ConcurrentHashMap保存它的併發安全性。而裡面一層的Map則是某個用戶的多個session級屬性。
那麼session是如何使用呢?當我們伺服器生成一個session和sessionId後,就會通過一個set-Cookie的Header,通知瀏覽器你要在用戶本地創建一個cookie.用來保存這個sessionId.這個Header中還包括path和httpOnly,過期時間(預設是-1,表示
一個會話期)。瀏覽器保存這個sessionId的Cookie後,後面的每次請求,瀏覽器都會自動去將這個cookie設置到請求頭中,那麼伺服器接收到請求後,就會說“哦,老熟人又來了”。這個ssesionId能獲取到對應的session。也就能知道前面操作留下的數據。
那麼伺服器的這個session什麼時候會消失呢?很多人可能會猜想一個貌似完美的方案,當瀏覽器關閉後,session就會消失?但是事實是不可能的!因為我們知道,不可能關閉瀏覽器後,就去觸發一個請求去通知瀏覽器,調用session的過期或者
刪除方法。這樣就將瀏覽器和伺服器強烈耦合在一起!另外一個合理的做法是,當瀏覽器關閉後,意味著一個會話期滿後,瀏覽器之前創建的Cookie就會失效。這時候再打開瀏覽器,它是不會再在請求中附上之前那個sessionId的,所以儘管這個時候這個session可能還
存在,但是沒有沒有sessionId這個憑證來操作它了!那麼session都會有一個過期時間。這個都是可配的,一般在web.xml中。那麼如果一個session的最後操作時間距離某個時間點,中間的時間間隔恰好是>=那個過期時間,那麼當檢查進行時,就會銷毀這個session。
三,session機制存在的問題
第一個,session劫持:大家在上面可能會發現,sessionId這個憑證,是保存在用戶本地的。那麼如果一旦被別人找到並複製了這個憑證,就意味著他也能獲取伺服器的認證,能獲取到伺服器上你存放的東西了!著就像是好萊塢大片里經常
出現的特工冒用別人身份的橋段。
第二個,Cookie禁用問題:session的憑證,就是依靠瀏覽器的cookie,一旦用戶在本地禁用cookie,那麼這個令牌就沒有了,意味了伺服器存放的東西,永遠沒有人來領取。
第三個,session的分散式問題:現在的數據都是幾何級增長,系統都是分散式架構。如果一個前端系統有A,B兩台。那麼當用戶訪問A系統,A系統給他分配了一個session,並給他一個令牌,那麼當他下次再去訪問B系統時,帶著這個令牌,傳統的session就會
出現問題。因為令牌是A系統頒給他的,B系統並不認識。
以上3個問題大多都是有解決辦法的。