Session
HTTP 協(xié)議是一種無狀態(tài)協(xié)議,即每次服務(wù)端接收到客戶端的請求時牺氨,都是一個全新的請求狡耻,服務(wù)器并不知道客戶端的歷史請求記錄;Session 和 Cookie 的主要目的就是為了彌補 HTTP 的無狀態(tài)特性猴凹。
大綱
- Session的概念
- Session的創(chuàng)建
- Session的生命周期
- Session的工作機制
- Session的弊端
Session的概念
Session一般譯作會話酝豪,牛津詞典對其的解釋是進行某活動連續(xù)的一段時間。從不同的層面看待Session精堕,它有著類似但不全然相同的含義孵淘。比如,在web應(yīng)用的用戶看來歹篓,他打開瀏覽器訪問一個電子商務(wù)網(wǎng)站瘫证,登錄揉阎、并完成購物直到關(guān)閉瀏覽器,這是一個會話背捌。而在web應(yīng)用的開發(fā)者開來毙籽,用戶登錄時我需要創(chuàng)建一個數(shù)據(jù)結(jié)構(gòu)以存儲用戶的登錄信息,這個結(jié)構(gòu)也叫做Session毡庆。因此在談?wù)揝ession的時候要注意上下文環(huán)境坑赡。而本文談?wù)摰氖且环N基于HTTP協(xié)議的用以增強web應(yīng)用能力的機制或者說一種方案,它不是單指某種特定的動態(tài)頁面技術(shù)么抗,而這種能力就是保持狀態(tài)毅否,也可以稱作保持會話
- Session是服務(wù)端會話的緩存機制(即記錄客戶端狀態(tài)的機制)
- Session是由web的服務(wù)器創(chuàng)建,保存在服務(wù)端
- Session的存儲形式:鍵值對 >> key = value
- Session的過期時間:默認30 minutes
Session的創(chuàng)建?
為了說明問題蝇刀,這里基于Java Servlet理解Session的創(chuàng)建與原理螟加,這里所說Servlet已經(jīng)涵蓋了JSP技術(shù),因為吞琐,Jsp是Servlet技術(shù)的反轉(zhuǎn)捆探,開發(fā)階段看到的JSP頁面最終也會被編譯為Servlet執(zhí)行,兩者有著相同的本質(zhì)站粟。
在Java中Http的Session對象用javax.servlet.http.HttpSession來表示
一個常見的誤解是
:
通常大都以為Session在有客戶端訪問時就被創(chuàng)建黍图,其實并不是;
所以當用戶向服務(wù)器發(fā)送請求時,Session不一定會被創(chuàng)建起來奴烙,而是直到某server端程序調(diào)用 HttpServletRequest.getSession(true)
這樣的語句時才被創(chuàng)建 雌隅。
創(chuàng)建Session的API:二者滿足其一即創(chuàng)建Session
/**
* Servlet
* 默認為:true
* 如果把值改為false,則不會創(chuàng)建session >> 即獲取到的session值為null
*/
HttpSession session = request.getSession(true);
/**
* JSP
* 默認為:true
* 如果把值改為false缸沃,則不會創(chuàng)建session >> 即獲取到的session值為null
*/
<%@ page session="true"%>
當用戶請求的servlet調(diào)用了getSession方法時,都會獲取Session修械,至于是否創(chuàng)建新的Session取決于當前request是否已綁定Session趾牧。當客戶端在請求中加入了jSessionid標識而servlet容器根據(jù)此標識查找到了對應(yīng)的Session對象時,會將此Session綁定到此次請求的request對象肯污,客戶端請求中不帶jSessionid或者此jSessionid對應(yīng)的Session已過期失效時翘单,Session的綁定無法完成,此時必須創(chuàng)建新的Session蹦渣。同時發(fā)送Set-cookie頭通知客戶端開始保持新的會話
Session的生命周期
1.Session生效
- Session在用戶第一次訪問服務(wù)器時創(chuàng)建哄芜。
注意:只有訪問JSP、Servlet等程序時才會創(chuàng)建Session柬唯,只訪問Html认臊,Image等靜態(tài)資源并不會創(chuàng)建Session,但是可以通過特殊的方式強制生成Session
2.Session失效
- 服務(wù)器卸載了當前Web應(yīng)用锄奢,Session銷毀;
- 服務(wù)器自動清除超過有效期的Session失晴,Session銷毀;
服務(wù)器會把長時間沒有活動的Session從服務(wù)器內(nèi)存中清除剧腻,此時的Session便以失效Tomcat中的Session的默認有效期為30分鐘
3. 調(diào)用Session的invalidate()方法銷毀Session;
HttpSession session = request.getSession();
//銷毀該request中的所有session
session.invalidate();
//銷毀session中指定的屬性
session.removeAttribute("key");
3.Session的過期時間計算
- Session的過期時間從Session不活動的時候開始計算涂屁,如果session一直活動书在,session就一直不會過期,也就是說Session只要被訪問拆又,Session過期的計時器就會清0
4.Session的有效期設(shè)置
- 在web.xml中設(shè)置
<!--有效期30分鐘 -->
<session-config>
<session-timeout>30</session-timeout>
</session-config>
- 在程序中手動設(shè)置
//有效期30分鐘(設(shè)置單位為秒)
session.setMaxInactiveInterval(30 * 60);
//設(shè)置為-1即永不過期
request.getSession().setMaxInactiveInterval(-1);
- 在Tomcat中設(shè)置
<!--在Tomcat中的server.xml配置文件中設(shè)置-->
<Context path="/livsorder"
docBase="/home/httpd/html/livsorder"
defaultSessionTimeOut="3600" //有效期30分鐘
isWARExpanded="true"
isWARValidated="false"
isInvokerEnabled="true"
isWorkDirPersistent="false"/>
Session的工作機制
- 服務(wù)器第一次接收到請求儒旬,在內(nèi)存中開辟Session空間,創(chuàng)建session對象帖族,生成sessionId
- 通過響應(yīng)頭Set-cookie:"JSESSIONID=XXXXXXXX"命令栈源,向客戶端發(fā)送要求設(shè)置cookie的響應(yīng)
- 客戶端接收到響應(yīng),在瀏覽器cookie中設(shè)置JSESSIONID=XXXXXX信息盟萨,接下來的客戶端每次向同一個服務(wù)發(fā)送請求時凉翻,該請求都會攜帶cookie中所包含的JESSIONID=XXXXXX的信息 ,該cookie的過期時間為瀏覽器回話結(jié)束
- 服務(wù)器每次接收到請求都會首先從cookie中讀取JESSIONID所對應(yīng)的值捻激,然后通過這個值去session找到該值所對應(yīng)的用戶信息來確認用戶身份
Session的弊端
1. Session失效
- Session失效的原因:
上述的Session都是基于cookie制轰,當瀏覽器禁用了cookie,那么就不會存在cookie胞谭,也無法將JESSIONID的信息設(shè)置在cookie中垃杖,那么session也就失去了應(yīng)有的作用
- Session失效處理方案:重寫URL
具體案例參考:http://www.reibang.com/p/395bac076ea9
當cookie被禁用之后,就無法繼續(xù)通過請求頭Set-cookie來將JESSIONID設(shè)置在cookie中丈屹,但是Session的機制只是讓客戶端每次求同一服務(wù)器的時候调俘,攜帶JESSIONID來實現(xiàn)確認身份作用,而cookie相對來說會讓其實現(xiàn)方式更簡潔旺垒,但是如果cookie不能用彩库,還可以使用其它的方式來實現(xiàn),<u>最常用的即重寫URL先蒋,簡單的說就是通過URL攜帶SessionId參數(shù)把sessionId傳遞到客戶端骇钦,客戶端發(fā)請求始終攜帶sessionId即可
//用于對sendRedirect方法后的url地址進行重寫
response.encodeRedirectURL(java.lang.String url);
//用于對表單action和超鏈接的url地址進行重寫
response.encodeURL(java.lang.String url);
2. Session Hijack (JESSIONID劫持)
- sessionId被劫持的原因
眾所周知cookie是保存在客戶端的,也就是說cookie是透明的竞漾,那么也就是說cookie中所保存的JESSIONID也是對外可見的眯搭,而服務(wù)端只認JESSIONID,即只要用戶知道JESSIONID的值就可以獲取到該JESSIONID所對應(yīng)的session內(nèi)容业岁,就會出現(xiàn)安全性的問題鳞仙,同理重寫URL的方式,同樣會出現(xiàn)sessionId被劫持可能笔时,這就常說的XSS跨站腳本攻擊棍好;
劫持sessionId案例參考:https://www.cnblogs.com/chenpi/p/5434537.html
- session hijack 解決方式
1.加強對提交信息和頁面信息的過濾,讓非法內(nèi)容無處施展;
2.設(shè)置cookie的httpOnly屬性為:true
httpOnly屬性值設(shè)置為true來避免cookie中內(nèi)容被(比如JS)惡意腳本讀取梳玫,這樣在1爹梁、2雙重措施下避免sessionId被劫持(相對來說Set-cookie的方式比URL重寫更為安全)
3. Session功能缺陷(重要問題)
- Session資源浪費
因為Session是保存在服務(wù)器內(nèi)存中的,所以隨著用戶量的大量提升而使Session大量的生成提澎,如果無法及時清理姚垃,就會造成Tomcat內(nèi)存占用過大,導(dǎo)致Tomcat癱瘓
- Session狀態(tài)的范圍局限行
隨著業(yè)務(wù)需求增加盼忌,程序的擴展积糯,或者負載均衡,那么程序就會運行在多臺無服務(wù)器谦纱,但是服務(wù)器的內(nèi)存不能在多臺服務(wù)器之間共享看成,那么Session也無法共享,就需要面臨session同步的問題
- Session功能缺陷的解決方案
無論是資源內(nèi)存的占用還是Session的共享跨嘉,其實都可以采用Session持久化解決 川慌; - 常用的兩種持久化解決方案:
<1>.持久化Session到硬盤(FileStore)
<2>.持久化Session到數(shù)據(jù)庫(JDBCStore)通常用Redis數(shù)據(jù)庫