<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    狼愛上貍

    我胡漢三又回來了

    acegi,IBM的Acegi Security System(4)

    2008 年 3 月 20 日

    Bilal Siddiqui 將繼續在他的 系列文章 中展示如何使用 Acegi 保護 Java™Server Faces (JSF) 應用程序。配置 JSF 和 Acegi,讓它們在 servlet 容器中協作,探索 JSF 和 Acegi 組件如何彼此協作。

    系列 的前 3 部分討論了如何使用 Acegi Security System 保護 Java 企業應用程序:

    • 第 1 部分 解釋了如何使用 Acegi 的內置過濾器實現一個簡單的基于 URL 的安全系統。
    • 第 2 部分 展示了如何編寫訪問控制策略、將其存儲在 LDAP 目錄服務器中,以及配置 Acegi 與 LDAP 服務器交互,從而實現訪問控制策略。
    • 第 3 部分 展示了如何在企業應用程序中使用 Acegi 保護對 Java 類實例的訪問。

    第 4 部分將討論如何使用 Acegi 保護在 servlet 容器中運行的 JavaServer Faces (JSF) 應用程序。本文首先解釋 Acegi 針對此目標提供的特性,并澄清一些關于使用 Acegi 和 JSF 的常見誤解。然后提供一個簡單的 web.xml 文件,可以用來部署 Acegi,從而保護 JSF 應用程序。然后深入探討 Acegi 和 JSF 組件,了解在部署 web.xml 文件和用戶訪問 JSF 應用程序時所發生的事件。本文最后提供了一個由 Acegi 保護的示例 JSF 應用程序。

    無需編寫 Java 代碼即可添加安全性

    回顧一下本系列的第一個示例 Acegi 應用程序(請參閱 第 1 部分 中的 “一個簡單 Acegi 應用程序” 一節)。該應用程序使用 Acegi 提供了以下安全特性:

    • 當一個未經驗證的用戶試圖訪問受保護的資源時,提供一個登錄頁面。
    • 將授權用戶直接重定向到所需的受保護資源。
    • 如果用戶未被授權訪問受保護資源,提供一個訪問拒絕頁面。

    回想一下,您無需編寫任何 Java 代碼就能獲得這些特性。只需要對 Acegi 進行配置。同樣,在 JSF 應用程序中,無需編寫任何 Java 代碼,也應該能夠從 Acegi 實現相同的特性。

    澄清誤解

    其他一些作者似乎認為將 Acegi 與 JSF 集成需要 JSF 應用程序提供登錄頁面(參見 參考資料)。這種觀點并不正確。在需要時提供登錄頁面,這是 Acegi 的職責。確保登錄頁面在安全會話期間只出現一次,這也是 Acegi 的職責。然后,經過身份驗證和授權的用戶可以訪問一個受保護資源,無需重復執行登錄過程。

    如果使用 JSF 提供登錄頁面,將會發生兩個主要的問題:

    • 當需要時,沒有利用 Acegi 的功能提供登錄頁面。必須編寫 Java 代碼實現所有邏輯來提供登錄頁面。

    • 至少需要編寫一些 Java 代碼將用戶憑證(用戶名和密碼)從 JSF 的登錄頁面移交到 Acegi。

    Acegi 的目的是避免編寫 Java 安全代碼。如果使用 JSF 提供登錄頁面,則沒有實現這一用途,并且會引發一系列其他 JSF-Acegi 集成問題,所有這些問題都源于 “Acegi 是用來提供可配置安全性” 這一事實。如果試圖使用 JSF 來完成 Acegi 的工作,將會遇到麻煩。

    本文余下部分將解釋并演示獨立于 Acegi 的 JSF 應用程序開發,并在稍后配置 Acegi 以保護 JSF 應用程序 — 無需編寫任何 Java 代碼。首先看一下 web.xml 文件,可以部署該文件保護 JSF 應用程序。





    回頁首


    部署 Acegi 保護 JSF 應用程序

    清單 1 展示了一個 web.xml 文件(通常稱為部署描述符),可以使用這個文件部署 Acegi,從而保護運行在 servlet 容器(比如 Apache Tomcat)中的 JSF 應用程序:


    清單 1. 用于部署 Acegi 和 servlet 容器中的 JSF 的 web.xml 文件
                            <?xml version="1.0"?>
                <!DOCTYPE web-app PUBLIC
                "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
                "http://java.sun.com/dtd/web-app_2_3.dtd">
                <web-app>
                <context-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>/WEB-INF/acegi-config.xml</param-value>
                </context-param>
                <context-param>
                <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
                <param-value>server</param-value>
                </context-param>
                <context-param>
                <param-name>javax.faces.CONFIG_FILES</param-name>
                <param-value>/WEB-INF/faces-config.xml</param-value>
                </context-param>
                <listener>
                <listener-class>
                org.springframework.web.context.ContextLoaderListener
                </listener-class>
                </listener>
                <listener>
                <listener-class>
                com.sun.faces.config.ConfigureListener
                </listener-class>
                </listener>
                <!-- Faces Servlet -->
                <servlet>
                <servlet-name>Faces Servlet</servlet-name>
                <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
                <load-on-startup> 1 </load-on-startup>
                </servlet>
                <!-- Faces Servlet Mapping -->
                <servlet-mapping>
                <servlet-name>Faces Servlet</servlet-name>
                <url-pattern>*.faces</url-pattern>
                </servlet-mapping>
                <!-- Acegi filter configuration -->
                <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>
                <!-- Acegi Filter Mapping -->
                <filter-mapping>
                <filter-name>Acegi Filter Chain Proxy</filter-name>
                <url-pattern>/*</url-pattern>
                </filter-mapping>
                </web-app>
                

    注意,清單 1 包含以下標記:

    • 3 個 <context-param> 標記
    • 2 個 <listener> 標記
    • 1 個 <filter> 標記
    • 1 個 <servlet> 標記
    • 1 個 <servlet-mapping> 標記
    • 1 個 <filter-mapping> 標記

    閱讀該文件,了解每個標記在 JSF-Acegi 應用程序中的用途。

    向 Acegi 和 JSF 提供上下文參數

    清單 1 中的每個 <context-param> 標記定義一個參數,供 Acegi 或 JSF 在啟動或執行期間使用。第一個參數 — contextConfigLocation — 定義 Acegi 的 XML 配置文件的位置。

    JSF 需要 javax.faces.STATE_SAVING_METHODjavax.faces.CONFIG_FILES 參數。javax.faces.STATE_SAVING_METHOD 參數指定希望在客戶機還是服務器上存儲 JSF 頁面-視圖狀態。Sun 的參考實現的默認行為是將 JSF 視圖存儲在服務器上。

    javax.faces.CONFIG_FILES 參數指定 JSF 需要的配置文件的位置。JSF 配置文件的詳細信息不屬于本文討論的范圍(參見 參考資料,獲取涉及該主題的資源鏈接)。

    為 Acegi 和 JSF 配置偵聽器

    現在看一下 清單 1 中的 2 個 <listener> 標記。<listener> 標記定義偵聽器類,偵聽器類偵聽并處理 JSP 或 servlet 應用程序啟動和執行期間發生的事件。例如:

    • 啟動 JSP 或 servlet 應用程序時,servlet 容器創建一個新的 servlet 上下文。每當 JSP 或 servlet 應用程序啟動時,就會觸發此事件。

    • servlet 容器創建一個新的 servlet 請求對象。每當容器從客戶機收到一個 HTTP 請求時,此事件就會發生。

    • 建立一個新的 HTTP 會話。當請求客戶機建立一個與 servlet 容器的會話時,此事件就會發生。

    • 一個新屬性被添加到 servlet 上下文、servlet 請求和 HTTP 會話對象。

    • servlet 上下文、servlet 請求或 HTTP 會話對象的一個現有屬性被修改或刪除。

    <listener> 標記就像一種可擴展性機制,允許在 servlet 容器內部運行的應用程序協同某些事件進行處理。servlet 規范定義了偵聽器類為處理事件而實現的一些接口。

    例如,Spring Framework 實現一個 javax.servlet.ServletContextListener servlet 接口。實現此接口的 spring 類是 org.springframework.web.context.ContextLoaderListener。注意,這是 清單 1 的第一個 <listener> 標記中的偵聽器類。

    類似地,JSF 實現一個 com.sun.faces.config.ConfigureListener 類,該類實現一些事件-偵聽接口。可以在 清單 1 的第二個 <listener> 標記中找到 ConfigureListener 類。

    本文稍后將解釋不同的事件-偵聽器接口,以及 Acegi 和 JSF 事件-偵聽器類內部執行的處理(請參閱 “啟動 JSF-Acegi 應用程序” 和 “處理對受 Acegi 保護的 JSF 頁面的請求”)。

    配置和映射 servlet 過濾器

    現在看一下 清單 1 中的 <filter> 標記。在請求的 servlet 處理傳入的請求之前,servlet 應用程序使用過濾器對其進行預處理。在請求執行之前,Acegi 使用 servlet 過濾器對用戶進行身份驗證。

    請注意 清單 1 中的 <filter> 標記,它的 <filter-class> 子標記指定一個 org.acegisecurity.util.FilterToBeanProxy 類。FilterToBeanProxy 類是 Acegi 的一部分。此類實現一個 javax.servlet.Filter 接口,該接口是 servlet 應用程序的一部分。javax.servlet.Filter 接口有一個 doFilter() 方法,servlet 容器在收到請求時調用該方法。

    還需注意,清單 1<filter> 標記有另一個子標記 <init-param><init-param> 標記指定實例化 FilterToBeanProxy 類所需的參數。可以從 清單 1 中看出,FilterToBeanProxy 類只需要一個參數,該參數是 FilterChainProxy 類的一個對象。FilterChainProxy 類表示 第 1 部分 1 中討論的整個 Acegi 過濾器鏈(請參閱 “安全過濾器” 小節)。FilterToBeanProxy 類的 doFilter() 方法使用 FilterChainProxy 類執行 Acegi 的安全過濾器鏈。

    清單 1 中的 <filter-mapping> 標記指定調用 Acegi 的 FilterToBeanProxy 的請求 URL。我已經將所有的 JSF 頁面映射到 Acegi 的 FilterToBeanProxy。這意味著只要用戶試圖訪問 JSF 頁面,FilterChainProxy doFilter() 方法就會自動獲得控制權。

    配置 JSF servlet

    web.xml 文件中的 <servlet> 標記指定希望從特定 URl 調用的 servlet(在本例中是一個 JSF servlet)。<servlet-mapping> 標記定義該 URL。幾乎所有的 JSP 或 servlet 應用程序都包含這兩個標記,所以無需再作討論(參見 參考資料,獲取討論 servlet 編程的資源鏈接)。

    現在,您已經看到,web.xml 文件要部署 Acegi 以保護 JSF 應用程序所需的所有標記。您已經了解了偵聽器、過濾器和 servlet 如何相互協作。從這里的討論中可以看出,如果在 servlet 容器中部署 清單 1 中的 web.xml 文件,Acegi 和 JSF 都試圖在兩種情形下進行一些處理:

    • 當啟動應用程序時
    • 當應用程序收到對 JSF 頁面的請求時

    接下來的兩節解釋每種情況中發生的一系列事件。





    回頁首


    啟動 JSF-Acegi 應用程序

    圖 1 展示了在 JSF-Acegi 應用程序啟動時發生的事件順序:


    圖 1. JSF-Acegi 應用程序啟動時發生的事件順序
    JSF-Acegi 應用程序啟動時發生的事件順序


    詳細來講,圖 1 顯示的事件順序如下所示:

    1. servlet 容器實例化在 web.xml 文件中配置的所有偵聽器。

    2. servlet 容器將 Acegi 的 ContextLoaderListener 注冊為一個偵聽器類,該類實現 javax.servlet.ServletContextListener接口。ServletContextListener 接口包含兩個重要方法:contextInitialized()contextDestroyed()
      • contextInitialized() 方法在初始化 servlet 上下文時獲得控制權。
      • 類似地,當應用程序退出時,contextDestroyed() 方法會被調用,并消除 servlet 上下文。

    3. servlet 容器將 JSF 的 ConfigureListener 注冊為另一個偵聽器。JSF 的 ConfigureListener 實現許多偵聽器接口,比如 ServletContextListenerServletContextAttributeListenerServletRequestListener,以及 ServletRequestAttributeListener。您已經看到了 ServletContextListener 接口的方法。余下的接口是:
      • ServletContextAttributeListener,它包含 3 種方法:attributeAdded() attributeRemoved()attributeReplaced()。這 3 種方法分別在某個屬性被添加到 servlet 上下文、被從 servlet 上下文刪除、被新屬性取代時獲得控制權。attributeReplaced() 方法在 處理對受 Acegi 保護的 JSF 頁面的請求 小節的第 8 步中獲得控制權。

      • ServletRequestListener 中包含的方法在創建或刪除新的 servlet 請求對象時獲得控制權。servlet 請求方法表示并包裝來自用戶的請求。

      • ServletRequestAttributeListener 中包含的方法在添加、刪除或替換某個請求對象的屬性時獲得控制權。本文稍后將討論在 處理對受 Acegi 保護的 JSF 頁面的請求 小節的第 3 步中創建一個新的請求對象時,JSF 的 ConfigureListener 執行的處理。

    4. servlet 容器創建一個 servlet 上下文對象,該對象封裝應用程序資源(比如 JSP 頁面、Java 類和應用程序初始化參數),并允許整個應用程序訪問這些資源。JSF-Acegi 應用程序的所有其他組件(偵聽器、過濾器,以及 servlet)在 servlet 上下文對象中以屬性的形式存儲與應用程序資源相關的信息。

    5. servlet 容器通知 Acegi 的 ContextLoaderListener,servlet 上下文是通過調用 ContextLoaderListenercontextInitializated() 方法初始化的。

    6. contextInitialized() 方法解析 Acegi 的配置文件,為 JSF-Acegi 應用程序創建 Web 應用程序上下文,以及實例化所有的安全過濾器和在 Acegi 配置文件中配置的 Jave bean。在以后 JSF 應用程序收到來自客戶機的請求時,這些過濾器對象將會用于身份驗證和授權(參閱 第 3 部分 中關于 Web 應用程序上下文創建的討論和圖 1)。

    7. servlet 容器通知 JSF 的 ConfigureListener,servlet 上下文是通過調用 contextInitialized() 方法初始化的。

    8. contextInitialized() 方法檢查在 JSF 配置文件中配置的所有 JSF 托管 bean,確保 Java 類與每個 bean 并存。

    9. servlet 容器檢查 web.xml 文件中任何配置的過濾器。例如,清單 1 中的 web.xml 文件包含一個 Acegi 過濾器 FilterToBeanProxy,servlet 容器將其實例化、初始化并注冊為一個過濾器。Acegi 現在可以對傳入的請求執行身份驗證和授權了。

    10. servlet 容器實例化 faces servlet,后者開始偵聽從用戶傳入的請求。

    下一節解釋 JSF-Acegi 應用程序收到來自用戶的請求時發生的一系列事件。





    回頁首


    處理對受 Acegi 保護的 JSF 頁面的請求

    您已經了解了如何配置 Acegi 保護 JSF 應用程序。也看到了當啟動 JSF-Acegi 應用程序時發生的一系列事件。本節描述當用戶發送一個對受 Acegi 保護的 JSF 頁面的請求時,JSF 和 Acegi 組件如何在 servlet 容器的框架中運行。

    圖 2 展示了當客戶機發送一個對受 Acegi 保護的 JSF 頁面的請求時,發生的事件順序:


    圖 2. JSF 和 Acegi 協作提供 JSF 頁面
    JSF 和 Acegi 協作提供 JSF 頁面


    詳細來講,圖 2 展示的事件順序如下所示:

    1. servlet 容器創建一個表示用戶請求的 servlet 請求對象。

    2. 回想一下 啟動 JSF-Acegi 應用程序 小節中的第 3 步,JSF 的 ConfigureListener 實現 ServletRequestListener 接口。這意味著 ConfigureListener 偵聽與創建和刪除 servlet 請求對象相關的事件。因此,servlet 容器調用 ConfigureListener 類的 requestInitialized() 方法。

    3. requestInitialized() 方法準備執行請求的 JSF 生命周期。準備過程包括檢查請求的 faces 上下文是否存在。faces 上下文封裝與應用程序資源相關的信息。faces servlet 執行 JSF 生命周期時需要這些信息。如果此請求是新會話的第一個請求,就會缺少 faces 上下文。在這種情況下,requestInitialized() 方法創建一個新的 faces 上下文。

    4. servlet 容器檢查用戶的請求是否帶有任何狀態信息。如果 servlet 容器未找到狀態信息,它會假設該請求是新會話的第一個請求,并為用戶創建一個 HTTP 會話對象。如果 servlet 容器發現該請求包含某種狀態信息(比如一個 cookie 或 URL 中的某種狀態信息),它就會根據保存的會話信息恢復用戶以前的會話。

    5. servlet 容器把請求 URL 與一個 URL 模式進行匹配,這個 URL 模式包含在配置描述符中的 <filter-mapping> 標記的 <url-pattern> 子標記中。如果請求 URL 與這個 URL 模式匹配,servlet 容器調用 Acegi 的 FilterToBeanProxyFilterToBeanProxy 已在 圖 1 的第 9 步中被注冊為一個 servlet 過濾器。

    6. Acegi 的 FilterToBeanProxy 使用 FilterChainProxy 類執行 Acegi 的完整的安全過濾器鏈。Acegi 的過濾器自動檢查第 4 步中創建的 HTTP 會話對象,以查看請求客戶機是否已被驗證。如果 Acegi 發現用戶未被驗證,它提供一個登錄頁面。否則,它就直接執行 第 2 部分 的 “配置攔截器” 一節中描述的授權過程。

    7. Acegi 使用經過驗證的用戶的會話信息更新 servlet 上下文。

    8. servlet 容器通知 JSF 的 ConfigureListenerattributeReplaced() 方法,servlet 上下文已被更新。ConfigureListener 檢查是否有任何 JSF bean 被更改。如果發現任何更改,它相應地更新 faces 上下文。但是,在本例中,在身份驗證過程中 Acegi 沒有更改任何 JSF 托管 bean,因此在此調用期間 ConfigureListener 不進行任何處理。

    9. 如果授權過程成功,控制權被轉移到 faces servlet,它執行 JSF 生命周期并向用戶發回一個響應。

    現在,您了解了 JSF 和 Acegi 如何協作提供 JSF 請求,接下來看一下完成后的 JSF 和 Acegi。





    回頁首


    示例 JSF-Acegi 應用程序

    本文的下載部分(參見 下載)包含一個示例 JSF-Acegi 應用程序 JSFAcegiSample,演示了 Acegi 與 JSF 的簡單集成。示例應用程序使用 清單 1 中的 web.xml。

    要部署示例應用程序,執行 第 1 部分 的 “部署并運行應用程序” 一節中的兩個步驟。還需要從 Sun 的 JSF 站點(參見 參考資料)下載并解壓 jsf-1_1_01.zip。將 jsf-1.1.X.zip 中的所有文件復制到 JSFAcegiSample 應用程序的 WEB-INF/lib 文件夾中。

    從瀏覽器訪問 http://localhost:8080/JSFAcegiSample,可以調用示例應用程序。JSFAcegiSample 應用程序顯示一個索引頁面和一個登錄頁面,索引頁面中包含受保護資源的鏈接。所有受保護頁面都是使用 JSF 組件開發的,而 Acegi 提供登錄頁面并執行身份驗證和授權。





    結束語

    在本文中,了解了如何配置 Acegi 以保護 JSF 應用程序。還詳細了解了 JSF 和 Acegi 組件如何在一個 servlet 容器的框架中協作。最后,嘗試運行了一個示例 JSF-Acegi 應用程序。

    關于實現 JSF 應用程序的 Acegi 安全性,還涉及到更多內容。本系列的下一篇文章將演示如何使用 Acegi 保護對 JSF 的托管 bean 的訪問。


    來自: http://www.cnblogs.com/amboyna/archive/2008/03/25/1122089.html

    posted on 2008-05-08 18:50 狼愛上貍 閱讀(294) 評論(0)  編輯  收藏 所屬分類: Acegi

    主站蜘蛛池模板: 久久久久久国产精品免费免费男同| 中文字幕亚洲专区| 午夜精品射精入后重之免费观看| 亚洲gay片在线gv网站| 午夜亚洲国产理论秋霞| 亚洲情侣偷拍精品| 永久黄网站色视频免费观看| 最近中文字幕国语免费完整| 国产无遮挡又黄又爽免费网站| 337p日本欧洲亚洲大胆人人| 亚洲中文无码永久免| 亚洲三级视频在线| 久久久久亚洲Av无码专| 亚洲精品乱码久久久久久| 亚洲国产精品自产在线播放| 日本v片免费一区二区三区| 免费无码A片一区二三区| 91久久精品国产免费直播| 暖暖日本免费中文字幕| 中文字幕不卡免费视频| 人成电影网在线观看免费| 美女被免费视频网站| 国产亚洲美女精品久久久久| 亚洲国产av玩弄放荡人妇| 亚洲高清视频在线| 亚洲成A人片在线播放器| 亚洲高清一区二区三区| 亚洲真人无码永久在线观看| 亚洲综合无码一区二区痴汉| 亚洲香蕉久久一区二区| 亚洲国产超清无码专区| 亚洲黄色在线视频| 亚洲人成网网址在线看| 国产成+人+综合+亚洲专| 丁香婷婷亚洲六月综合色| 亚洲欧洲尹人香蕉综合| 亚洲国产成人精品青青草原| 亚洲三级在线播放| 亚洲国产成人久久一区二区三区| 亚洲AV成人无码网站| 粉色视频成年免费人15次|