Acegi 核心實現圍繞「七劍」展開,本文結合靜態 Bean 圖與動態序列圖,完整追蹤請求如何穿越 Filter 鏈並完成認證授權。
Authentication。<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/login.jsp=#NONE#
/**=httpSessionContextIntegrationFilter,
authenticationProcessingFilter,
exceptionTranslationFilter,
filterInvocationInterceptor
</value>
</property>
</bean>
SecurityContext → 存入 SecurityContextHolder → chain.doFilter()。requiresAuthentication() 檢測是否為登入請求 (j_acegi_security_check)。UsernamePasswordAuthenticationToken。authenticationManager.authenticate() 驗證。SecurityContextHolder.getContext().setAuthentication()、重導向 defaultTargetUrl。AuthenticationException → 重導向 authenticationFailureUrl。SecurityContext 取得 Authentication。AccessDecisionManager 決策:遍歷 ConfigAttributeDefinition 所需角色,與 Authentication.getAuthorities() 比對。AccessDeniedException → ExceptionTranslationFilter 處理。// FilterSecurityInterceptor 內部
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
GrantedAuthority[] userAuths = auth.getAuthorities(); // 劍4
UserDetails user = userDetailsService.loadUserByUsername(auth.getName()); // 劍6,7
GrantedAuthority[] requiredAuths = configAttributes.getAuthorities(); // 配置需求
// AccessDecisionVoter 比對 userAuths 與 requiredAuths
FilterChainProxy.doFilter() → VirtualFilterChain.doFilter() 遞迴調用下一 Filter。FilterChain 參數,決定是否 chain.doFilter() 放行或自行回應。AuthenticationManager (ProviderManager) 委派給 AuthenticationProvider 驗證,支援多 Provider 鏈。「七劍」是 Acegi 不變的核心,Filter 鏈與配置是針對不同場景的組裝方式。理解七劍職責與協作,即可靈活擴充、排錯。