Javaweb Session機制(有待補充)


Javaweb Session機制

一、前言

  session,中文經常翻譯為會話,其本來的含義是指有始有終的一系列動作/消息,比如打電話是從拿起電話撥號到掛斷電話這中間的一系列過程可以稱之為一個session。

  session在Web開發環境下的語義又有了新的擴展,它的含義是指一類用來在客戶端與服務器端之間保持狀態的解決方案。有時候Session也用來指這種解決方案的存儲結構。

二、Session機制

  session機制采用的是在服務器端保持 HTTP 狀態信息的方案 。

  服務器使用一種類似於散列表的結構(也可能就是使用散列表)來保存信息。

  當程序需要為某個客戶端的請求創建一個session時,服務器首先檢查這個客戶端的請求里是否包含了一個session標識(即sessionId),如果已經包含一個sessionId則說明以前已經為此客戶創建過session,服務器就按照session id把這個session檢索出來使用(如果檢索不到,可能會新建一個,這種情況可能出現在服務端已經刪除了該用戶對應的session對象,但用戶人為地在請求的URL后面附加上一個JSESSION的參數)。如果客戶請求不包含sessionId,則為此客戶創建一個session並且生成一個與此session相關聯的sessionId,這個session id將在本次響應中返回給客戶端保存。

三、保存Session id的幾種方式

  保存session id的方式可以采用cookie,這樣在交互過程中瀏覽器可以自動的按照規則把這個標識發送給服務器。

  由於cookie可以被人為的禁用,必須有其它的機制以便在cookie被禁用時仍然能夠把session id傳遞回服務器,經常采用的一種技術叫做URL重寫,就是把session id附加在URL路徑的后面,附加的方式也有兩種,一種是作為URL路徑的附加信息,另一種是作為查詢字符串附加在URL后面。網絡在整個交互過程中始終保持狀態,就必須在每個客戶端可能請求的路徑后面都包含這個session id。

四、Session Cookie

  session通過SessionID來區分不同的客戶, session是以cookie或URL重寫為基礎的,默認使用cookie來實現,系統會創造一個名為JSESSIONID的輸出cookie,這稱之為session cookie,以區別persistent cookies(也就是我們通常所說的cookie),session cookie是存儲於瀏覽器內存中的,並不是寫到硬盤上的,通常看不到JSESSIONID,但是當把瀏覽器的cookie禁止后,web服務器會采用URL重寫的方式傳遞Sessionid,這時地址欄會看到

  session cookie針對某一次會話而言,會話結束session cookie也就隨着消失了,而persistent cookie只是存在於客戶端硬盤上的一段文本。

  關閉瀏覽器,只會是瀏覽器端內存里的session cookie消失,但不會使保存在服務器端的session對象消失,同樣也不會使已經保存到硬盤上的持久化cookie消失。

五、Session的創建與刪除

  一個常見的錯誤是以為session在有客戶端訪問時就被創建,然而事實是直到某server端程序(如Servlet)調用HttpServletRequest.getSession(true) 或者 HttpServletRequest.getSession()這樣的語句時才會被創建。

  session在下列情況下被刪除:
  A.程序調用HttpSession.invalidate()
  B.距離上一次收到客戶端發送的session id時間間隔超過了session的最大有效時間
  C.服務器進程被停止

  注意:關閉瀏覽器只會使存儲在客戶端瀏覽器內存中的session cookie失效,不會使服務器端的session對象失效。

  另外,兩個瀏覽器窗口訪問應用程序會使用同一個session

  通常session cookie是不能跨窗口使用的(IE 8 版本以前),當你新開了一個瀏覽器窗口進入相同頁面時,系統會賦予你一個新的session id,這樣信息共享的目的就達不到了。

  此時可以先把session id保存在persistent cookie中(通過設置cookie的最大有效時間),然后在新窗口中讀出來,就可以得到上一個窗口的session id了,這樣通過session cookie和persistent cookie的結合就可以實現了跨窗口的會話跟蹤。

六、Session的超時管理

  WEB服務器無法判斷當前的客戶端瀏覽器是否還會繼續訪問,也無法檢測客戶端瀏覽器是否關閉,所以,即使客戶已經離開或關閉了瀏覽器,WEB服務器還要保留與之對應的HttpSession對象。

  隨着時間的推移而不斷增加新的訪問客戶端,WEB服務器內存中將會因此積累起大量的不再被使用的HttpSession對象,並將最終導致服務器內存耗盡。

  WEB服務器采用“超時限制”的辦法來判斷客戶端是否還在繼續訪問,如果某個客戶端在一定的時間之內沒有發出后續請求,WEB服務器則認為客戶端已經停止了活動,結束與該客戶端的會話並將與之對應的HttpSession對象變成垃圾。

  如果客戶端瀏覽器超時后再次發出訪問請求,WEB服務器則認為這是一個新的會話的開始,將為之創建新的HttpSession對象和分配新的會話標識號。

  會話的超時間隔可以在web.xml文件中設置,其默認值由Servlet容器定義。
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>

七、Java中與Session相關的常用方法

HttpSession接口中的方法

getId方法
getCreationTime方法
getLastAccessedTime方法
setMaxInactiveInterval方法
getMaxInactiveInterval方法
isNew方法:如果客戶端請求消息中返回了一個與Servlet程序當前獲得的HttpSession對象的會話標識號相同的會話標識號,則認為這個HttpSession對象不是新建的。
invalidate方法
getServletContext方法
setAttribute方法
getAttribute方法
removeAttribute方法
getAttributeNames方法

HttpServletRequest接口中的Session方法

getSession方法
public HttpSession getSession(boolean create)
public HttpSession getSession()
isRequestedSessionIdValid方法
isRequestedSessionIdFromCookie方法
isRequestedSessionIdFromURL方法

八、利用URL重寫實現Session跟蹤

  Servlet規范中引入了一種補充的會話管理機制,它允許不支持Cookie的瀏覽器也可以與WEB服務器保持連續的會話。這種補充機制要求在響應消息的實體內容中必須包含下一次請求的超鏈接,並將會話標識號作為超鏈接的URL地址的一個特殊參數。

  將會話標識號以參數形式附加在超鏈接的URL地址后面的技術稱為URL重寫。如果在瀏覽器不支持Cookie或者關閉了Cookie功能的情況下,WEB服務器還要能夠與瀏覽器實現有狀態的會話,就必須對所有可能被客戶端訪問的請求路徑(包括超鏈接、form表單的action屬性設置和重定向的URL)進行URL重寫。

HttpServletResponse接口中定義了兩個用於完成URL重寫方法:
encodeURL方法
encodeRedirectURL方法

九、application與session辨析

application域范圍屬性

Session域范圍屬性

十、HttpSession 的生命周期:

什么時候創建 HttpSession 對象?

  是否瀏覽器訪問服務端的任何一個JSP或Servlet,服務器都會立即創建一個 HttpSession 對象呢?不一定。若當前的JSP(或Servlet)是客戶端訪問的當前WEB應用的第一個資源,且JSP的page指定的session屬性值為false, 則服務器就不會為JSP創建一個HttpSession對象;若當前 JSP 不是客戶端訪問的當前 WEB 應用的第一個資源,且其他頁面已經創建一個 HttpSession 對象,則當前 JSP 頁面會返回一個會話的 HttpSession 對象,而不會創建一個新的 HttpSession‘ 對象

  session=“false“  到底表示什么意思?當前 JSP 頁面禁用 session 隱含變量!但可以使用其他的顯式的 HttpSession 對象

  對於 Serlvet 而言:若 Serlvet 是客戶端訪問的第一個 WEB 應用的資源,則只有調用了 request.getSession() 或 request.getSession(true) 才會創建 HttpSession 對象

什么時候銷毀 HttpSession 對象?

有待補充.............

十一、利用Session避免表單的重復提交

  調用 RequestDispatcher.forward() 方法,瀏覽器所保留的URL 是先前的表單提交的 URL,此時點擊”刷新”, 瀏覽器將再次提交用戶先前輸入的數據,引起重復提交

  如果采用 HttpServletResponse.sendRedirct() 方法將客戶端重定向到成功頁面,將不會出現重復提交的問題

  包含有FORM表單的頁面必須通過一個服務器程序動態產生,服務器程序為每次產生的頁面中的FORM表單都分配一個唯一的隨機標識號,並在FORM表單的一個隱藏字段中設置這個標識號,同時在當前用戶的Session域中保存這個標識號。

  當用戶提交FORM表單時,負責接收這一請求的服務器程序比較FORM表單隱藏字段中的標識號與存儲在當前用戶的Session域中的標識號是否相同,如果相同則處理表單數據,處理完后清除當前用戶的Session域中存儲的標識號。在下列情況下,服務器程序將忽略提交的表單請求:
  ①當前用戶的Session中不存在表單標識號
  ②用戶提交的表單數據中沒有標識號字段
  ③存儲在當前用戶的Session域中的表單標識號與表單數據中的標識號不同

  瀏覽器只有重新向WEB服務器請求包含FORM表單的頁面時,服務器程序才又產生另外一個隨機標識號,並將這個標識號保存在Session域中和作為新返回的FORM表單中的隱藏字段值。

  TokenProcessor.java:用於管理表單標識號的工具類,它主要用於產生、比較和清除存儲在當前用戶Session中的表單標識號。為了保證表單標識號的唯一性,每次將當前SessionID和系統時間的組合值按MD5算法計算的結果作為表單標識號,並且將TokenProcessor類設計為單件類

  表單提交常見問題:同一個用戶打開同一個瀏覽器進程的多個窗口來並發訪問同一個WEB站點的多個FORM表單頁面時,將會出現表單無法正常提交的情況。

  解決方案:將FORM表單的標識號作為表單隱藏字段的名稱,如下所示:
  <input type='hidden' name='4b15c6b2f573831b4b5107d849fcafb8' value=''>

  將所有的表單標識號存儲進一個Vector集合對象中,並將Vector集合對象存儲進Session域中。當表單提交時,先從Session域中取出Vector集合對象,然后再從Vector集合對象中逐一取出每個表單標識號作為參數調用HttpServletRequest.getParameter方法,如果其中有一次調用的返回值不為null,則接受並處理該表單數據,處理完后將該表單標識號從Vector集合對象中刪除。

十二、利用Session實現一次性驗證碼

  一次性驗證碼的主要目的就是為了限制人們利用工具軟件來暴力猜測密碼,其原理與利用Session防止表單重復提交的原理基本一樣,只是將表單標識號變成了驗證碼的形式,並且要求用戶將提示的驗證碼手工填寫進一個表單字段中,而不是通過表單的隱藏字段自動回傳給服務器。

  服務器程序接收到表單數據后,首先判斷用戶是否填寫了正確的驗證碼,只有該驗證碼與服務器端保存的驗證碼匹配時,服務器程序才開始正常的表單處理流程。

  密碼猜測工具要逐一嘗試每個密碼的前題條件是先輸入正確的驗證碼,而驗證碼是一次性有效的,這樣基本上就阻斷了密碼猜測工具的自動地處理過程。

如果,您對我的這篇博文有什么疑問,歡迎評論區留言,大家互相討論學習。
如果,您認為閱讀這篇博客讓您有些收獲,不妨點擊一下右下角的【推薦】。
如果,您希望更容易地發現我的新博客,不妨點擊一下左下角的【關注我】。
如果,您對我的博文感興趣,可以關注我的后續博客,我是【AlbertRui】。

轉載請注明出處和鏈接地址,歡迎轉載,謝謝!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM