在這篇博客中, 我們接著看另一個Filter, anonymousProcessingFilter.
1, 為什麼要配置這個? 它能給我們帶來什麼好處?
為了解決這個問題, 看了下Acegi的文檔 , 但說實在的, 由於文檔中用是"convenient"和"nice"這樣的詞來描述這個filter的好處, 我現在還感覺不到. 這裡把我現在給想到的理由總結一下.
為了理論上的完美. 用了這個fitler,就可以對系統中所有 的鏈接加權限管理了, 像login, logout和home這樣的"非常規訪問",也可以加一個默認的匿名訪問Authentication. 像這樣的"非常規訪問"是可以在acegi的配置文件中寫死的, 當然寫死有寫死的壞處. 由這個壞處,我們看下一個理由.
為了某個鏈接的動態設定. 可能會有這樣的情況: 一個鏈接的訪問權限剛開始時是有專門的訪問權限的, 但由於業務邏輯的變更, 這個鏈接的權限改為匿名的了,或者說原來的匿名訪問要改為具有一定權限訪問了. 這時, 為了在不重啟服務器情況下設定權限, 就預先配置一個anonymousProcessingFilter, 讓它來處理那些默認的情況.
別的我現在猜不出來了, 希望大家能補上.
2, 怎麼配置?
雖說不是很理解, 但還是要配置的. 那怎麼配置呢? 我們先看這個filter所涉及到的三個類: AnonymousProcessingFilter, AnonymousAuthenticationToken,AnonymousAuthenticationProvider. 第一個類沒什麼說的, 它就是這個filter的實現類, 沒有它辦不成事. 第二個類實際上是一個Authentication, acegi通過它來加一個默認的匿名Authentication. 第三個類實現了AuthenticationProvider接口, 有了一個匿名的Authentication, 相應地得給一個Provider, 以便在filterInvocationInterceptor檢查權限時,被"卡"住. 呵呵, 看到這, 我覺得挺好笑的了: 本身是一個虛頭八腦的東西, 為了"掩蓋"它, 讓在真實世界裡行的通, 還得再給弄兩個一樣虛頭八腦的東東陪著.
有了一種大致的了解後, 我們看配置:
2.1 配置anonymousProcessingFilter bean.
Xml代碼
<bean id="anonymousProcessingFilter" class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
<property name="key" value="anonymous"/>
<property name="userAttribute" value="anonymous,ROLE_ANONYMOUS"/>
</bean>
這兩個Property, 都是在生成AnonymousAuthenticationToken時用到. userAttribute中的anonymous對應著Authentication(AnonymousAuthenticationToken也是一種Authentication,雖說有些虛)的principal, ROLE_ANONYMOUS對應著Authentication中的GrantedAuthority[], key的anonymous生成AnonymousAuthenticationToken中的keyHash(通過String類的hashCode方法獲得).
<property name="key" value="anonymous"/>與下面配置的anonymousAuthenticationProvider中的相應行對應.
2.2 配置anonymousAuthenticationProvider
Xml代碼
<bean id="anonymousAuthenticationProvider" class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
<property name="key" value="anonymous"/>
</bean>
配置好後, 把這個anonymousAuthenticationProvider配置到ProviderManager類下providers, 這樣filterInvocationInterceptor碰到前面配置的匿名Authentication時, 才能在AccessDecisionVoter"投票"時, 由AnonymousAuthentication的自己人anonymousAuthenticationProvider"保護"著"逃過 "check.
一個猜想: 這裡的key跟上面anonymousProcessingFilter的key得一致, 不然在"投票"時, 沒這個"暗號""自己人"也互相不認識了.想驗證這個猜想, 看了下文檔,發現這樣的話: "The key is shared between the filter and authentication provider, so that tokens created by the former are accepted by the latter".自己的猜想不錯!
有了上面的配置分析, 運行機理稍看下源碼就可以明白了, 這裡也就不用再另寫了.
-----------------------------------------
看文檔時發現這麼段話, 覺得很有必要記下來,雖說現在還沒有切身體驗:Rounding out the anonymous authentication discussion is the AuthenticationTrustResolver interface, with its corresponding AuthenticationTrustResolverImpl implementation. This interface provides an isAnonymous(Authentication) method, which allows interested classes to take into account this special type of authentication status. The ExceptionTranslationFilter uses this interface in processing AccessDeniedExceptions. If an AccessDeniedException is thrown, and the authentication is of an anonymous type, instead of throwing a 403 (forbidden) response, the filter will instead commence the AuthenticationEntryPoint so the principal can authenticate properly. This is a necessary distinction, otherwise principals would always be deemed "authenticated" and never be given an opportunity to login via form, basic, digest or some other normal authentication mechanism.