企業應用安全痛點:ECM 系統需控制文件系統/數據庫/目錄服務等異構數據源訪問。Acegi 提供聲明式、可配置、無侵入的安全框架,專為 Spring 設計但通用於所有 Java 應用。
| 組件類型 | 代表 | 職責 |
|---|---|---|
| Filter (過濾器) | AuthenticationProcessingFilter, FilterSecurityInterceptor | 最高級抽象,處理認證/授權/會話/登出等 HTTP 級關注點 |
| Manager (管理器) | ProviderManager, AccessDecisionManager | 協調多個 Provider/Voter,封裝決策邏輯 |
| Provider (提供者) | DaoAuthenticationProvider, LdapAuthenticationProvider | 對接具體用戶存儲(屬性文件/LDAP/數據庫),執行認證邏輯 |
| Handler (處理器) | SecurityContextLogoutHandler, RememberMeServices | 原子操作步驟(如使會話失效、刪除 Cookie),組合靈活 |
Acegi 組件間依賴複雜,通過 Spring IOC 容器管理:
<beans>
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>...URL-過濾器映射...</value>
</property>
</bean>
<bean id="authenticationProcessingFilter"
class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
<property name="authenticationManager" ref="authManager"/> <!-- 依賴管理器 -->
</bean>
<bean id="authManager" class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list><!-- Provider 列表 --></list>
</property>
</bean>
</beans>
<bean>:每個 Acegi 組件實例id:實例標識,供 ref 引用class:實現類<property name="..." ref="..."/>:引用其他 Bean 實例(依賴注入)<property name="..." value="..."/>:注入字面值SecurityContext(安全信息占位符)存入 SecurityContextHolder<bean id="authenticationProcessingFilter"
class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="filterProcessesUrl" value="/j_acegi_security_check"/> <!-- 登錄提交 URL -->
<property name="defaultTargetUrl" value="/protected/protected1.jsp"/> <!-- 登錄成功跳轉 -->
<property name="authenticationFailureUrl" value="/login.jsp?login_error=1"/> <!-- 失敗跳轉 -->
</bean>
/j_acegi_security_check POST 請求UsernamePasswordAuthenticationTokenAuthenticationManager 驗證 → 成功存入 SecurityContext → 重定向<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
<constructor-arg value="/logoutSuccess.jsp"/> <!-- 登出成功頁 -->
<constructor-arg>
<list><bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/></list>
</constructor-arg>
</bean>
/j_acegi_logout)SecurityContextLogoutHandler 使 HTTP Session 無效<bean id="exceptionTranslationFilter"
class="org.acegisecurity.ui.ExceptionTranslationFilter">
<property name="authenticationEntryPoint">
<bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl" value="/login.jsp"/>
</bean>
</property>
<property name="accessDeniedHandler">
<bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
<property name="errorPage" value="/accessDenied.jsp"/>
</bean>
</property>
</bean>
AuthenticationException → 重定向到登錄頁AccessDeniedException → 渲染 403 拒絕頁<bean id="filterInvocationInterceptor"
class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="objectDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/protected/**=ROLE_HEAD_OF_ENGINEERING
/**=IS_AUTHENTICATED_ANONYMOUSLY
</value>
</property>
</bean>
objectDefinitionSource:Ant 風格 URL 模式 → 角色映射AccessDecisionManager 決策(見下文)FilterChainProxy(代理過濾器)chain.doFilter()、直接返回(如 APF 處理登錄)、拋出異常(由 ETF 捕獲)index.jsp:歡迎頁,含受保護資源鏈接、登錄鏈接protected1.jsp、protected2.jsp:受保護資源(需 ROLE_HEAD_OF_ENGINEERING)login.jsp:登錄表單(提交到 /j_acegi_security_check)accessDenied.jsp:403 頁面<web-app>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/acegi-config.xml</param-value>
</context-param>
<filter>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
<init-param>
<param-name>targetClass</param-name>
<param-value>org.acegisecurity.util.FilterChainProxy</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
acegi-security-sample-tutorial.war 取出 WEB-INF/lib 所有 JARacegisample.war 複製到 Tomcat webappsWEB-INF/libhttps://localhost:8080/acegisample/alice/123(角色 ROLE_HEAD_OF_ENGINEERING) → 登錄成功 → 重定向回目標頁protected1.jsp本文建立了 Acegi 架構模型 → 組件依賴 → 過濾器鏈 → XML 配置 → 示例驗證 完整認知鏈。核心洞見:
後續系列將深入:LDAP 目錄服務整合(第 2 部分)、方法級安全(第 3 部分)、JSF 整合(第 4-5 部分)。