天天看點

Tomcat中的Session小結什麼是SessionSession的目的實作機制Tomcat中的session實作session存在的問題

對Tomcat而言,Session是一塊在伺服器開辟的記憶體空間,其存儲結構為ConcurrentHashMap;

Http協定是一種無狀态協定,即每次服務端接收到用戶端的請求時,都是一個全新的請求,伺服器并不知道用戶端的曆史請求記錄;

Session的主要目的就是為了彌補Http的無狀态特性。簡單的說,就是伺服器可以利用session存儲用戶端在同一個會話期間的一些操作記錄;

1、伺服器如何判斷用戶端發送過來的請求是屬于同一個會話?

答:用Session id區分,Session id相同的即認為是同一個會話,在Tomcat中Session id用JSESSIONID表示;

2、伺服器、用戶端如何擷取Session id?Session id在其之間是如何傳輸的呢?

答:伺服器第一次接收到請求時,開辟了一塊Session空間(建立了Session對象),同時生成一個Session id,并通過響應頭的Set-Cookie:“JSESSIONID=XXXXXXX”指令,向用戶端發送要求設定cookie的響應;

用戶端收到響應後,在本機用戶端設定了一個JSESSIONID=XXXXXXX的cookie資訊,該cookie的過期時間為浏覽器會話結束;

接下來用戶端每次向同一個網站發送請求時,請求頭都會帶上該cookie資訊(包含Session id);

然後,伺服器通過讀取請求頭中的Cookie資訊,擷取名稱為JSESSIONID的值,得到此次請求的Session id;

ps:伺服器隻會在用戶端第一次請求響應的時候,在響應頭上添加Set-Cookie:“JSESSIONID=XXXXXXX”資訊,接下來在同一個會話的第二第三次響應頭裡,是不會添加Set-Cookie:“JSESSIONID=XXXXXXX”資訊的;

而用戶端是會在每次請求頭的cookie中帶上JSESSIONID資訊;

以chrome浏覽器為例,通路一個基于tomcat伺服器的網站的時候,

浏覽器第一次通路伺服器,伺服器會在響應頭添加Set-Cookie:“JSESSIONID=XXXXXXX”資訊,要求用戶端設定cookie,如下圖:

Tomcat中的Session小結什麼是SessionSession的目的實作機制Tomcat中的session實作session存在的問題

同時我們也可以在浏覽器中找到其存儲的sessionid資訊,如下圖

Tomcat中的Session小結什麼是SessionSession的目的實作機制Tomcat中的session實作session存在的問題

接下來,浏覽器第二次、第三次...通路伺服器,觀察其請求頭的cookie資訊,可以看到JSESSIONID資訊存儲在cookie裡,發送給伺服器;且響應頭裡沒有Set-Cookie資訊,如下圖:

Tomcat中的Session小結什麼是SessionSession的目的實作機制Tomcat中的session實作session存在的問題

隻要浏覽器未關閉,在通路同一個站點的時候,其請求頭Cookie中的JSESSIONID都是同一個值,被伺服器認為是同一個會話。

首先,從session中擷取key為count的值,累加,存入session,并列印;

然後,每次從請求中擷取列印cookie資訊,從響應中擷取列印Header的Set-Cookie資訊:

Tomcat中的Session小結什麼是SessionSession的目的實作機制Tomcat中的session實作session存在的問題
Tomcat中的Session小結什麼是SessionSession的目的實作機制Tomcat中的session實作session存在的問題

部署到tomcat後,連續通路該servlet,觀察控制台輸出,如下,用戶端第一次通路伺服器的時候,在服務端的響應頭裡添加了JSESSIONID資訊,且接下來用戶端的每次通路都會帶上該JSESSIONID:

Tomcat中的Session小結什麼是SessionSession的目的實作機制Tomcat中的session實作session存在的問題

隻要使用者知道JSESSIONID,該使用者就可以擷取到JSESSIONID對應的session内容,還是以上面這個例子為例,

我先用IE浏覽器通路該站點,比如連續通路了5次,此時,session中的count值為:

Tomcat中的Session小結什麼是SessionSession的目的實作機制Tomcat中的session實作session存在的問題

檢視該會話的Session id,為6A541281A79B24BC290ED3270CF15E32

Tomcat中的Session小結什麼是SessionSession的目的實作機制Tomcat中的session實作session存在的問題

接下來打開chrome控制台,将IE浏覽器擷取過來的JSESSIONID資訊(“6A541281A79B24BC290ED3270CF15E32”)寫入到cookie中,如下

Tomcat中的Session小結什麼是SessionSession的目的實作機制Tomcat中的session實作session存在的問題

接着删除其中的一個,隻留下JSESSIONID為“6A541281A79B24BC290ED3270CF15E32”的cookie;

Tomcat中的Session小結什麼是SessionSession的目的實作機制Tomcat中的session實作session存在的問題

重新整理頁面,發現我們從session擷取的count值已經變成6了,說明此次chrome浏覽器的請求劫持了IE浏覽器會話中的session,

Tomcat中的Session小結什麼是SessionSession的目的實作機制Tomcat中的session實作session存在的問題

Tomcat中一個會話對應一個session,其實作類是StandardSession,檢視源碼,可以找到一個attributes成員屬性,即存儲session的資料結構,為ConcurrentHashMap,支援高并發的HashMap實作;

那麼,tomcat中多個會話對應的session是由誰來維護的呢?ManagerBase類,檢視其代碼,可以發現其有一個sessions成員屬性,存儲着各個會話的session資訊:

接下來,看一下幾個重要的方法,

用戶端每次的請求,tomcat都會在HashMap中查找對應的key為JSESSIONID的Session對象是否存在,可以檢視Request的doGetSession方法源碼,如下源碼:

Tomcat中的Session小結什麼是SessionSession的目的實作機制Tomcat中的session實作session存在的問題

 View Code

先看doGetSession方法中的如下代碼,這個一般是第一次通路的情況,即建立session對象,session的建立是調用了ManagerBase的createSession方法來實作的; 另外,注意response.addSessionCookieInternal方法,該方法的功能就是上面提到的往響應頭寫入“Set-Cookie”資訊;最後,還要調用session.access方法記錄下該session的最後通路時間,因為session是可以設定過期時間的;

Tomcat中的Session小結什麼是SessionSession的目的實作機制Tomcat中的session實作session存在的問題
Tomcat中的Session小結什麼是SessionSession的目的實作機制Tomcat中的session實作session存在的問題

再看doGetSession方法中的如下代碼,這個一般是第二次以後通路的情況,通過ManagerBase的findSession方法查找session,其實就是利用map的key從ConcurrentHashMap中拿取對應的value,這裡的key即requestedSessionId,也即JSESSIONID,同時還要調用session.access方法,記錄下該session的最後通路時間;

Tomcat中的Session小結什麼是SessionSession的目的實作機制Tomcat中的session實作session存在的問題
Tomcat中的Session小結什麼是SessionSession的目的實作機制Tomcat中的session實作session存在的問題

這個我們一般調用getAttribute/setAttribute方法:

getAttribute方法很簡單,就是根據key從map中擷取value;

setAttribute方法稍微複雜點,除了設定key-value外,如果添加了一些事件監聽(HttpSessionAttributeListener)的話,還要通知執行,如beforeSessionAttributeReplaced, afterSessionAttributeReplaced, beforeSessionAttributeAdded、 afterSessionAttributeAdded。。。

安全性,session劫持,這個前面已經舉過例子了;

增加伺服器壓力,因為session是直接存儲在伺服器的記憶體中的;

如果存在多台伺服器的話,還存在session同步問題,當然如果隻有一台tomcat伺服器的話,也就沒有session同步的事情了,然而現在一般的應用都會用到多台tomcat伺服器,通過負載均衡,同一個會話有可能會被配置設定到不同的tomcat伺服器,是以很可能出現session不一緻問題;解決session同步問題,實際上主要是保證能夠抽離出一塊共享空間存放session資訊,且這塊空間不同的tomcat伺服器都可以通路到;一般這塊共享的空間可以是資料庫,或者某台伺服器的記憶體空間,甚至硬碟空間,或者用戶端的cookie也是可以的;

本文轉自風一樣的碼農部落格園部落格,原文連結:http://www.cnblogs.com/chenpi/p/5434537.html,如需轉載請自行聯系原作者