AnonymousProcessingFilter 為未認證請求建立匿名 Authentication,使「公開資源」也能納入統一權限決策流程,避免在配置檔硬編碼排除 URL。
Authentication 物件,FilterSecurityInterceptor 統一決策。AccessDecisionVoter 配置,無需修改 Filter 鏈。SecurityContextHolder.getContext().getAuthentication() 取得 Principal,無需判斷 null。AnonymousProcessingFilter:產生 AnonymousAuthenticationToken 放入 SecurityContext。AnonymousAuthenticationToken:實作 Authentication,攜帶 ROLE_ANONYMOUS 權限。AnonymousAuthenticationProvider:驗證 Token,提供「自己人」投票通過。<bean id="anonymousProcessingFilter"
class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
<property name="key" value="anonymous"/>
<property name="userAttribute" value="anonymous,ROLE_ANONYMOUS"/>
</bean>
<bean id="anonymousAuthenticationProvider"
class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
<property name="key" value="anonymous"/> <-- 必須與 Filter key 一致 -->
</bean>
<!-- 註冊 Provider -->
<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list>
<ref bean="daoAuthenticationProvider"/>
<ref bean="rememberMeAuthenticationProvider"/>
<ref bean="anonymousAuthenticationProvider"/>
</list>
</property>
</bean>
/**=httpSessionContextIntegrationFilter,
logoutFilter,
authenticationProcessingFilter,
rememberMeProcessingFilter,
anonymousProcessingFilter, <-- 處理未認證請求
exceptionTranslationFilter,
filterInvocationInterceptor
文件明確指出:「The key is shared between the filter and authentication provider, so that tokens created by the former are accepted by the latter.」若 key 不同,Provider 會拒絕 Token,導致匿名請求被視為未認證而拋出 AccessDeniedException。
ExceptionTranslationFilter 利用 AuthenticationTrustResolver.isAnonymous() 判斷:若匿名用戶存取受保護資源,導向登入頁而非直接 403,給予登入機會。