深刻分析Session和Cookie

爲何須要cookie和session

在Web發展史中,咱們知道瀏覽器與服務器間採用的是http協議,而這種協議是無狀態的,因此這就致使了服務器沒法知道是誰在瀏覽網頁,但很明顯,一些網頁須要知道用戶的狀態,例如登錄,購物車等。java

因此爲了解決這一問題,前後出現了四種技術,分別是隱藏表單域,URL重寫,cookie,session。而用的最多也是比較重要的就是cookie和session了。apache

Cookie

首先來了解cookie瀏覽器

是什麼

cookie是瀏覽器保存在用戶電腦上的一小段文本,通俗的來說就是當一個用戶經過http訪問到服務器時,服務器會將一些Key/Value鍵值對返回給客戶端瀏覽器,並給這些數據加上一些限制條件,在條件符合時這個用戶下次訪問這個服務器時,數據經過請求頭又被完整地給帶回服務器,服務器根據這些信息來判斷不一樣的用戶。bash

也就是說,cookie是服務器傳給客戶端並保存在客戶端的一段信息,這個Cookie是有大小,數量限制的!!服務器

Cookie的建立

當前Cookie有兩個版本,分別對應兩種設置響應頭:「Set-Cookie」和「Set-Cookie2」。在Servlet中並不支持Set-Cookie2,因此咱們來看看Set-Cookie的屬性項:cookie

屬性項 屬性項介紹
NAME=VALUE 鍵值對,能夠設置保存的Key/Value,這裏NAME不能和其餘屬性項名字同樣
Expires 過時時間,在這個時間點後Cookie失效
Domain 生成Cookie域名
Path 該Cookie是在當前那個路徑下生成的
Secure 加密設置,設置他以後,只會在SSH鏈接時纔會回傳該Cookie

如今,咱們先來了解這些屬性項,其餘的都說的很清楚了,咱們來看看Domain有什麼用:

如今,咱們假設這裏有兩個域名:session

域名A:a.b.f.com.cn
域名B:c.d.f.com.cndom

顯然,域名A和域名B都是f.com.cn的子域名加密

綜上所述,咱們知道了domain的用處,聰明的小夥伴已經發現了,單點登錄就是用這個原理實現的。spa

好的,如今瞭解完了Set-Cookie的屬性項,開始建立Cookie

Web服務器經過發送一個稱爲Set-Cookie的http消息來建立一個Cookie:

Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]

這裏咱們思考一個問題,當咱們在服務器建立多個Cookie時,這些Cookie最終是在一個Header項中仍是以獨立的Header存在的呢?


image

int size = headers.size();
for(int i = 0;i < size;i++){
    outputBuffer.sendHeader(headers.getName(i),headers.getValue(i));
}
複製代碼
咱們能夠看到,構建http返回字節流時是將Header中全部的項順序寫出,而沒有進行任何修改。因此能夠想象在瀏覽器在接收http返回的數據時是分別解析每個Header項。

++ 接着,在客戶端進行保存,如何保存呢?這裏又要對Cookie進行進一步的瞭解。 ++

Cookie的分類

會話級別Cookie:

所謂會話級別Cookie,就是在瀏覽器關閉以後Cookie就會失效。

持久級別Cookie:

保存在硬盤的Cookie,只要設置了過時時間就是硬盤級別Cookie。

好的,如今cookie保存在了客戶端,當咱們去請求一個URL時,瀏覽器會根據這個URL路徑將符合條件的Cookie放在請求頭中傳給服務器。

Session

各位客官看到這裏實屬不易,😀,但咱們仍是要想一想,Cookie是有大小限制和數量限制的,而且愈來愈多的Cookie表明客戶端和服務器的傳輸量增長,可不能夠每次傳的時候不傳全部cookie值,而只傳一個惟一ID,經過這個ID直接在服務器查找用戶信息呢?答案是有的,這就是咱們的session。

理解Session:

Session是基於Cookie來工做的,同一個客戶端每次訪問服務器時,只要當瀏覽器在第一次訪問服務器時,服務器設置一個id並保存一些信息(例如登錄就保存用戶信息,視具體狀況),並把這個id經過Cookie存到客戶端,客戶端每次和服務器交互時只傳這個id,就能夠實現維持瀏覽器和服務器的狀態,而這個ID一般是NAME爲JSESSIONID的一個Cookie。

Session和Cookie

實際上,有四種方式讓Session正常工做

  1. 經過URL傳遞SessionID
  2. 經過Cookie傳遞SessionID
  3. 經過SSL傳遞SessionID
  4. 經過隱藏表單傳遞SessionID
第一種狀況:

當瀏覽器不支持Cookie功能時,瀏覽器會將用戶的SessionCookieName(默認爲JSESSIONID)重寫到用戶請求的URL參數中。格式:/path/Servlet;name=value;name2=value2?Name3=value3

第三種狀況:

會根據javax.servlet.request.ssl_session屬性值設置SessionID。

注:若是客戶端支持Cookie,又經過URL重寫,Tomcat仍然會解析Cookie中的SessionID並覆蓋URL中的SessionID

工做原理

咱們先看session工做的時序圖

image

1、建立Session

當客戶端訪問到服務器,服務器會爲這個客戶端經過request.getSession()方法建立一個Session,若是當前SessionID尚未對應的HttpSession對象,就建立一個新的,並添加到org.apache.catalina.Manager的sessions容器中保存,這就作到了對狀態的保持。固然,這個SessionID是惟一的

2、session保存

由圖可知,session對象已經保存在了Manager類中,StandardManager做爲實現類,經過requestedSessionId從StandardManager的sessions集合中取出StandardSession對象。

咱們來看看StandardManager時如何對全部StandardSession對象進行生命週期管理

當Servlet容器關閉:

StandardManager將持久化沒過時的StandardSession對象(必須調用Servlet容器中的stop和start命令,不能直接kill)

當Servlet容器重啓時:

StandardManager初始化會重讀這個文件,解析出全部session對象。

3、session的銷燬

這裏有一個誤區,也是我以前的錯誤理解,就是我將session的生命週期理解成一次會話,瀏覽器打開就建立,瀏覽器關閉就銷燬,這樣理解是錯的!!

session的聲明週期是從建立到超時過時

也就是說,當session建立後,瀏覽器關閉,會話級別的Cookie被銷燬,若是沒有超過設定時間,該SessionID對應的session是沒有被銷燬的

檢查session失效

檢查每一個Session是否失效是在Tomcat的一個後臺線程完成的(backgroundProcess()方法中);除了後臺進程檢驗session是否失效外,調用request.getSession()也會檢查該session是否過時,固然,調用這種方法若是過時的話又會從新建立一個新的session。

作個總結

相同點和不一樣點

相同點(有關係的地方)

  • Session和Cookie都是爲了讓http協議又狀態而存在
  • Session經過Cookie工做,Cookie傳輸的SessionID讓Session知道這個客戶端究竟是誰

不一樣點

Session將信息保存到服務器,Cookie將信息保存在客戶端

工做流程

當瀏覽器第一次訪問服務器時,服務器建立Session並將SessionID經過Cookie帶給瀏覽器保存在客戶端,同時服務器根據業務邏輯保存相應的客戶端信息保存在session中;客戶端再訪問時上傳Cookie,服務器獲得Cookie後獲取裏面的SessionID,來維持狀態。




參考:alibaba叢書《深刻分析Java Web》

相關文章
相關標籤/搜索