《Spring Security3》第三章第三部分翻譯上(Remember me功能實現)

Remember me

對於經常訪問站點的用戶有一個便利的功能就是remember me。這個功能允許一個再次訪問的用戶能夠被記住,它通過在用戶的瀏覽器上存儲一個加密的cookie來實現的。如果Spring Security能夠識別出用戶提供的remember me cookie,用戶將不必填寫用戶名和密碼,而是直接登錄進入系統。

 

與到目前爲止我們介紹的其它功能不同,remember me功能並不是在使用security命名空間方式的配置中自動添加的。讓我們嘗試這個功能並查看它是怎樣影響登錄流程的。

實現remember me選項

完成這個練習後,將會爲用戶訪問pet store應用提供一個簡單的記憶功能。

 

修改dogstore-security.xml配置文件,添加<remember-me>聲明。設置key屬性爲jbcpPetStore:

 

Xml代碼  收藏代碼
  1. <http auto-config="true" use-expressions="true" access-decision-  
  2. manager-ref="affirmativeBased">  
  3. …  
  4.     <remember-me key="jbcpPetStore"/>  
  5.     <logout invalidate-session="true" logout-success-url="/" logout-url="/logout"/>  
  6. </http>  
 

 

如果我們現在嘗試使用應用,在流程上將不會看到有任何的變化。這是因爲還需要在登錄form上添加一個輸入域,以允許用戶選擇使用這個功能。編輯login.jsp文件,添加一個checkbox,代碼如下:

 

Html代碼  收藏代碼
  1. <input id="j_username" name="j_username" size="20" maxlength="50" type="text"/>  
  2. <br />  
  3. <input id="_spring_security_remember_me" name="_spring_security_  
  4. remember_me" type="checkbox" value="true"/>  
  5. <label for="_spring_security_remember_me">Remember Me?</label>  
  6. <br />  
  7. <label for="j_password">Password</label>:  
 

 

當我們再次登錄時,如果Remember Me被選中,一個Remember Me的cookie將會設置在用戶的瀏覽器中。

如果用戶關閉瀏覽器並重新打開訪問一個JBCP Pets站點上需要認證的頁面,他將不會再看到登錄頁了。請親自試一下——登錄並將Remember Me選項選中,收藏首頁,然後重啓瀏覽器並再次訪問首頁。你能發現你直接登錄成功並不再需要提供憑證。

 

一些高級的用戶在體驗本功能時也可以使用瀏覽器插件如Firecookie(http://www.

softwareishard.com/blog/firecookie/),來管理(移除)會話session。這將會在你開發或校驗這種類型功能時,節省你時間和提高效率。

Remember me是怎樣實現的

Remember me功能設置了一個cookie在用戶的瀏覽器上,它包含一個Base64編碼的字符串,包含以下內容:

l  用戶的名字;

l  過期的日期/時間;

l  一個MD5的散列值包括過期日期/時間、用戶名和密碼;

l  應用的key值,是在<remember-me>元素的key屬性中定義的。

這些內容將被組合成一個cookie的值存儲在瀏覽器中以備後用。

 

MD5是一種知名的加密哈希算法。加密哈希算法將輸入的數據進行壓縮並生成唯一的任意長度的文字,這叫做摘要。摘要能夠在以後使用,以校驗不明的輸入是否與生成hash的輸入內容完全一致,此時並不需要使用原來的輸入內容本身。下面的圖片展示了這個過程:


 

你可以看到,未知的輸入可以與存儲的MD5哈希進行校驗,並能夠得出未知的輸入與存儲的已知輸入是否匹配的結論。摘要和加密算法(encryption algorithms)的一個重要不同在於,它很難從反向工程從摘要值得到初始的數據。這是因爲摘要僅僅是原始內容的一個概述或指紋(fingerprint,),並不是全部的數據本身(它可能會很大)。

 

儘管對加密的數據不可能進行解碼,但是MD5對一個類型的國際卻很脆弱,包括挖掘算法本身的弱點以及彩虹表攻擊(rainbow table attacks)。彩虹表通常會包括數百萬輸入值計算出來的哈希值。這使得攻擊者能夠尋找彩虹表中的哈希值從而確定實際值(未經過hash的值)。我們將會在第四章:憑證安全存儲中講解密碼安全的時,介紹防範這種攻擊的一種方法。

 

關於remember me的cookie,我們能夠看到這個cookie的組成足夠複雜,所以對攻擊者來說很難造出一個仿冒的cookie。在第四章中,我們將會學習另一種技術來使得remember me功能更加安全,免受惡意攻擊。

 

Cookie的失效時間基於一個配置的過期時間段的長度。如果用戶在cookie失效之前重新訪問我們的站點,這個cookie將和應用設置的其它cookie一起提交到應用上。

 

如果存在remember me cookie,o.s.s.web.authentication.rememberme.RememberMeAuthenticationFilter過濾器將會檢查cookie的內容並通過檢查是否爲一個認證過的remember me cookie來認證用戶(查看本章後面的Remember me是否安全?章節,將會講述這樣做的原因),這個過濾器是通過<remember-me>配置指令添加到過濾器鏈中的。

 

下面的圖表闡述了校驗remember me cookie過程中涉及到的不同組件:


 

RememberMeAuthenticationFilter在過濾器鏈中,位於SecurityContextHolderAwareRequestFilter之後,而在AnonymousProcessingFilter之前。正如鏈中的其它過濾器那樣,RememberMeAuthenticationFilter也會檢查request,如果是其關注的,對應的操作將會被執行。

按圖中所述,過濾器負責檢查用戶的過濾器是否remember me cookie作爲它們請求的一部分。如果remember me被發現,它會是一個Base64的編碼,期望的MD5哈希值通過cookie中的用戶名和密碼進行計算獲得。(這裏感覺有些問題,因爲期望的MD5值應該是通過應用來進行獲取,而不是提供前臺過來的cookie計算出來的。?)如果cookie通過這一層的校驗,用戶就已經登錄成功了。

 

【你可能已經意識到如果用戶修改了用戶名或密碼,任何的remember me token都將失效。請確保給用戶提供適當的信息,如果允許它們修改賬號的那些信息。在第四章中,我們將會看到一個替代的remember me實現,它只依賴用戶名並不依賴密碼。】

 

我們看到RememberMeAuthenticationFilter依賴一個o.s.s.web.authentication.RememberMeServices的實現來校驗cookie。如果登錄請求的request包含一個名爲_spring_security_remember_me的form參數,相同的實現類也會於form登錄成功時使用。這個cookie用上面提到的信息進行編碼,以Base64編碼存儲在瀏覽器中,包含了時間戳和用戶密碼等信息形成的MD5哈希值。

 

需要記住的是,可以區分通過remember me認證的用戶和提供用戶名和密碼(或相當憑證)認證的用戶。我們將會在審查remember me功能的安全性的時,對其進行簡單的實驗。

Remember me與用戶的生命週期

RememberMeServices的實現在用戶的生命週期中(一個認證用戶session的生命週期)在好幾個地方被調用。爲了使你理解remember me功能,瞭解remember me service完成生命週期功能的時間點將會有所幫助:

行爲

應該做什麼?

登錄成功

實現類設置remember me cookie(如果設置了對應的form參數)

登錄失敗

如果存在的話,實現類應該刪掉這個cookie

用戶退出

如果存在的話,實現類應該刪掉這個cookie

 

知道RememberMeServices在何時以及怎樣與用戶的生命週期關聯對於創建自定義的認證處理至關重要,因爲我們需要保證任何的自定義認證處理對待RememberMeServices保持一致性,以保證這個功能的有效性和安全性。

Remember me配置指令

可以修改兩個常用的配置來改變remember me功能的默認行爲:

屬性

描述

Key

爲remember mecookie定義一個唯一的key值,以與我們的應用關聯

token-validity-seconds

定義時間的長度(以秒計)。Remember me的cookie將在將被視爲認證合法,並且也將用於設置cookie的過期時間。

通過對cookie哈希內容生成的講解你可以推斷出,Key屬性對與remember me功能的安全性很重要。要保證你選擇的key值是你的應用唯一使用的,並且足夠長以至於不能很容易的被猜出。

 

請記住本書的目的何在,我們讓key的值相對很簡單,但是如果你要使用remember me功能在你的應用中,建議key值包含應用的唯一名稱以及至少36位長度的隨機字符。密碼生成工具(在google中搜索“online password generator”)是一個好辦法來得到包含文字數字以及特殊字符組成的僞隨機混合內容,以作爲你的remember me key值。

 

還要記住的是應用處於不同的環境中(如開發、測試、產品級等),remember me cookie的值也要考慮這些情況。這能夠避免remember me cookie在測試階段被無意中的錯誤使用。

 

一個產品環境的應用中,示例的key值如下:

jbcpPets-rmkey-paLLwApsifs24THosE62scabWow78PEaCh99Jus

 

token-validity-seconds屬性被用來設置rememberme token被接受作爲自動登錄功能(即使要校驗的token不合法)的秒數。本屬性還會設置用戶瀏覽器中登錄cookie能夠被保存的最長時間。

 

【設置remember me的會話cookie:如果token-validity-seconds屬性被設置成-1,登錄cookie將被設置爲會話cookie,即在用戶關閉瀏覽器後不會被保存。Token的有效時間是一個不可配置的值爲2周(假設用戶不關閉瀏覽器)。不要將這個cookie與存儲用戶的session ID的cookie相混淆——它們是不同的事情卻有着類似的名字。】

 

關於remember me功能的高級自定義功能,還有幾個其它的配置指令。我們將會在接下來的練習中包含部分,另一部分在第六章:高級配置與擴展中包含,那時會介紹高級的授權技術。

發佈了25 篇原創文章 · 獲贊 2 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章