使用 Acegi Security System 實現基於 URL 的安全性
Acegi Security System 是一種功能強大並易於使用的替代性方案,使您不 必再為 Java 企業應用程序編寫大量的安全代碼。雖然它專門針對使用 Spring 框架編寫的應用程序,但是任何類型的 Java 應用程序都沒有理由不去使用 Acegi。這份共分三部分的系列文章詳細介紹了 Acegi,並展示了如何使用它保 護簡單的企業應用程序以及更復雜的應用程序。
本系列首先介紹企業應用程序中常見的安全問題,並說明 Acegi 如何解決這 些問題。您將了解 Acegi 的架構模型及其安全過濾器,後者包含了在保護應用 程序中將用到的大多數功能。您還將了解到各個過濾器如何單獨進行工作,如何 將它們組合起來,以及過濾器如何在一個企業安全實現中將各種功能從頭到尾地 鏈接起來。本文最後通過一個樣例應用程序演示了基於 URL 安全系統的 Acegi 實現。本系列後續兩篇文章將探究 Acegi 的一些更高級的應用,包括如何設計 和托管訪問控制策略,然後如何去配置 Acegi 以使用這些策略。
您必須 下載 Acegi,這樣才能編譯本文的示例代碼並運行本文的樣例應用程 序。還必須有作為工作站的一部分運行的 Tomcat 服務器。
企業應用程序安全性
由於企業內容管理(ECM)應用程序管理存儲在不同類型數據源(如文件系統 、關系數據庫和目錄服務)中的企業內容的編寫和處理,ECM 安全性要求對這些 數據源的訪問進行控制。比如,一個 ECM 應用程序可能會控制被授權讀取、編 輯或刪除數據的對象,而這些數據和制造業企業的設計、市場營銷、生產以及質 量控制有關。
在一個 ECM 安全場景中,比較常見的就是通過對企業資源定位符(或網絡地 址)應用安全性,從而實現訪問控制。這種簡單的安全模型被稱為統一資源定位 符 或 URL 安全性。正如我在本文後面(以及本系列後續文章)所演示的一樣, Acegi 為實現 URL 安全性提供了全面的特性。
然而,在很多企業場景中,URL 安全性還遠遠不夠。比如,假設一個 PDF 文 檔包含某個制造業公司生產的特殊產品的數據。文檔的一部分包含了將由該公司 的設計部門編輯和更新的設計數據。另一部分包含了生產經理將使用的生產數據 。對於諸如此類的場景,需要實現更加細粒度的安全性,對文檔的不同部分應用 不同的訪問權限。
本文介紹了 Acegi 為實現 URL 安全性而提供的各種功能。本系列的下一篇 文章將演示此框架的基於方法的安全性,它提供了對企業數據訪問的更細粒度的 控制。
Acegi Security System
Acegi Security System 使用安全過濾器來提供企業應用程序的身份驗證和 授權服務。該框架提供了不同類型的過濾器,可以根據應用程序的需求進行配置 。您將在本文後面了解到 安全過濾器的不同類型;現在,只需注意可以為如下 任務配置 Acegi 安全過濾器:
在訪問一個安全資源之前提示用戶登錄。
通過檢查安全標記(如密碼),對用戶進行身份驗證。
檢查經過身份驗證的用戶是否具有訪問某個安全資源的特權。
將成功進行身份驗證和授權的用戶重定向到所請求的安全資源。
對不具備訪問安全資源特權的用戶顯示 Access Denied 頁面。
在服務器上記錄成功進行身份驗證的用戶,並在用戶的客戶機上設置安全 cookie。使用該 cookie 執行下一次身份驗證,而無需要求用戶登錄。
將身份驗證信息存儲在服務器端的會話對象中,從而安全地進行對資源的後 續請求。
在服務器端對象中構建並保存安全信息的緩存,從而優化性能。
當用戶退出時,刪除為用戶安全會話而保存的服務器端對象。
與大量後端數據存儲服務(如目錄服務或關系數據庫)進行通信,這些服務 用於存儲用戶的安全信息和 ECM 的訪問控制策略。
正如這個列表顯示的那樣,Acegi 的安全過濾器允許您執行保護企業應用程 序所需的幾乎任何事情。
架構和組件
對 Acegi 了解越多,使用起來就越簡單。這一節介紹 Acegi 的組件;接下 來您將了解該框架如何使用反轉控制(IOC)和 XML 配置文件來組合組件並表示 它們的依賴關系。
四大組件
Acegi Security System 由四種主要類型的組件組成:過濾器、管理器、提 供者和處理程序。
過濾器 這種最高級的組件提供了常見的安全服務,如身份驗證、會話處理以 及注銷。我將在 本文後面的部分 深入討論過濾器。 管理器 過濾器僅是安全相 關功能的高級抽象:實際上要使用管理器和提供者實現身份驗證處理和注銷服務 。管理器管理由不同提供者提供的較低級的安全服務。 提供者 有大量的提供者 可用於和不同類型的數據存儲服務通信,例如目錄服務、關系數據庫或簡單的內 存中的對象。這意味著您可以將用戶庫和訪問控制協議存儲在任何一種這樣的數 據存儲服務中,並且 Acegi 的管理器將在運行時選擇合適的提供者。 處理程序 有時任務可能會被分解為多個步驟,其中每個步驟由一個特定的處理程序執行。 比方說,Acegi 的 注銷過濾器 使用兩個處理程序來退出一個 HTTP 客戶機。其 中一個處理程序使用戶的 HTTP 會話無效,而另一個處理程序則刪除用戶的 cookie。當根據應用程序需求配置 Acegi 時,多個處理程序能夠提供很好的靈 活性。您可以使用自己選擇的處理程序來執行保護應用程序所需的步驟。
反轉控制
Acegi 的組件通過彼此之間的依賴來對企業應用程序進行保護。比如,一個 身份驗證處理過濾器需要一個身份驗證管理器選擇一個合適的身份驗證提供者。 這就是說您必須能夠表示和管理 Acegi 組件的依賴關系。
IOC 實現通常用於管理 Java 組件之間的依賴關系。IOC 提供了兩個重要的 特性:
它提供了一種語法,表示應用程序所需的組件以及這些組件如何相互依賴。
它保證了所需的組件在運行時是可用的。
XML 配置文件
Acegi 使用 Spring 框架(請參見 參考資料)附帶的流行開源 IOC 實現來 管理其組件。Spring 需要您編寫一個 XML 配置文件來表示組件的依賴關系,如 清單 1 所示:
清單 1. Spring 配置文件的結構
<beans>
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value> value here </value>
</property>
</bean>
<bean id="authenticationProcessingFilter"
class="org.acegisecurity.ui.webapp.AuthenticationProcessingFitler">
<property name="authenticationManager" ref="authManager"/>
<!-- Other properties -->
</bean>
<bean id="authManager"
class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<!-- List of providers here -->
</property>
</bean>
<!-- Other bean tags -- >
</beans>
如您所見,Acegi 使用的 Spring XML 配置文件包含一個 <beans> 標 記,它封裝了一些其他的 <bean> 標記。所有的 Acegi 組件(即過濾器 、管理器、提供者等)實際上都是 JavaBean。XML 配置文件中的每個 <bean> 標記都代表一個 Acegi 組件。
進一步解釋 XML 配置文件
首先將注意到的是每個 <bean> 標記都包含一個 class 屬性,這個屬 性標識組件所使用的類。<bean> 標記還具有一個 id 屬性,它標識作為 Acegi 組件工作的實例(Java 對象)。
比方說,清單 1 的第一個 <bean> 標記標識了名為 filterChainProxy 的組件實例,它是名為 org.acegisecurity.util.FilterChainProxy 的類的實例。
使用 <bean> 標記的子標記來表示 bean 的依賴關系。比如,注意第 一個 <bean> 標記的 <property> 子標記。<property> 子 標記定義了 <bean> 標記依賴的其他 bean 或值。
所以在 清單 1 中,第一個 <bean> 標記的 <property> 子標 記具有一個 name 屬性和一個 <value> 子標記,分別定義了這個 bean 依賴的屬性的名稱和值。
同樣,清單 1 中的第二個和第三個 <bean> 標記定義了一個過濾器 bean 依賴於一個管理器 bean。第二個 <bean> 標記表示過濾器 bean, 而第三個 <bean> 標記表示管理器 bean。
過濾器的 <bean> 標記包含一個 <property> 子標記,該子標 記具有兩個屬性:name 和 ref。name 屬性定義了過濾器 bean 的屬性,而 ref 屬性引用了管理器 bean 的實例(名稱)。
下一節將展示如何在 XML 配置文件中配置 Acegi 過濾器。在本文後面的內 容中,您將在一個樣例 Acegi 應用程序中使用過濾器。
安全過濾器
正如我前面提到的一樣,Acegi 使用安全過濾器為企業應用程序提供身份驗 證和授權服務。您可以根據應用程序的需要使用和配置不同類型的過濾器。這一 節將介紹五種最重要的 Acegi 安全過濾器。
Session Integration Filter
Acegi 的 Session Integration Filter(SIF)通常是您將要配置的第一個 過濾器。SIF 創建了一個安全上下文對象,這是一個與安全相關的信息的占位符 。其他 Acegi 過濾器將安全信息保存在安全上下文中,也會使用安全上下文中 可用的安全信息。
SIF 創建安全上下文並調用過濾器鏈中的其他過濾器。然後其他過濾器檢索 安全上下文並對其進行更改。比如,Authentication Processing Filter(我將 稍後進行介紹)將用戶信息(如用戶名、密碼和電子郵件地址)存儲在安全上下 文中。
當所有的處理程序完成處理後,SIF 檢查安全上下文是否更新。如果任何一 個過濾器對安全上下文做出了更改,SIF 將把更改保存到服務器端的會話對象中 。如果安全上下文中沒有發現任何更改,那麼 SIF 將刪除它。
在 XML 配置文件中對 SIF 進行了配置,如清單 2 所示:
清單 2. 配置 SIF
<bean id="httpSessionContextIntegrationFilter"
class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"/ >
Authentication Processing Filter
Acegi 使用 Authentication Processing Filter(APF)進行身份驗證。APF 使用一個身份驗證(或登錄)表單,用戶在其中輸入用戶名和密碼,並觸發身份 驗證。
APF 執行所有的後端身份驗證處理任務,比如從客戶機請求中提取用戶名和 密碼,從後端用戶庫中讀取用戶參數,以及使用這些信息對用戶進行身份驗證。
在配置 APF 時,您必須提供如下參數:
Authentication manager 指定了用來管理身份驗證提供者的身份驗證管理器 。
Filter processes URL 指定了客戶在登錄窗口中按下 Sign In 按鈕時要訪 問的 URL。收到這個 URL 的請求後,Acegi 立即調用 APF。
Default target URL 指定了成功進行身份驗證和授權後呈現給用戶的頁面。
Authentication failure URL 指定了身份驗證失敗情況下用戶看到的頁面。
APF 從用戶的請求對象中得到用戶名、密碼和其他信息。它將這些信息傳送 給身份驗證管理器。身份驗證管理器使用適當的提供者從後端用戶庫中讀取詳細 的用戶信息(如用戶名、密碼、電子郵件地址和用戶訪問權利或特權),對用戶 進行身份驗證,並將信息存儲在一個 Authentication 對象中。
最後,APF 將 Authentication 對象保存在 SIF 之前創建的安全上下文中。 存儲在安全上下文中的 Authentication 對象將用於做出授權決策。
APF 的配置如清單 3 所示:
清單 3. 配置 APF
<bean id="authenticationProcessingFilter"
class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
<property name="authenticationManager"
ref="authenticationManager" />
<property name="filterProcessesUrl"
value="/j_acegi_security_check" />
<property name="defaultTargetUrl"
value="/protected/protected1.jsp" />
<property name="authenticationFailureUrl"
value="/login.jsp? login_error=1" />
</bean>
可以從這段代碼中看到,APF 依賴於上面討論的這四個參數。每個參數都是 作為清單 3 所示的 <property> 標記配置的。
Logout Processing Filter
Acegi 使用一個 Logout Processing Filer(LPF)管理注銷處理。當客戶機 發來注銷請求時,將使用 LPF 進行處理。它標識了來自由客戶機所調用 URL 的 注銷請求。
LPF 的配置如清單 4 所示:
清單 4. 配置 LPF
<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
<constructor-arg value="/logoutSuccess.jsp"/>
<constructor-arg>
<list>
<bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>< BR> </list>
</constructor- arg>
</bean>
可以看到 LPF 在其構造方法中包含兩個參數:注銷成功 URL (/logoutSuccess.jsp)和處理程序列表。注銷成功 URL 用來在注銷過程完成 後重定向客戶機。處理程序執行實際的注銷過程;我在這裡只配置了一個處理程 序,因為只需一個處理程序就可以使 HTTP 會話變為無效。我將在本系列下一篇 文章中討論更多的處理程序。
Exception Translation Filter
Exception Translation Filter(ETF)處理身份驗證和授權過程中的異常情 況,比如授權失敗。在這些異常情況中,ETF 將決定如何進行操作。
比如,如果一個沒有進行身份驗證的用戶試圖訪問受保護的資源,ETF 將顯 示一個登錄頁面要求用戶進行身份驗證。類似地,在授權失敗的情況下,可以配 置 ETF 來呈現一個 Access Denied 頁面。
ETF 的配置如清單 5 所示:
清單 5. 配置 ETF
<bean id="exceptionTranslationFilter"
class="org.acegisecurity.ui.ExceptionTranslationFilter">
<property name="authenticationEntryPoint">
<bean
class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntry Point">
<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>
正如清單 5 所示,ETF 包含兩個參數,名為 authenticationEntryPoint 和 accessDeniedHandler。authenticationEntryPoint 屬性指定登錄頁面,而 accessDeniedHandler 指定 Access Denied 頁面。
攔截過濾器
Acegi 的攔截過濾器 用於做出授權決策。您需要在 APF 成功執行身份驗證 後對攔截過濾器進行配置,以使其發揮作用。攔截器使用應用程序的訪問控制策 略來做出授權決定。
本系列的下一篇文章將展示如何設計訪問控制策略,如何將它們托管在目錄 服務中,以及如何配置 Acegi 以讀取您的訪問控制策略。但是,目前我將繼續 向您展示如何使用 Acegi 配置一個簡單的訪問控制策略。在本文後面的部分, 您將看到使用簡單的訪問控制策略構建一個樣例應用程序。
配置簡單的訪問控制策略可分為兩個步驟:
編寫訪問控制策略。
根據策略配置 Acegi 的攔截過濾器。
步驟 1. 編寫簡單的訪問控制策略
首先看一下 清單 6,它展示了如何定義一個用戶及其用戶角色:
清單 6. 為用戶定義簡單的訪問控制策略
alice=123,ROLE_HEAD_OF_ENGINEERING
清單 6 所示的訪問控制策略定義了用戶名 alice,它的密碼是 123,角色是 ROLE_HEAD_OF_ENGINEERING。(下一節將說明如何在文件中定義任意數量的用戶 及其用戶角色,然後配置攔截過濾器以使用這些文件。)
步驟 2. 配置 Acegi 的攔截過濾器
攔截過濾器使用三個組件來做出授權決策,我在清單 7 中對其進行了配置:
清單 7. 配置攔截過濾器
<bean id="filterInvocationInterceptor"
class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">< BR> <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>
<!-- More properties of the interceptor filter -->
</bean>
如清單 7 所示,配置所需的三個組件是 authenticationManager、 accessDecisionManager、objectDefinitionSource:
authenticationManager 組件與我在介紹 Authentication Processing Filter 時討論過的身份驗證管理器相同。攔截過濾器可以在授權的過程中使用 authenticationManager 重新對客戶機進行身份驗證。
accessDecisionManager 組件管理授權過程,這部分內容將在本系列的下篇 文章中詳細討論。
objectDefinitionSource 組件包含對應於將要發生的授權的訪問控制定義。 例如,清單 7 中的 objectDefinitionSource 屬性值包含兩個 URL (/protected/* 和 /*)。其值定義了這些 URL 的角色。/protected/* URL 的 角色是 ROLE_HEAD_OF_ENGINEERING。您可以根據應用程序的需要定義任何角色 。
回想一下 清單 6,您為用戶名 alice 定義了 ROLE_HEAD_OF_ENGINEERING。 這就是說 alice 將能夠訪問 /protected/* URL。
過濾器工作原理
正如您已經了解到的一樣,Acegi 的組件彼此依賴,從而對您的應用程序進 行保護。在本文後面的部分,您將看到如何對 Acegi 進行配置,從而按照特定 的順序應用安全過濾器,因此需要創建過濾器鏈。出於這個目的, Acegi 保存了一個過濾器鏈對象,它封裝了為保護應用程序而配置了的所有過濾 器。圖 1 展示了 Acegi 過濾器鏈的生命周期,該周期從客戶機向您的應用程序 發送 HTTP 請求開始。(圖 1 顯示了服務於浏覽器客戶機的容器。)
圖 1. 托管 Acegi 過濾器鏈以安全地為浏覽器客戶機服務的容器
下面的步驟描述了過濾器鏈的生命周期:
浏覽器客戶機向您的應用程序發送 HTTP 請求。
容器接收到 HTTP 請求並創建一個請求對象,該對象將封裝 HTTP 請求中包 含的信息。容器還創建一個各種過濾器都可處理的響應對象,從而為發出請求的 客戶機准備好 HTTP 響應。容器然後調用 Acegi 的過濾器鏈代理,這是一個代 理過濾器。該代理知道應用的過濾器的實際順序。當容器調用代理時,它將向代 理發送請求、響應以及過濾器鏈對象。
代理過濾器調用過濾器鏈中第一個過濾器,向其發送請求、響應和過濾器鏈 對象。
鏈中的過濾器逐個執行其處理。一個過濾器可以通過調用過濾器鏈中下一個 過濾器隨時終止自身處理。有的過濾器甚至根本不執行任何處理(比如,如果 APF 發現一個到來的請求沒有要求身份驗證,它可能會立即終止其處理)。
當身份驗證過濾器完成其處理時,這些過濾器將把請求和響應對象發送到應 用程序中配置的攔截過濾器。
攔截器決定是否對發出請求的客戶機進行授權,使它訪問所請求的資源。
攔截器將控制權傳輸給應用程序(比如,成功進行了身份驗證和授權的客戶 機請求的 JSP 頁面)。
應用程序改寫響應對象的內容。
響應對象已經准備好了,容器將響應對象轉換為 HTTP 響應,並將響應發送 到發出請求的客戶機。
為幫助您進一步理解 Acegi 過濾器,我將詳細探討其中兩個過濾器的操作: Session Integration Filter 和 Authentication Processing Filter。
SIF 如何創建一個安全上下文
圖 2 展示了 SIF 創建安全上下文所涉及到的步驟:
圖 2. SIF 創建安全上下文
現在詳細地考慮下面這些步驟:
Acegi 的過濾器鏈代理調用 SIF 並向其發送請求、響應和過濾器鏈對象。注 意:通常將 SIF 配置為過濾器鏈中第一個過濾器。
SIF 檢查它是否已經對這個 Web 請求進行過處理。如果是的話,它將不再進 一步進行處理,並將控制權傳輸給過濾器鏈中的下一個過濾器(參見下面的第 4 個步驟)。如果 SIF 發現這是第一次對這個 Web 請求調用 SIF,它將設置一個 標記,將在下一次使用該標記,以表示曾經調用過 SIF。
SIF 將檢查是否存在一個會話對象,以及它是否包含安全上下文。它從會話 對象中檢索安全上下文,並將其放置在名為 security context holder 的臨時占位符中。如果不存在會話對象,SIF 將創建一個新的安全 上下文,並將它放到 security context holder 中。注意:security context holder 位於應用程序的范圍內,所以可以被其他的安全過濾器訪問。
SIF 調用過濾器鏈中的下一個過濾器。
其他過濾器可以編輯安全上下文。
SIF 在過濾器鏈完成處理後接收控制權。
SIF 檢查其他的過濾器是否在其處理過程中更改了安全上下文(比如,APF 可能將用戶詳細信息存儲在安全上下文中)。如果是的話,它將更新會話對象中 的安全上下文。就是說在過濾器鏈處理過程中,對安全上下文的任何更改現在都 保存在會話對象中。
APF 如何對用戶進行身份驗證
圖 3 展示了 APF 對用戶進行身份驗證所涉及到的步驟:
圖 3. APF 對用戶進行身份驗證
現在仔細考慮以下這些步驟:
過濾器鏈中前面的過濾器向 APF 發送請求、響應和過濾鏈對象。
APF 使用從請求對象中獲得的用戶名、密碼以及其他信息創建身份驗證標記 。
APF 將身份驗證標記傳遞給身份驗證管理器。
身份驗證管理器可能包含一個或更多身份驗證提供者。每個提供者恰好支持 一種類型的身份驗證。管理器檢查哪一種提供者支持它從 APF 收到的身份驗證 標記。
身份驗證管理器將身份驗證標記發送到適合進行身份驗證的提供者。
身份驗證提供者支持從身份驗證標記中提取用戶名,並將它發送給名為 user cache service 的服務。Acegi 緩存了已經進行過身份驗證的用 戶。該用戶下次登錄時,Acegi 可以從緩存中加載他或她的詳細信息(比如用戶 名、密碼和權限),而不是從後端數據存儲中讀取數據。這種方法使得性能得到 了改善。
user cache service 檢查用戶的詳細信息是否存在於緩存中。
user cache service 將用戶的詳細信息返回給身份驗證提供者。如果緩存不 包含用戶詳細信息,則返回 null。
身份驗證提供者檢查緩存服務返回的是用戶的詳細信息還是 null。
如果緩存返回 null,身份驗證提供者將用戶名(在步驟 6 中提取)發送給 另一個名為 user details service 的服務。
user details service 與包含用戶詳細信息的後端數據存儲通信(如目錄服 務)。
user details service 返回用戶的詳細信息,或者,如果找不到用戶詳細信 息則拋出身份驗證異常。
如果 user cache service 或者 user details service 返回有效的用戶詳 細信息,身份驗證提供者將使用 user cache service 或 user details service 返回的密碼來匹配用戶提供的安全標記(如密碼)。如果找到一個匹配 ,身份驗證提供者將用戶的詳細信息返回給身份驗證管理器。否則的話,則拋出 一個身份驗證異常。
身份驗證管理器將用戶的詳細信息返回給 APF。這樣用戶就成功地進行了身 份驗證。
APF 將用戶詳細信息保存在 圖 2 所示由步驟 3 創建的安全上下文中。
APF 將控制權傳輸給過濾器鏈中的下一個過濾器。
一個簡單的 Acegi 應用程序
在本文中,您已經了解了很多關於 Acegi 的知識,所以現在看一下利用您目 前學到的知識能做些什麼,從而結束本文。對於這個簡單的演示,我設計了一個 樣例應用程序(參見 下載),並對 Acegi 進行了配置以保護它的一些資源。
樣例應用程序包含 5 個 JSP 頁面:index.jsp、protected1.jsp、 protected2.jsp、login.jsp 和 accessDenied.jsp。
index.jsp 是應用程序的歡迎頁面。它向用戶顯示了三個超鏈接,如圖 4 所 示:
圖 4. 樣例應用程序的歡迎頁面:
圖 4 所示的鏈接中,其中兩個鏈接指向了被保護的資源 (protected1.jsp 和 protected2.jsp),第三個鏈接指向登錄頁面 (login.jsp)。只有在 Acegi 發現用戶沒有被授權訪問受保護的資源時,才會 顯示 accessDenied.jsp 頁面。
如果用戶試圖訪問任何受保護的頁面,樣例應用程序將顯示登錄頁面。當用 戶使用登錄頁面進入後,應用程序將自動重定向到被請求的受保護資源。
用戶可以通過單擊歡迎頁面中的第三個鏈接直接請求登錄頁面。這種情況下 ,應用程序顯示用戶可以進入系統的登錄頁面。進入系統以後,應用程序將用戶 重定向到 protected1.jsp,它是用戶進入系統而沒有請求特定的受保護資源時 顯示的默認資源。
配置樣例應用程序
為本文下載的源代碼包含一個名為 acegi-config.xml 的 XML 配置文件,它 包含 Acegi 過濾器的配置。根據 安全過濾器的討論 中的示例,您應該很熟悉 這些配置。
我還為樣例應用程序編寫了一個 web.xml 文件,如清單 8 所示:
清單 8. 樣例應用程序的 web.xml 文件
<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>
web.xml 文件配置如下:
acegi-config.xml 文件的 URL 位於 <context-param> 標記中。
Acegi 過濾器鏈代理類的名稱位於 <filter> 標記中。
URL 到 Acegi 過濾器鏈代理的映射在 <filter-mapping> 標記中。注 意:您可以簡單地將應用程序的所有 URL(/*)映射到 Acegi 過濾器鏈代理。 Acegi 將對映射到 Acegi 過濾器鏈代理上的所有 URL 應用安全性。
應用程序上下文加載程序位於 <listener> 標記中,它將加載 Spring 的 IOC 框架。
部署並運行應用程序
部署並運行樣例應用程序非常的簡單。只需要完成兩件事情:
1.將 acegisample.war 文件從本教程下載的源代碼中復制到安裝 Tomcat 的 webapps 目錄中。
2.從 Acegi Security System 主頁 下載並解壓縮 acegi-security- 1.0.3.zip。您將找到一個名為 acegi-security-sample-tutorial.war 的樣例 應用程序。解壓縮 war 文件並提取其 WEB-INF/lib 文件夾中所有的 jar 文件 。將所有的 JAR 文件從 WEB-INF/lib 文件夾中復制到 theacegisample.war 應 用程序的 WEB-INF/lib 文件夾。
現在,您已經為運行樣例應用程序做好准備 了。啟動 Tomcat 並將浏覽器指向 http://localhost:8080/acegisample/。
您將看到 圖 4 所示的歡迎頁面,但是此時顯示的頁面是真實的。請繼續運 行程序,並查看在嘗試訪問歡迎頁面顯示的不同鏈接時會發生什麼狀況。
結束語
在使用 Acegi 保護 Java 應用程序 系列的第一篇文章中,您了解了 Acegi 安全系統的特性、架構和組件,學習了大量有關 Acegi 安全過濾器的知識,這 些過濾器被集成到 Acegi 的安全框架中。您還學習了如何使用 XML 配置文件配 置組件依賴關系,並查看了 Acegi 的安全過濾器在樣例程序中工作的情形,該 應用程序可以實現基於 URL 的安全性。
本文所述的安全技術非常的簡單,所以 Acegi 使用這些技術實現安全性。本 系列的下一文章將開始介紹 Acegi 的一些較為高級的應用,首先是編寫訪問控 制協議並將其存儲到目錄服務中。您還將了解到如何配置 Acegi,使它與目錄服 務交互,從而實現您的訪問控制策略。
本文配套源碼