acegi,IBM的Acegi Security System(3)
2007 年 10 月 18 日
本文是 Acegi Security Systerm 介紹的最后一部分(共三部分),Bilal Siddiqui 將向您介紹如何保護(hù)對 Java 類實(shí)例的訪問,從而結(jié)束本系列文章。通過本文了解為何需要對 Java™ 類的訪問進(jìn)行保護(hù),Spring 如何創(chuàng)建和保護(hù)對 Java 類實(shí)例的訪問以及如何對 Acegi 進(jìn)行配置以實(shí)現(xiàn) Java 應(yīng)用程序的類安全性。
這期共分三部分的系列文章介紹了如何使用 Acegi 安全系統(tǒng)保護(hù) Java 企業(yè)應(yīng)用程序。系列文章的 第 1 部分 簡單介紹了 Acegi 并解釋如何使用其內(nèi)置的安全過濾器實(shí)現(xiàn)一個(gè)簡單的、基于 URL 的安全系統(tǒng)。第 2 部分 介紹了如何編寫訪問控制策略并將其保存到一個(gè) LDAP 目錄服務(wù)器,以及如何配置 Acegi 來與目錄服務(wù)器進(jìn)行交互,從而實(shí)現(xiàn)訪問控制策略。第 3 部分(也是本系列的最后一篇文章)將演示如何在企業(yè)應(yīng)用程序中使用 Acegi 保護(hù)對 Java 類實(shí)例的訪問。
首先我將介紹何時(shí)需要對 Java 類訪問進(jìn)行保護(hù),包括文中引用的兩個(gè)典型企業(yè)應(yīng)用程序場景。之后,我將解釋 Spring 的反轉(zhuǎn)控制(IOC)框架如何創(chuàng)建可從 JSP 或 servlet 訪問的 Java 類實(shí)例。我還將介紹有關(guān) bean 代理 的重要概念,Spring 正是使用它過濾對 Java 類的訪問。最后,我將介紹如何對 Acegi 的方法安全性攔截器進(jìn)行配置以控制對 Java 類的訪問。我將對 第 2 部分 中的示例程序進(jìn)行增強(qiáng),為實(shí)現(xiàn)安全的 Java 對象提供支持,從而結(jié)束本系列的最后一篇文章。
由于本文的討論構(gòu)建在本系列前兩部分的內(nèi)容之上,因此會(huì)經(jīng)常引用到 第 1 部分 和 第 2 部分 中的討論和示例。因此,在繼續(xù)閱讀本文之前,在其他瀏覽器窗口中打開前兩期文章將有助于理解本文內(nèi)容。
您可能還記得,我曾在本系列的開頭部分簡單介紹了 企業(yè)應(yīng)用程序安全性。在那次討論中我曾提到過一種場景,其中 URL 安全性并不能完全滿足這種場景的安全需求:
假設(shè)有這樣一個(gè) PDF 文檔,其中包含了某制造業(yè)公司生產(chǎn)的特定產(chǎn)品的數(shù)據(jù)。文檔的一部分包含了設(shè)計(jì)數(shù)據(jù),將由公司設(shè)計(jì)部分進(jìn)行編輯和更新。文檔另一部分包含生產(chǎn)經(jīng)理將使用到的生產(chǎn)數(shù)據(jù)。對于此類場景,需要實(shí)現(xiàn)更加細(xì)粒度的安全性,對文檔的不同部分應(yīng)用不同的訪問權(quán)限。
在繼續(xù)閱讀之前,請考慮更多的應(yīng)用程序場景,除了實(shí)現(xiàn) URL 安全性以外,這些場景還要求您對單獨(dú)的類訪問進(jìn)行保護(hù)。
業(yè)務(wù)自動(dòng)化應(yīng)用程序中的工作流由多個(gè)流程組成。例如,病理學(xué)實(shí)驗(yàn)室中執(zhí)行血液測試的工作流由若干個(gè)步驟組成,其中每個(gè)步驟可看作一個(gè)業(yè)務(wù)流程:
- 工作人員從病人處采集血液樣本并為其分配一個(gè) ID。
- 實(shí)驗(yàn)室技術(shù)人員對樣本進(jìn)行必要的測試并準(zhǔn)備測試結(jié)果。
- 由具備相應(yīng)資格的病理學(xué)專家根據(jù)測試結(jié)果編寫測試報(bào)告。
很明顯,每個(gè)流程分別由單獨(dú)的授權(quán)用戶執(zhí)行。未授權(quán)的用戶則無權(quán)執(zhí)行流程。例如,實(shí)驗(yàn)室研究人員只負(fù)責(zé)準(zhǔn)備試驗(yàn)結(jié)果,而無權(quán)編寫測試報(bào)告。
幾乎所有的業(yè)務(wù)自動(dòng)化應(yīng)用程序都普遍使用授權(quán)的業(yè)務(wù)流程。通常,每個(gè)業(yè)務(wù)流程被實(shí)現(xiàn)為一個(gè) Java 類,并且需要使用合適的訪問控制策略對所有類實(shí)施保護(hù)。
企業(yè)對企業(yè)(Business-to-business)集成
Business-to-business (B2B) 集成指一種常見的場景,其中的兩個(gè)企業(yè)實(shí)體需要彼此公開各自的特定功能。例如,賓館可能向旅游公司公開其房間預(yù)訂功能,而后者使用該功能為游客預(yù)訂空閑的房間。作為合作伙伴的旅游公司可能具有一個(gè)特定的訂房率。在這個(gè)場景中,賓館的訂房系統(tǒng)必須先對旅游公司進(jìn)行身份驗(yàn)證,然后才能允許他們訪問所選擇的類,以便按照特定的訂房率進(jìn)行房間預(yù)訂。
![]() ![]() |
![]()
|
現(xiàn)在您已經(jīng)了解了對 Java 類示例的訪問進(jìn)行保護(hù)的重要性。在介紹能夠?qū)崿F(xiàn)更高級安全性的 Acegi 新功能之前,我將引導(dǎo)您回顧 Spring 框架的幾個(gè)關(guān)鍵特性,您需要了解這些內(nèi)容才能繼續(xù)后文的示例。
首先對一些 Java 類進(jìn)行配置并執(zhí)行實(shí)例化。第 1 部分 曾介紹過,Java 類在 Spring 的 XML 配置文件中進(jìn)行配置。在 Spring 配置文件中配置 Java 類的過程與 Acegi 過濾器的配置過程完全相同,因此這里不多做介紹。相反,我們將查看清單 1,它展示了名為 publicCatalog
的 bean 的配置:
清單 1. Acegi XML 配置文件
<beans> <bean id="publicCatalog" class="com.catalog.PublicCatalog" /> <!--Other bean tags --> <beans> |
了解 Spring 的 IOC 框架如何從 XML 配置文件讀取 Java 類信息以及如何進(jìn)行實(shí)例化,這一點(diǎn)非常重要。您可能還記得,我在系列文章的 第 1 部分 中使用一個(gè) web.xml 文件配置 <listener>
標(biāo)記,它指向名為 ContextLoaderListener
的類。ContextLoaderListener
裝載 Spring 的 IOC 框架并創(chuàng)建 Java 對象。您可以參考 第 1 部分的清單 8 查看全部內(nèi)容。圖 1 也對此進(jìn)行了描述:
圖 1. 裝載 Spring 的 IOC 框架并創(chuàng)建 Java 對象

現(xiàn)在我們將詳細(xì)討論這些步驟:
- 當(dāng)初始化 Acegi 應(yīng)用程序時(shí),servlet 容器(本例中為 Apache Tomcat)創(chuàng)建了一個(gè) servlet 上下文,其中保存了有關(guān)應(yīng)用程序資源的信息,例如 JSP 頁面和類。
- servlet 容器通知
ContextLoaderListener
類應(yīng)用程序正在啟動(dòng)。
ContextLoaderListener
類創(chuàng)建一個(gè) Web 應(yīng)用程序上下文以保存應(yīng)用程序中特定于 Spring 的資源信息。借助 Spring 的 IOC 框架,您可以裝載自己的自定義應(yīng)用程序上下文。要?jiǎng)?chuàng)建應(yīng)用程序上下文,將使用名為ContextLoader
的上下文裝載器類裝載應(yīng)用程序上下文。
- 如果應(yīng)用程序不需要定義自己的應(yīng)用程序上下文,則可以使用名為
XMLWebApplicationContext
的類,它是 Spring 框架的一部分并提供可處理 Spring XML 配置文件的功能。Acegi 應(yīng)用程序使用的是 Spring 的 XML 配置文件,因此本文僅討論由XMLWebApplicationContext
類表示的應(yīng)用程序上下文。在本例中,上下文裝載器對XMLWebApplicationContext
類進(jìn)行實(shí)例化,后者表示您的 Acegi 應(yīng)用程序的應(yīng)用程序上下文。上下文裝載器還在 Web 應(yīng)用程序上下文中設(shè)置 servlet 上下文(于步驟 1 中創(chuàng)建)的引用。
XMLWebApplicationContext
類對 XML 配置文件進(jìn)行解析,獲得關(guān)于 Java 類的信息并將信息裝載到其他內(nèi)部對象中。
XMLWebApplicationContext
類對 XML 配置文件中指定的所有 Java 類進(jìn)行實(shí)例化。XMLWebApplicationContext
類檢查 XML 配置文件中經(jīng)過配置的 Java bean 是否依賴其他的 Java 對象。如果是的話,XMLWebApplicationContext
類將首先對其他 bean 所依賴的 bean 進(jìn)行實(shí)例化。通過這種方式,XMLWebApplicationContext
類創(chuàng)建了 XML 配置文件中定義的所有 bean 的實(shí)例。(注意,步驟 6 假定 XML 配置文件中所有 bean 都不要進(jìn)行保護(hù),稍后一節(jié)將介紹步驟 5 和步驟 6 之間執(zhí)行的額外步驟,從而保護(hù)對此處創(chuàng)建的 Java bean 的訪問)。
XMLWebApplicationContext
類將所有 bean 保存在一個(gè)數(shù)組中。
您現(xiàn)在已了解到如何從 XML 配置文件中裝載 bean 定義并創(chuàng)建 Java 類的實(shí)例。接下來,我將向您介紹 Spring bean 代理并解釋它對于保護(hù) Java 類實(shí)例的重要性。
![]() ![]() |
![]()
|
上一節(jié)討論了 Spring 的 IOC 框架對 Java 對象進(jìn)行實(shí)例化。要保護(hù)對 Java 對象的訪問,Spring 的 IOC 框架使用了 bean 代理 的概念。本節(jié)首先介紹如何配置 bean 代理,然后演示 Spring 的 IOC 框架如何創(chuàng)建代理對象。
如果希望創(chuàng)建 bean 代理,Spring IOC 框架要求您對代理創(chuàng)建器 bean 的實(shí)例進(jìn)行配置。Spring 的 IOC 框架使用代理創(chuàng)建器創(chuàng)建代理對象。清單 2 為代理創(chuàng)建器 bean 的配置文件,用于保護(hù)名為 privateCatalog
的 Java 對象:
清單 2. 代理 bean 配置
<bean id="proxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"> <list> <value>privateCatalog</value> <!--Names of other beans to be proxied --> </list> </property> <property name="interceptorNames"> <list> <value>privateCatalogSecurityInterceptor</value> </list> </property> </bean> |
如清單 2 所示,<bean>
標(biāo)記具有一個(gè) class
屬性,其值為 org.springframework.aop.framework.autoproxy. BeanNameAutoProxyCreator
。BeanNameAutoProxyCreator
類是 Spring IOC 框架的一部分,可以自動(dòng)創(chuàng)建 bean 代理。Spring 框架提供了 BeanPostProcessor
接口,它提供了一種可擴(kuò)展機(jī)制,允許應(yīng)用程序編寫自己的邏輯來創(chuàng)建 bean 代理。Spring 的 BeanNameAutoProxyCreator
類實(shí)現(xiàn)了 BeanPostProcessor
接口并提供所有必需的代理創(chuàng)建邏輯來保護(hù) Java 類。因此,本文中您無需實(shí)現(xiàn) BeanPostProcessor
接口。
在創(chuàng)建 bean 代理時(shí),BeanNameAutoProxyCreator
類為所有由 beanNames
屬性定義的 bean 創(chuàng)建代理(參見 清單 2 中 <bean>
標(biāo)記的第一個(gè) <property>
子元素)。beanNames
屬性在 <list>
標(biāo)記中包含一個(gè) bean 名稱列表。在 清單 2 中,我只對希望為之創(chuàng)建代理的 privateCatalog
bean進(jìn)行了配置。
現(xiàn)在查看 清單 2 中 <bean>
標(biāo)記的第二個(gè) <property>
子元素。它指定了名為 interceptorNames
的代理,它將一個(gè)或多個(gè)攔截器的名稱封裝起來。我將在后文詳細(xì)討論攔截器概念。現(xiàn)在,只需了解攔截器可以攔截用戶并在用戶訪問 bean 之前實(shí)現(xiàn)訪問控制策略。
現(xiàn)在,您已了解了如何對希望進(jìn)行保護(hù)的 bean 配置代理。接下來,您將了解 Spring 的 IOC 框架如何在內(nèi)部為應(yīng)用程序的 bean 創(chuàng)建代理對象。
在 “使用 Spring 創(chuàng)建 Java 對象” 的步驟 5 和步驟 6 中,您了解了 XMLWebApplicationContext
類如何從 XML 配置文件中讀取 bean 定義并隨后創(chuàng)建 bean 實(shí)例。在創(chuàng)建 bean 實(shí)例之前,XMLWebApplicationContext
類將檢查 XML 配置文件是否包含任何代理創(chuàng)建器 bean(即實(shí)現(xiàn) BeanPostProcessor
接口的 bean)配置。如果存在該 bean,它將要求代理創(chuàng)建器為您希望進(jìn)行保護(hù)的 bean 創(chuàng)建 bean 代理。
現(xiàn)在考慮代理創(chuàng)建器如何在內(nèi)部創(chuàng)建代理對象:
- 代理創(chuàng)建器(即
BeanNameAutoProxyCreator
類)裝載 清單 2 中配置的beanNames
屬性文件中指定的所有 bean 名稱。
- 代理創(chuàng)建器使用 bean 名稱裝載各自的 Java 類,這些類使用了每個(gè) bean 定義的
class
屬性。
- 代理創(chuàng)建器創(chuàng)建 清單 2 所示的
interceptorNames
屬性中指定的攔截器的實(shí)例。
- 最后,代理創(chuàng)建器創(chuàng)建一個(gè)
Cglib2AopProxy
類的實(shí)例,將所有 bean 名稱(步驟 2)和攔截器(步驟 3)傳遞到Cglib2AopProxy
類。Cglib2AopProxy
類是 Spring 框架的一部分并用于生成動(dòng)態(tài)代理對象。在本例中,Cglib2AopProxy
類將創(chuàng)建安全 bean 訪問控制所需的代理對象。
Cglib2AopProxy
類實(shí)現(xiàn)了兩個(gè)名為 AOPProxy
和 MethodInterceptor
的接口。AOPProxy
接口由 Spring 框架提供,表示您希望進(jìn)行代理的實(shí)際 bean,因此它與您的 bean 公開相同的方法。MethodInterceptor
接口也源于 AOP 框架,它包含的方法可以在用戶試圖訪問您已執(zhí)行代理的 bean 時(shí)接受控制權(quán)。這意味著 MethodInterceptor
接口處理來自用戶的請求以訪問執(zhí)行過代理的 bean。由于 Cglib2AopProxy
類同時(shí)實(shí)現(xiàn)了 AOPProxy
和 MethodInterceptor
接口,因此它提供了完整的功能,既可以提供經(jīng)過代理的 bean,也可以處理用戶請求以訪問代理 bean(參見 參考資料小節(jié) 中有關(guān) AOP 的討論文章的鏈接)。
執(zhí)行完前面的步驟后,您現(xiàn)在具有了所需的代理對象。因此 XMLWebApplicationContext
類將安全 bean 的代理(而不是實(shí)際的 bean)保存在 “使用 Spring 創(chuàng)建 Java 對象” 的步驟 7 中的同一個(gè)數(shù)組中。
![]() ![]() |
![]()
|
在前面的幾節(jié)中,您了解了 Spring 如何創(chuàng)建公有 bean 和私有 bean。出于本文的目的,您可將公有 bean 視為使用代理保護(hù)的不安全的私有 bean。現(xiàn)在我們來看一下客戶機(jī)應(yīng)用程序?yàn)樵L問公有 bean 和私有 bean 而必須遵循的一系列步驟。
清單 3 展示了 publicCatalog
和 privateCatalog
兩個(gè) bean 的 XML 配置。publicCatalog
bean 意味著公共訪問,因此不需要使用 bean 代理。privateCatalog
bean 意味著只能由指定用戶訪問,因此必須加以保護(hù)。我在清單 3 中包含了 privateCatalog
bean 的 bean 代理配置:
清單 3. publicCatalog 和 privateCatalog bean 的 XML 配置
<beans> <bean id="publicCatalog" class="sample.PublicCatalog"/> <bean id="privateCatalog" class="sample.PrivateCatalog"/> <!-- proxy configuration for privateCatalog bean --> <bean id="proxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"> <list> <value>privateCatalog</value> <!--Names of other beans to be proxied --> </list> </property> <property name="interceptorNames"> <list> <value>privateCatalogSecurityInterceptor</value> </list> </property> </bean> <beans> |
應(yīng)用程序可以使用清單 4 中的代碼訪問清單 3 中配置的 publicCatalog
和 privateCatalog
Java bean。注意,清單 4 中顯示的 Java 代碼可位于 JSP 頁面或位于服務(wù)器端 Java 應(yīng)用程序的 bean 中。
清單 4. 訪問安全和不安全 Java bean 的客戶機(jī)應(yīng)用程序代碼
//Step 1: Fetching an instance of the application context XMLWebApplicationContext applicationCtx = WebApplicationContextUtils.getWebApplicationContext( this.getServletConfig().getServletContext()); //Step 2: Fetching an insecure bean from the application context PublicCatalog publicCatalog = (PublicCatalog) applicationCtx.getBean("publicCatalog"); //Step 3: Calling a method of the insecure bean String publicData = publicCatalog.getData(); //Step 4: Fetching a secure bean from the application context PrivateCatalog privateCatalog = (PrivateCatalog) applicationCtx.getBean("privateCatalog"); //Step 5: Calling a method of the secure bean String privateData = privateCatalog.getData(); |
下面將進(jìn)一步討論清單 4 中的步驟:
- 步驟 1:取回一個(gè)應(yīng)用程序上下文實(shí)例
當(dāng)應(yīng)用程序希望訪問 XML 配置文件中配置的 Java bean 時(shí),它必須取回您在 “使用 Spring 創(chuàng)建 Java 對象” 的步驟 4 中見到的XMLWebApplicationContext
對象。XMLWebApplicationContext
對象包含對 XML 配置文件配置的所有 Java beans 的引用。
- 步驟 2:從應(yīng)用程序上下文中取回不安全的 bean
您現(xiàn)在具有一個(gè)對XMLWebApplicationContext
對象的引用。XMLWebApplicationContext
類公開了一個(gè)getBean()
方法,它包含 bean 的名稱并在數(shù)組中查找 “使用 Spring 創(chuàng)建 Java 對象” 步驟 7 中準(zhǔn)備的 bean。在本例中,該 bean 為publicCatalog
(未執(zhí)行過代理),因此XMLWebApplicationContext
將返回實(shí)際的 bean。
- 步驟 3:調(diào)用不安全 bean 的方法
現(xiàn)在您可以調(diào)用步驟 2 中獲得的publicCatalog
bean 的任何方法。例如,清單 4 顯示的getData()
方法調(diào)用的執(zhí)行沒有應(yīng)用任何訪問控制并向應(yīng)用程序返回類別數(shù)據(jù)。
- 步驟 4:從應(yīng)用程序上下文取回安全 bean
安全 bean 與不安全 bean 的取回方式類似,惟一區(qū)別是:當(dāng)您通過調(diào)用getBean()
方法嘗試取回安全 bean 時(shí),您將獲得安全對象的代理而不是實(shí)際的對象。該代理就是我在 “Spring IOC 發(fā)揮效用” 步驟 4 中解釋的由 Spring 框架創(chuàng)建的同一個(gè)對象。
- 步驟 5:調(diào)用安全 bean 的方法
當(dāng)調(diào)用安全 bean 的方法時(shí),您在 步驟 4 中獲得的代理對象將一個(gè)方法調(diào)用請求分配給攔截器。攔截器將檢查試圖訪問方法的用戶是否具有相應(yīng)的訪問權(quán),從而處理方法調(diào)用請求。
您現(xiàn)在應(yīng)該對 Spring 框架如何創(chuàng)建 Java 對象以及客戶機(jī)應(yīng)用程序如何與之交互有了清晰的了解。了解了這些內(nèi)容后,就更加容易理解并利用 Acegi 的方法安全性攔截器,下一節(jié)將具體介紹該主題。
![]() ![]() |
![]()
|
只要應(yīng)用程序試圖訪問由 Acegi 安全系統(tǒng)保護(hù)的 bean 方法,請求將被自動(dòng)傳遞到 Acegi 的方法安全性攔截器。方法安全性攔截器的作用就是控制對安全 Java bean 的方法的訪問。攔截器使用 Acegi 的身份驗(yàn)證和授權(quán)框架確認(rèn)用戶是否具有權(quán)利調(diào)用安全 Java bean 的方法,然后相應(yīng)地作出響應(yīng)。
清單 5 展示 Acegi 的方法安全性攔截器的示例配置:
清單 5. 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 <!-- Roles required by other beans --> </value> </property> </bean> |
清單 5 所示的攔截器配置包含三個(gè)需要進(jìn)行配置的屬性,可以保護(hù)對 Java bean 的訪問:authenticationManager
、accessDecisionManager
和 objectDefinitionSource
。
回憶一下,您在本系列第 1 部分的 配置身份驗(yàn)證處理過濾器 中曾對 authenticationManager
屬性進(jìn)行了配置。authenticationManager
屬性的作用是對用戶進(jìn)行身份驗(yàn)證。
您在本系列的第二篇文章中了解了 accessDecisionManager 屬性。這個(gè)訪問決策管理器負(fù)責(zé)制定授權(quán)決策。在允許對一個(gè)安全 bean 進(jìn)行訪問之前,方法安全攔截器使用 authenticationManager
和 accessDecisionManager
屬性對用戶進(jìn)行身份驗(yàn)證和授權(quán)。
現(xiàn)在查看 清單 5 中配置的 objectDefinitionSource
屬性。它類似于第 1 部分中出現(xiàn)的 objectDefinitionSource 屬性。以前的 objectDefinitionSource 包含類似于 /protected/*
和 /**
這樣的 URL,清單 5 中的 objectDefinitionSource
屬性指定類和方法名;例如,sample.PrivateCatalog
是之前執(zhí)行過代理的類的名稱,而 getData
是您希望對其控制用戶訪問的方法的名字。
當(dāng)用戶訪問 PrivateCatalog
bean 的 getData()
方法時(shí),控制權(quán)將自動(dòng)傳遞給攔截器。攔截器使用 Acegi 框架檢查用戶的業(yè)務(wù)角色是否為 ROLE_HEAD_OF_ENGINEERING
(特定于本文的示例)。如果是的話,攔截器將允許對 getData()
方法進(jìn)行訪問。如果攔截器發(fā)現(xiàn)用戶角色不是 ROLE_HEAD_OF_ENGINEERING
,則拒絕訪問。
下一節(jié)將查看一個(gè)示例 Acegi 應(yīng)用程序,它將實(shí)現(xiàn)您目前所了解的所有概念。
![]() ![]() |
![]()
|
本文的 下載源代碼 包含了一個(gè)名為 AcegiMethodSecurity 的示例應(yīng)用程序,可按照以下方法進(jìn)行配置和部署:
- 使用用戶信息填充 LDAP 服務(wù)器。下載的示例應(yīng)用程序 包含一個(gè) LDIF 文件,其中含有預(yù)備裝載到 LDAP 服務(wù)器的用戶信息。關(guān)于如何將 LDIF 文件導(dǎo)入到 LDAP 服務(wù)器,請參考第 2 部分的 “填充服務(wù)器” 一節(jié)。注意,該應(yīng)用程序涉及與第 2 部分相同的用戶(
alice
、bob
和specialUser
)。
- 將本文下載源代碼中的 acegiMethodSecurity.war 文件復(fù)制到 Tomcat 安裝目錄中的 webapps 目錄。
- 將 Acegi 的 jar 文件復(fù)制到示例應(yīng)用程序的 WEB-INF/lib 文件夾。(有關(guān)內(nèi)容請參考第 1 部分的 “部署和運(yùn)行應(yīng)用程序” 一節(jié)。 )
- 下載 cglib-full-2.0.2.jar 文件并將其復(fù)制到示例應(yīng)用程序的 WEB-INF/lib 文件夾。
啟動(dòng) Tomcat 并嘗試運(yùn)行示例應(yīng)用程序。
通過從瀏覽器訪問 http://localhost:8080/acegiMethodSecurity URL 可調(diào)用示例應(yīng)用程序。AcegiMethodSecurity 顯示的索引頁面包含兩個(gè)鏈接(Catalog 和 Login),如圖 2 所示:
圖 2. 示例應(yīng)用程序的主頁面

當(dāng)單擊應(yīng)用程序的 Catalog 鏈接時(shí),它將要求您進(jìn)行登錄。如果以 alice
或 specialUser
的身份進(jìn)行登錄,示例應(yīng)用程序?qū)⑻峁?em>完整的 類別,包括公有數(shù)據(jù)和私有數(shù)據(jù)。這是因?yàn)樵?清單 5 中,您對方法安全性攔截器進(jìn)行了配置,允許用戶使用 ROLE_HEAD_OF_ENGINEERING
訪問私有類別,而 alice
和 specialUser
都具有該訪問權(quán)。另一方面,如果您以 bob
的身份登錄,示例應(yīng)用程序?qū)H顯示公有數(shù)據(jù)。
![]() ![]() |
![]()
|
本節(jié)將演示經(jīng)過增強(qiáng)的示例應(yīng)用程序。增強(qiáng)后的示例應(yīng)用程序?qū)⒄故?Acegi 如何使您能夠在運(yùn)行時(shí)向通過身份驗(yàn)證的用戶臨時(shí)分配額外角色。
當(dāng)安全 bean(例如 清單 3 的 privateCatalog
bean)要訪問一個(gè)原創(chuàng)資源時(shí),您可能需要使用額外的角色。例如,您可能考慮到您的安全 bean 需要通過 Java 的 Remote Method Invocation (RMI) 框架或一個(gè) Web 服務(wù)訪問某個(gè)遠(yuǎn)程應(yīng)用程序。訪問安全 bean 的用戶不會(huì)占用遠(yuǎn)程應(yīng)用程序要求訪問用戶所具備的業(yè)務(wù)角色。
在本例中,Acegi 首先檢查用戶是否經(jīng)過授權(quán)來訪問安全 bean。之后,Acegi 允許用戶訪問安全 bean。當(dāng)安全 bean 試圖訪問遠(yuǎn)程服務(wù)時(shí),它需要使用額外的業(yè)務(wù)角色。如果訪問安全 bean 的用戶不具備額外角色,安全 bean 就不能成功訪問遠(yuǎn)程服務(wù)。
Acegi 框架提供了一種名為 run-as-replacement 的簡單機(jī)制,允許您僅在方法調(diào)用期間為通過身份驗(yàn)證的用戶配置一個(gè)或多個(gè)額外角色。您可以使用 run-as-replacement 機(jī)制為訪問遠(yuǎn)程應(yīng)用程序的安全 bean 配置額外角色。這意味著只要安全 bean 需要訪問遠(yuǎn)程應(yīng)用程序,Acegi 將為用戶裝載額外角色,從而允許安全 bean 訪問遠(yuǎn)程應(yīng)用程序。
清單 6 對 清單 5 中的方法安全性攔截器的配置進(jìn)行了增強(qiáng)。增強(qiáng)后的配置使用了 run-as-replacement 機(jī)制。
清單 6. Acegi 方法安全性攔截器的增強(qiáng)配置
<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="runAsManager"> |
清單 6 使用粗體顯示了兩處增強(qiáng)(與 清單 5 相比)。第一處增強(qiáng)為 runAsManager
屬性。runAsManager
屬性的作用是向通過身份驗(yàn)證的用戶動(dòng)態(tài)添加角色。出于這個(gè)目的,runAsManager
屬性包含了 RunAsManagerImpl
bean 的定義。RunAsManagerImpl
bean 只有在滿足下面的條件時(shí)才可變?yōu)榛钴S狀態(tài):在 objectDefinitionSource
方法的角色定義中找到以 RUN_AS_
為前綴的角色。例如,PrivateCatalog.getData()
方法的角色定義(清單 6 中以粗體顯示的第二處增強(qiáng))具有一個(gè) RUN_AS_MANAGER
角色。
RunAsManagerImpl
bean 包含一個(gè)名為 key
的屬性,它封裝的加密鍵用于確保只將額外的角色作為 run-as-replacement 程序的一部分生成。
當(dāng)用戶調(diào)用 getData()
方法時(shí),RunAsManagerImpl
bean 變?yōu)榛钴S狀態(tài)并創(chuàng)建名為 RUN_AS_MANAGER
的額外角色,從而啟用 getData()
方法訪問遠(yuǎn)程應(yīng)用程序。
本文的 下載源代碼 包含一個(gè)名為 EnhancedAcegiMethodSecurity
的示例應(yīng)用程序,它可以演示 run-as-replacement 機(jī)制和程序。該應(yīng)用程序?qū)@示一個(gè)具有 Catalog 鏈接的索引頁面。如果單擊 Catalog 鏈接,將要求進(jìn)行登錄。
登錄后,EnhancedAcegiMethodSecurity
應(yīng)用程序?qū)槟峁┑卿浻脩艏捌浣巧耐暾畔ⅰ@纾绻?alice
或 specialUser
身份登錄,將向您顯示用戶的所有業(yè)務(wù)角色,包括額外創(chuàng)建的臨時(shí)的 RUN_AS_MANAGER
角色。
在這份共分三部分的系列文章中,我介紹了如何使用 Acegi 安全系統(tǒng)增強(qiáng)基于 URL 的安全性和基于方法的安全性。您了解了如何設(shè)計(jì)訪問控制策略并將它們托管在目錄服務(wù)器中,如何對 Acegi 進(jìn)行配置以與目錄服務(wù)器進(jìn)行通信,以及如何根據(jù)托管在服務(wù)器的訪問控制策略制定身份驗(yàn)證和授權(quán)決策。
本系列的最后一篇文章主要介紹使用基于方法的安全性保護(hù) Java 類實(shí)例。文章還解釋了 Acegi 和 Spring 如何在內(nèi)部創(chuàng)建和代理 Java 對象以及 bean 代理如何實(shí)現(xiàn)訪問控制。文章包含了兩個(gè)示例應(yīng)用程序,您可以使用它們進(jìn)一步研究本系列中學(xué)到的概念,更多有關(guān)使用 Acegi 保護(hù) Java 應(yīng)用程序的內(nèi)容,請參見 參考資料 小節(jié)。
來自:http://www-128.ibm.com/developerworks/cn/java/j-acegi3/?
posted on 2008-05-08 18:47 狼愛上貍 閱讀(418) 評論(0) 編輯 收藏 所屬分類: Acegi