在上一篇部落格中《acegi security基於form表單認證-debug調試》中講述了一個現象,每次重新開啟新的瀏覽器,依然保留著上個頁面。針對上個例子來說,要麼是目前使用者資訊、要麼是無許可權資訊。出現這個現象上篇部落格我們已經分析過,就是securitycontext中已經存在認證過的權限物件。
那麼,我想,重新運行userinfo.jsp頁面,重新認證一遍,怎麼辦啊?唯一的辦法,stop server;open server again;不要這麼笨吧。 肯定有人會說,傻啊,運行login.jsp頁面啊。這也是一個辦法。但是遇到一個這樣的情況:這個頁面靜止不操作半天,然後重新整理這個頁面時,作為程式員的你,覺得該如何處理呢?結果又該是怎樣的呢?
基於此條件下,我們給大家介紹一下httpSessionContextIntegrationFilter,這個session過濾器開篇已經介紹過了,但是在兩個demo中一直沒有用到。那我們今天就在acegi設定檔中添加這個fiter,記住這個sessionfilter是在各個filter之前的,acegi設定檔中的filter是有順序要求的,想起來沒?若沒,請溫習《acegi security入門》 在form表單認證demo中,acegi設定檔中添加sessionfiter,其他一切都無需修改。
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy"> <property name ="filterInvocationDefinitionSource"> <value > PATTERN_TYPE_APACHE_ANT /**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor </value > </property > </bean > <bean id ="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter" />
另外再溫習一次,acegi控制流程程:
目的是:再開啟一個會話瀏覽器或session到期後,應該跳轉到登陸頁面。 添加sessionfitler後 測試如下: 1. 依然是運行http://localhost:8080/acegitest2/userinfo.jsp 2. 第一次運行,出現登陸頁面,使用test/1無許可權使用者登陸,展示無許可權頁面 3. 不關閉此瀏覽器,再開啟一個瀏覽器,再次運行http://localhost:8080/acegitest2/userinfo.jsp 你的瀏覽器顯示什麼頁面呢? 是這樣? 還是這樣?
若是,則說明session是一樣的。我們知道IE8中預設是session共用的。 測試載入器:是IE9。是IE8。 4. 關閉此瀏覽器,再開啟一個瀏覽器,再次運行http://localhost:8080/acegitest2/userinfo.jsp 你的瀏覽器顯示什麼頁面呢? 你會發現IE8和IE9下,都會出現同一個頁面即login.jsp。 5. 思考? 再次出現驗證出現登陸頁面,說明是不同的session。關閉瀏覽器後,為啥IE8、9,session就沒有了呢。 我們知道cookie是用戶端存放的,session是伺服器維持的,關閉瀏覽器,只是我用戶端關閉,tomcat沒有停止啊?難道伺服器知道瀏覽器關閉?
瀏覽器與伺服器之間一系列互動動作稱為一個session。
session存放在伺服器上,由伺服器維持session。
session是在伺服器上,當然是伺服器建立的。
- session何時建立的呢?是我們訪問url地址時就建立的嗎?
很多人都以為我們一運行url,就自動產生了session。這是很多錯誤的觀點。對於對於這種觀點的人,也可以理解,因為開始我們不動手做或不涉及到session這塊,是自然而然的產生這種觀點,並且大多部分我們用架構或訪問人家網站什麼的,都會有記憶功能。
實際上session通過java程式建立的:request.getSession(flag);getSession不是獲得當前的session嗎,怎麼會是建立session呢?沒有create啊?其實這是隱含建立的,我們解釋一下這個方法,也許第一眼又誤認為了。 request.getSession(flag);為啥有個參數呢?你平時都帶不帶參數呢?帶或不帶,也許影響你的程式哦。 當flag=false時,request.getSession(false)有則返回當前session,無則返回null。 當flag=true時,request.getSession(true)有則返回當前session,無則建立一個session。 而我們經常使用的 request.getSession();這個方法,到底等同以上那個呢?哈哈,不幸的是,它等同於參數為true的方法。在座的您,有沒有中槍的哦? 哈哈,明白了吧,為啥產生session了吧。
肯定有人站起來反駁,我就建立一個helloworld.jsp,沒有任何java程式,jsp中還可以輸出session呢。在jsp中<% out.println(session.getId());%>,你如何解釋這個現象啊--啊--啊。 哈哈,這次你又被蒙在鼓裡了。我們都知道jsp最後都編譯成java程式,實際上jsp就是一個sevlet,那麼servlet肯定優先於jsp頁面。親,你去看看jsp編譯成java程式中有沒有類似request.getSession();這句話。 在tomcat_home/work/Catalina/localhost/org/你的項目/org/apache/jsp/你jsp目錄中相應的java和class檔案,嘗試著開啟一下,猛然會發現,我KAO,還真有這句話:session = pageContext.getSession();至於pageContext我就不解釋啦。 這下是否有一種被欺騙的趕腳啊。其實人家可是為咱們好。
此時剛才的人又站起來了,再次疑惑,可jsp啥都沒有,就一個<% out.println(session.getId());%>語句。 其實jsp中預設情況會有:<%@page session="true"%>,若你jsp中顯示改成:<%@page session="false"%>,那麼光禿禿的jsp中session就會null啦。 這下是否有一種更被欺騙的趕腳啊。其實人家確實為咱們好。
我們瞭解了session何時建立的了,那session何時銷毀的?就剛才acegi架構測試demo,關閉瀏覽器後,session為null,導致重新驗證,進入登陸頁面。那意思是說關閉瀏覽器,session就銷毀了? 既然session建立是程式來決定的,其實session銷毀,也是程式session.invalidate()來決定的。 那關閉瀏覽器,session變為null,是因為調用session.invalidate()原因嗎?這個不能顛倒順序。若關閉瀏覽器調用session.invalidate()則session變為null。而反過來則不通。為啥大部分人會感覺關閉瀏覽器,session為null,關鍵acegidemo中的session也為null呢?? 那就得瞭解session的原理了。
當瀏覽器訪問伺服器時,伺服器首先判斷用戶端請求中是否包含session的標識,若存在,說明伺服器已經給用戶端開闢一個session空間,然後根據此標識尋找具體的session;若不存在,則伺服器給用戶端建立一個session,然後把sessionId發給瀏覽器。 其實session時利用cookie來儲存sessionid,只不過在cookie中不是sessionid,而是jsessionid。只不過jsessionid就是sessionid的值。 這樣的話,cookie時存在瀏覽器生命週期,當瀏覽器關閉後,cookie就沒有了,導致cookie中的jsessionid也就沒有了。因此也無法找到伺服器中的session了,不過session在伺服器中還存在,只不過用戶端再也無法找到而已。 所以說呢,瀏覽器關閉,看似session銷毀,是因為大部分session是基於cookie存放sessionid原理實現的.但是真正的session對象在server中沒有被銷毀,不銷毀,一直占記憶體?
正式由於瀏覽器關閉,session不能真正銷毀,所以伺服器端有一個session時間的機制.當服務端server檢測到某一個session距它上次活躍期超過了規定的時間,那麼伺服器端就會調用session.invalidate()來銷毀.tomcat預設配置時間是30分鐘【tomcat6.0.37】當然這個時間可以自己修改,直接在自己項目中web.xml中進行配置即可。 所以session銷毀的情況如下:一是調用session.invalidate();二是session回話到期;三是server停止。
那若用戶端禁用了cookie呢? 這就用到另外一個技術—URL重寫。URL重寫是在url地址後面加上jsessionid,有兩種展示方式:一種是http://localhost:8080/項目名,jsessionid=***另一種是http://localhost:8080/項目名?jsessionid=*** 那具體如何?呢?這就用到java提供的api了。respone.encodeURL("地址")和response.encodeRedirectURL其中後者主要這麼使用:response.sendRedirect(response.encodeRedirectURL)重新導向應用。這兩個方法可以判斷,若用戶端禁止cookie,然後就會在url地址後面添加jsessionid;若用戶端支援cookie,則就是原來的url地址。
對於session瞭解後,下篇部落格講到系統常用登出功能時就會很簡單了。大家對這塊可以嘗試自己測試下,有啥發現或見解,及時溝通交流。