Spring Security教程之session管理

 

1.1     檢測session超時

1.2     concurrency-control

1.3     session 固定攻擊保護

 

       Spring Security通過http元素下的子元素session-management提供了對Http Session管理的支持。

 

1.1     檢測session超時

       Spring Security可以在用戶使用已經超時的sessionId進行請求時將用戶引導到指定的頁面。這個可以通過如下配置來實現。

   <security:http>

      ...

      <!-- session管理,invalid-session-url指定使用已經超時的sessionId進行請求需要重定向的頁面 -->

      <security:session-management invalid-session-url="/session_timeout.jsp"/>

      ...

   </security:http>

 

       需要注意的是session超時的重定向頁面應當是不需要認證的,否則再重定向到session超時頁面時會直接轉到用戶登錄頁面。此外如果你使用這種方式來檢測session超時,當你退出了登錄,然後在沒有關閉瀏覽器的情況下又重新進行了登錄,Spring Security可能會錯誤的報告session已經超時。這是因爲即使你已經退出登錄了,但當你設置session無效時,對應保存session信息的cookie並沒有被清除,等下次請求時還是會使用之前的sessionId進行請求。解決辦法是顯示的定義用戶在退出登錄時刪除對應的保存session信息的cookie。

   <security:http>

      ...

      <!-- 退出登錄時刪除session對應的cookie -->

      <security:logout delete-cookies="JSESSIONID"/>

      ...

   </security:http>

       此外,Spring Security並不保證這對所有的Servlet容器都有效,到底在你的容器上有沒有效,需要你自己進行實驗。

 

1.2     concurrency-control

       通常情況下,在你的應用中你可能只希望同一用戶在同時登錄多次時只能有一個是成功登入你的系統的,通常對應的行爲是後一次登錄將使前一次登錄失效,或者直接限制後一次登錄。Spring Security的session-management爲我們提供了這種限制。

       首先需要我們在web.xml中定義如下監聽器。

   <listener>

   <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>

   </listener>

 

       在session-management元素下有一個concurrency-control元素是用來限制同一用戶在應用中同時允許存在的已經通過認證的session數量。這個值默認是1,可以通過concurrency-control元素的max-sessions屬性來指定。

   <security:http auto-config="true">

      ...

      <security:session-management>

         <security:concurrency-control max-sessions="1"/>

      </security:session-management>

      ...

   </security:http>

 

       當同一用戶同時存在的已經通過認證的session數量超過了max-sessions所指定的值時,Spring Security的默認策略是將先前的設爲無效。如果要限制用戶再次登錄可以設置concurrency-control的error-if-maximum-exceeded的值爲true。

 

   <security:http auto-config="true">

      ...

      <security:session-management>

         <security:concurrency-control max-sessions="1" error-if-maximum-exceeded="true"/>

      </security:session-management>

      ...

   </security:http>

 

       設置error-if-maximum-exceeded爲true後如果你之前已經登錄了,然後想再次登錄,那麼系統將會拒絕你的登錄,同時將重定向到由form-login指定的authentication-failure-url。如果你的再次登錄是通過Remember-Me來完成的,那麼將不會轉到authentication-failure-url,而是返回未授權的錯誤碼401給客戶端,如果你還是想重定向一個指定的頁面,那麼你可以通過session-management的session-authentication-error-url屬性來指定,同時需要指定該url爲不受Spring Security管理,即通過http元素設置其secure=”none”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
< security:http  security="none" pattern="/none/**" />
 
< security:http >
 
    < security:form-login />
 
    < security:logout />
 
    < security:intercept-url  pattern="/**" access="ROLE_USER"/>
 
    <!-- session-authentication-error-url必須是不受Spring Security管理的 -->
 
    < security:session-management  session-authentication-error-url="/none/session_authentication_error.jsp">
 
       < security:concurrency-control  max-sessions="1" error-if-maximum-exceeded="true"/>
 
    </ security:session-management >
 
    < security:remember-me  data-source-ref="dataSource"/>
 
</ security:http >

  

       在上述配置中我們配置了session-authentication-error-url爲“/none/session_authentication_error.jsp”,同時我們通過<security:http security="none" pattern="/none/**" />指定了以“/none”開始的所有URL都不受Spring Security控制,這樣當用戶進行登錄以後,再次通過Remember-Me進行自動登錄時就會重定向到“/none/session_authentication_error.jsp”了。

       在上述配置中爲什麼我們需要通過<security:http security="none" pattern="/none/**" />指定我們的session-authentication-error-url不受Spring Security控制呢?把它換成<security:intercept-url pattern="/none/**"access="IS_AUTHENTICATED_ANONYMOUSLY"/>不行嗎?這就涉及到之前所介紹的它們兩者之間的區別了。前者表示不使用任何Spring Security過濾器,自然也就不需要通過Spring Security的認證了,而後者是會被Spring Security的FilterChain進行過濾的,只是其對應的URL可以匿名訪問,即不需要登錄就可訪問。使用後者時,REMEMBER_ME_FILTER檢測到用戶沒有登錄,同時其又提供了Remember-Me的相關信息,這將使得REMEMBER_ME_FILTER進行自動登錄,那麼在自動登錄時由於我們限制了同一用戶同一時間只能登錄一次,後來者將被拒絕登錄,這個時候將重定向到session-authentication-error-url,重定向訪問session-authentication-error-url時,經過REMEMBER_ME_FILTER時又會自動登錄,這樣就形成了一個死循環。所以session-authentication-error-url應當使用<security:http security="none" pattern="/none/**" />設置爲不受Spring Security控制,而不是使用<security:intercept-url pattern="/none/**"access="IS_AUTHENTICATED_ANONYMOUSLY"/>。

 

       此外,可以通過expired-url屬性指定當用戶嘗試使用一個由於其再次登錄導致session超時的session時所要跳轉的頁面。同時需要注意設置該URL爲不需要進行認證。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
< security:http  auto-config="true">
 
    < security:form-login />
 
    < security:logout />
 
    < security:intercept-url  pattern="/expired.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
 
    < security:intercept-url  pattern="/**" access="ROLE_USER"/>
 
    < security:session-management >
 
       < security:concurrency-control  max-sessions="1" expired-url="/expired.jsp" />
 
    </ security:session-management >
 
</ security:http >

  

1.3     session 固定攻擊保護

       session固定是指服務器在給客戶端創建session後,在該session過期之前,它們都將通過該session進行通信。session 固定攻擊是指惡意攻擊者先通過訪問應用來創建一個session,然後再讓其他用戶使用相同的session進行登錄(比如通過發送一個包含該sessionId參數的鏈接),待其他用戶成功登錄後,攻擊者利用原來的sessionId訪問系統將和原用戶獲得同樣的權限。Spring Security默認是對session固定攻擊採取了保護措施的,它會在用戶登錄的時候重新爲其生成一個新的session。如果你的應用不需要這種保護或者該保護措施與你的某些需求相沖突,你可以通過session-management的session-fixation-protection屬性來改變其保護策略。該屬性的可選值有如下三個。

l  migrateSession:這是默認值。其表示在用戶登錄後將新建一個session,同時將原session中的attribute都copy到新的session中。

l  none:表示繼續使用原來的session。

l  newSession:表示重新創建一個新的session,但是不copy原session擁有的attribute。

 

(注:本文是基於Spring Security3.1.6所寫)

 

Java設置session超時(失效)的時間

在一般系統登錄後,都會設置一個當前session失效的時間,以確保在用戶長時間不與服務器交互,自動退出登錄,銷燬session
具體設置的方法有三種:
1.在web容器中設置(以tomcat爲例)
在tomcat-7.0\conf\web.xml中設置,以下是tomcat7.0中默認配置:

1
2
3
<session-config>
<session-timeout> 30 </session-timeout>
</session-config>

tomcat默認session超時時間爲30分鐘,可以根據需要修改,負數或0爲不限制session失效時間

這裏要注意這個session設置的時間是根據服務器來計算的,而不是客戶端。所以如果在調試程序,應該是修改服務器端時間來測試,而不是客戶端

2.在工程的web.xml中設置
<!--時間單位爲分鐘-->

1
2
3
<session-config>
<session-timeout> 15 </session-timeout>
</session-config>

 這裏的15是指15分鐘失效

3.通過java代碼設置
session.setMaxInactiveInterval(30*60);//以秒爲單位,即在沒有活動30分鐘後,session將失效

三種方式優先等級:1 < 2 < 3

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章