URL 安全(第 1 部分)只能控制「能否訪問某頁面」。業務場景常需控制「能否調用某業務方法」:
Acegi 方法安全攔截器(Method Security Interceptor)提供方法級授權,配合 Spring AOP 代理實現透明保護。
ServletContextContextLoaderListener 啟動 Spring XMLWebApplicationContextpublicCatalog、privateCatalog 等)getBean() 獲取<!-- 代理創建器配置 -->
<bean id="proxyCreator"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list><value>privateCatalog</value></list>
</property>
<property name="interceptorNames">
<list><value>privateCatalogSecurityInterceptor</value></list>
</property>
</bean>
BeanNameAutoProxyCreator(實現 BeanPostProcessor)攔截 Bean 初始化beanNames 列表,加載對應類interceptorNames 指定的攔截器Cglib2AopProxy(實現 AOPProxy + MethodInterceptor)
// 1. 獲取應用上下文
XMLWebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(
getServletConfig().getServletContext());
// 2. 獲取公共 Bean(無代理,直接返回實例)
PublicCatalog publicCatalog = (PublicCatalog) ctx.getBean("publicCatalog");
String publicData = publicCatalog.getData(); // 直接調用
// 3. 獲取私有 Bean(返回代理對象)
PrivateCatalog privateCatalog = (PrivateCatalog) ctx.getBean("privateCatalog");
String privateData = privateCatalog.getData(); // 調用被代理攔截
<bean id="privateCatalogSecurityInterceptor"
class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
<property name="authenticationManager">
<ref bean="authenticationManager"/>
</property>
<property name="accessDecisionManager">
<ref bean="accessDecisionManager"/>
</property>
<property name="objectDefinitionSource">
<value>
sample.PrivateCatalog.getData=ROLE_HEAD_OF_ENGINEERING
</value>
</property>
</bean>
authenticationManager:身份驗證(第 1 部分配置)accessDecisionManager:授權決策(第 2 部分投票器機制)objectDefinitionSource:方法-角色映射,格式 全限定類名.方法名=角色場景:安全 Bean 內部需調用遠程服務(RMI/Web Service),遠程服務要求額外角色。
<bean id="privateCatalogSecurityInterceptor" ...>
<property name="runAsManager">
<bean id="runAsManager" class="org.acegisecurity.runas.RunAsManagerImpl">
<property name="key"><value>myKeyPass</value></property>
</bean>
</property>
<property name="objectDefinitionSource">
<value>
sample.PrivateCatalog.getData=ROLE_HEAD_OF_ENGINEERING,RUN_AS_MANAGER
</value>
</property>
</bean>
getData(),攔截器驗證 ROLE_HEAD_OF_ENGINEERINGRUN_AS_MANAGER 角色前綴RunAsManagerImpl 激活,生成臨時 RUN_AS_MANAGER 權限AcegiMethodSecurity:基礎方法安全演示EnhancedAcegiMethodSecurity:Run-As 機制演示webappsWEB-INF/libcglib-full-2.0.2.jar 到 WEB-INF/lib(CGLIB 代理必需)https://localhost:8080/acegiMethodSecurity| 用戶 | 角色 | 訪問 publicCatalog | 訪問 privateCatalog |
|---|---|---|---|
| alice | ROLE_HEAD_OF_ENGINEERING | ✅ 成功 | ✅ 成功(含私有數據) |
| specialUser | ROLE_HEAD_OF_ENGINEERING | ✅ 成功 | ✅ 成功 |
| bob | 無相關角色 | ✅ 成功 | ❌ 僅顯示公有數據 |
本文完整展示了 Spring AOP 代理 + Acegi 方法安全攔截器 實現透明方法級授權的全鏈路:XML 配置 → 容器啟動創建代理 → 客戶端獲取代理 → 方法調用攔截 → 身份驗證/授權決策 → Run-As 臨時提權。這種聲明式模式讓業務代碼零安全依賴,安全策略集中在 XML 配置,是企業級應用細粒度授權的標準實踐。