首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Acegi Security 系列第 3 部分:基於方法的安全性實現 Java 對象訪問控制

     編輯:Java 相關知識

從 URL 安全到方法安全:細粒度授權的必要性

URL 安全(第 1 部分)只能控制「能否訪問某頁面」。業務場景常需控制「能否調用某業務方法」:

  • 工作流引擎:不同角色執行不同節點(採集/檢測/簽署報告)
  • B2B 集成:合作夥伴調用特定服務(如旅行社以特定費率訂房)

Acegi 方法安全攔截器(Method Security Interceptor)提供方法級授權,配合 Spring AOP 代理實現透明保護。

Spring IOC 創建與代理 Java 對象

標準 Bean 創建流程

  1. Servlet 容器創建 ServletContext
  2. ContextLoaderListener 啟動 Spring XMLWebApplicationContext
  3. 解析 XML 配置,實例化所有 Bean(publicCatalog、privateCatalog 等)
  4. Bean 實例存入內部數組,供 getBean() 獲取

Bean 代理機制:保護私有 Bean

<!-- 代理創建器配置 -->
<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>

內部代理創建過程

  1. BeanNameAutoProxyCreator(實現 BeanPostProcessor)攔截 Bean 初始化
  2. 讀取 beanNames 列表,加載對應類
  3. 實例化 interceptorNames 指定的攔截器
  4. 創建 Cglib2AopProxy(實現 AOPProxy + MethodInterceptor)
  5. 生成動態代理對象替換原始 Bean 存入容器

客戶端訪問代理對象


// 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(); // 調用被代理攔截

Acegi 方法安全攔截器配置

<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:方法-角色映射,格式 全限定類名.方法名=角色

進階特性:Run-As 機制(臨時提權)

場景:安全 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>

運行時流程

  1. 用戶調用 getData(),攔截器驗證 ROLE_HEAD_OF_ENGINEERING
  2. 授權通過,檢測到 RUN_AS_MANAGER 角色前綴
  3. RunAsManagerImpl 激活,生成臨時 RUN_AS_MANAGER 權限
  4. 安全 Bean 執行過程中持有該臨時權限,可調用遠程服務
  5. 方法返回,臨時權限自動銷毀

示例應用驗證

  • AcegiMethodSecurity:基礎方法安全演示
  • EnhancedAcegiMethodSecurity:Run-As 機制演示

部署依賴

  1. LDAP 用戶數據(alice/bob/specialUser,參考第 2 部分)
  2. WAR 部署到 Tomcat webapps
  3. 複製 Acegi JAR 到 WEB-INF/lib
  4. 關鍵:複製 cglib-full-2.0.2.jar 到 WEB-INF/lib(CGLIB 代理必需)
  5. 啟動 Tomcat,訪問 https://localhost:8080/acegiMethodSecurity

測試驗證矩陣

用戶角色訪問 publicCatalog訪問 privateCatalog
aliceROLE_HEAD_OF_ENGINEERING✅ 成功✅ 成功(含私有數據)
specialUserROLE_HEAD_OF_ENGINEERING✅ 成功✅ 成功
bob無相關角色✅ 成功❌ 僅顯示公有數據

總結

本文完整展示了 Spring AOP 代理 + Acegi 方法安全攔截器 實現透明方法級授權的全鏈路:XML 配置 → 容器啟動創建代理 → 客戶端獲取代理 → 方法調用攔截 → 身份驗證/授權決策 → Run-As 臨時提權。這種聲明式模式讓業務代碼零安全依賴,安全策略集中在 XML 配置,是企業級應用細粒度授權的標準實踐。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved