前四部分已涵蓋 URL 安全、LDAP 策略、方法級安全、JSF 頁面保護。本文聚焦JSF 應用中 JavaBean(托管 Bean 與 IOC Bean)的安全訪問控制,實現零安全代碼的聲明式 Bean 保護。
創建一個 JSF 托管 Bean 作為「外殼」,其屬性映射到受 Acegi 保護的 IOC Bean:
<faces-config>
<managed-bean>
<managed-bean-name>catalog</managed-bean-name>
<managed-bean-class>sample.Catalog</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<!-- 公共數據映射到不受保護的 IOC Bean -->
<managed-property>
<property-name>publicData</property-name>
<value>#{publicCatalog.data}</value>
</managed-property>
<!-- 私有數據映射到受保護的 IOC Bean -->
<managed-property>
<property-name>privateData</property-name>
<value>#{privateCatalog.data}</value>
</managed-property>
</managed-bean>
<!-- 關鍵:配置 Spring 變量解析器,支援解析 IOC Bean -->
<application>
<variable-resolver>
org.springframework.web.jsf.DelegatingVariableResolver
</variable-resolver>
</application>
</faces-config>
public class Catalog {
private String publicData;
private String privateData;
// 標準 getter/setter,JSF 自動調用
public void setPublicData(String publicData) { this.publicData = publicData; }
public String getPublicData() { return publicData; }
public void setPrivateData(String privateData) { this.privateData = privateData; }
public String getPrivateData() { return privateData; }
}
<bean id="publicCatalog" class="sample.PublicCatalog" />
<bean id="privateCatalog" class="sample.PrivateCatalog" />
<!-- privateCatalog 代理配置,攔截器執行安全檢查 -->
<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>
無需托管 Bean 包裝,JSF 表達式直接引用 IOC Bean:
<h:outputText value="#{publicCatalog.data}" />
<h:outputText value="#{privateCatalog.data}" />
前提:同樣需配置 DelegatingVariableResolver,Acegi 代理攔截器自動執行授權檢查。
catalog 托管 Beanfaces-config.xml,實例化 Catalog,發現屬性引用 publicCatalog/privateCatalogDelegatingVariableResolver 解析 IOC Bean(委派 Spring 容器)getData() 獲取數據catalog.setPrivateData() 注入流程簡化:第 3-4 步直接解析頁面中的 #{privateCatalog.data},後續授權邏輯相同。
web.xml 整合 Acegi Filter(參考第 4 部分)faces-config.xml 中聲明 DelegatingVariableResolver核心優勢:業務邏輯零安全代碼,安全策略集中在 XML 配置,職責分離徹底。
源碼包含兩個示例:
JSFAcegiSampleWithSecureManagedBeans:策略一演示JSFAcegiSampleWithIOCBeans:策略二演示webappsjsf-1_1_01.zip) 解壓,所有 JAR 複製到 WEB-INF/libcglib-full-2.0.2.jar 複製到 WEB-INF/lib(代理所需)https://localhost:8080/應用名Acegi 在 JSF 中的 Bean 保護體現了聲明式安全精髓:通過 DelegatingVariableResolver 打通 JSF 與 Spring 容器,利用 Spring AOP 代理攔截 Bean 方法調用,配合方法安全攔截器實現細粒度授權。兩種模式各有適用場景——托管 Bean 模式適合漸進式遷移現有 JSF 應用,直接 IOC Bean 模式適合新架構設計。配合前文的 URL/頁面保護,構建了完整的 JSF 應用安全體系。