經過一段時間的總結, 對Acegi的初步研究終於到了最後一個常見Filter了,即 rememberMeProcessingFilter . 顧名思義, rememberMeProcessingFilter就是想讓系統記下來當前登錄的用戶,不至於以後每次進系統時都要輸入用戶名密碼.這方面的例子相信大家已有體會,我也就不必在些贅述.
先簡要地說下原理. 假定用戶登錄時選擇了"讓系統記住我"後, request進入Acegi後, Acegi會把用戶名密碼和相關信息記下來,再以Cookie的形式通過Response發往浏覽器並存儲到浏覽器中,這樣下次用戶訪問系統時,系統會通過 rememberMeProcessingFilter從浏覽器傳來的Cookie中取出先前的登錄信息,做判斷後以一個 remember-me authentication的形式放到SecurityContext中,接下來,跟anonymousProcessingFilter類似,在 filterInvocationInterceptor檢查時,也由自己人投一票通過,於是就通過Acegi的盤問去做想做的操作. 這裡我們也看來,其實是不系統記下來了,而浏覽器以cookie的形式住了, Acegi只是圍繞著cookie在合適的時候做些合適的事.
有了這個對原理的簡單介紹,下面我們來看怎麼配置,以及這個原理又是由誰來具體實現的.
按上面原理的順序,以便用戶選擇是否讓"系統記住我", 往login.jsp裡加一個如下所示的一個input標簽.
<input type="checkbox" name = "rememberMe " />讓系統記住我
注意下這裡的 rememberMe,後面要用到的.
再往以前定義好的 authenticationProcessingFilter裡了加個屬性,rememberMeServices,如下所示:
<!--新加 start ,這個很重要,沒有它系統就"記不住你"了-->
<property name="rememberMeServices" ref="rememberMeServices"/>
<!--新加 end -->
通過個rememberMeServices, Acegi在得知用戶登錄成功後會把用戶名和密碼生成一個Cookie放入到response裡,(這個cookie裡有Acegi做的暗號,這樣 acegi以後才能識得), 讓它捎給浏覽器保存下來,以備後用. 這步對應著上面用戶第一次輸入用戶名密碼成功登錄的情景.
接下就是用戶不用登錄訪問系統了. 這要配置主角 rememberMeProcessingFilter了, 其實現類為RememberMeProcessingFilter,這個類兩個屬性authenticationManager和rememberMeServices需要配置.如下:
<!--新加 start-->
<bean id="rememberMeProcessingFilter" class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="rememberMeServices" ref="rememberMeServices"/>
</bean>
<!--新加 end -->
加了這個filter後, request經過這裡時,acegi通過rememberMeServices(對,又是它,上面在登錄成功時就用到了),把相應的cookie取出來,再生成一個remember-me_authentication放到securityContext中, authenticationManager在此的目的是為了檢驗rememberMeServices從cookies裡取出的remember- me_authentication是否有效.
先看rememberMeServices定義,其定義如下:
<!--新加 start-->
<bean id="rememberMeServices" class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService" ref="userDetailsService"/>
<property name="key" value="23_*!cdU='612./e;NrI"/>
<property name="parameter" value="rememberMe"/>
</bean>
<!--下面, 這個rememberMeAuthenticationProvider加到了已經定義好的authenticationManager bean的providers裡-->
<bean id="rememberMeAuthenticationProvider" class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
<property name="key" value="23_*!cdU='612./e;NrI"/>
</bean>
<!--新加 end -->
三個屬性,它們分別是用來干啥的? 實際上, 在上面rememberMeProcessingFilter裡,rememberMeServices通過userDetailsService對 cookie裡取出的userName進行了檢驗,一是看現在還有沒這個user, 二是看密碼是否已改.這也正是下面rememberMeServices裡為什麼要有userDetailsService的原因.那key是干啥的呢? 在上面authenticationManager驗證remember-me_authentication是否有效時與provider裡的key來做比較的,正是由於這個原因,下面兩處的key值得一模一樣. 那個parameter呢? 再回過頭看第一步, 那裡我們加了一個name為rememberMe的input標簽,Acegi內部也正是通過個標簽來決定是否要做進一步的裝cookie處理.
至此,結合背後的實現原理, rememberMeProcessingFilter的配置完成完畢,在filterInvocationInterceptor檢查當前角色是否有足夠的操作時,就會在 remember-me_authentication自己人rememberMeAuthenticationProvider的"保護"下順利通過了.
這裡為了說明配置都起什麼作用,這些配置很散,大家可從附件中看到這些配置都加到什麼位置了,它們又是怎麼跟原的filter及其支撐類配合的.