實現基於角色的授權

CloudSpace發表於2009-07-30

Scott Crowther, 軟體工程師, IBM
Abe Guerra, 軟體工程師, IBM
Tamer Nassar, 軟體工程師, IBM

2009 年 6 月 29 日

瞭解如何通過使用者身份驗證實現一個動態的使用者介面。身份驗證通常是對具有多組使用者的應用程式的一種要求。每個使用者組都需要訪問某些應用程式功能,而這部分功能對於另一個使用者組可能需要進行限制。身份驗證機制必須要驗證使用者憑證並基於使用者憑證控制對應用程式功能的訪問。本文展示瞭如何使用 OpenLDAP 和 Tomcat 實現基本的身份驗證機制。本文將 OpenLDAP 和 Tomcat 實現與 OpenLDAP 和 WASCE 實現做了對比。最後,還通過例子展示瞭如何使用 Java™ 程式碼和 JSTL 實現這個動態 UI。

簡介

Web 應用程式通常需要控制特定的一組使用者所能使用的功能性。比如,一個應用程式可能會允許一組專業使用者嚮應用伺服器上傳資料檔案。但是,此應用程式需要防止一般的使用者也這麼做。

控制對應用程式功能的訪問是一個分為兩個步驟的過程。首先,使用身份驗證機制來辨識當前使用者。其次,使用授權機制來控制對應用程式功能的訪問。此過程的實現可能會涉及到應用程式 Web 頁面的多個副本,其中每組使用者分別具有此 Web 頁面的一個相關副本。本文建議並使用了另外一個實現,這個實現的目的是用 Web 頁面的一個副本來通過 Java 和 JSTL 動態呈現適當的功能性。

實現授權的技術很多。考慮到應用程式的複雜性,本文中的實現使用了一個應用伺服器。尤其是,我們使用了 Tomcat 6 和 WebSphere Application Server Community Edition 2.1 (WASCE)。之所以採用 WASCE 實現,是考慮到與 Apache Geronimo 的整合及其相關的 J2EE 平臺。

本文的實現使用了 Lightweight Directory Access Protocol (LDAP)。LDAP 實現提供了一種管理應用程式使用者所需的健壯機制。有若干個 LDAP 伺服器可供我們使用。我們所需要的 LDAP 伺服器應該是健壯、穩定和開源的。根據這些條件,我們做了一番研究,結果,OpenLDAP 成為了我們的最佳之選。

開發環境

本文針對的是一個基於 Java 的 Web 應用程式。我們使用了 Java 5、JSF 1.2 和 JSTL 1.2。我們的 IDE 是帶 Web Tools Platform. (WTP) 的 Eclipse Ganymede 發行版(相關下載連結,請參見 參考資料)。

安裝了 Java 和 Eclipse 之後,就可以開始設定開發環境了。首先,需要通過如下步驟建立所需的專案庫:

  • 從選單欄單擊 Windows
  • 選擇 Preferences
  • 在 Preferences 視窗中雙擊 Web
  • 雙擊 JavaServer Faces Tools(在 Web 下)。
  • 選擇 Libraries(在 JavaServer Faces 下)。
  • 單擊 New 以新增下述三個 jar 檔案:
    • jstl-1.2.jar
    • jsf-api.jar
    • jsf-impl.jar

這時的 Preferences 視窗應該類似圖 1。


圖 1. Preferences
做出上述選擇後的 Preferences 視窗

其次,需要通過如下步驟建立一個新的 Eclipse 專案:

  • 從選單欄單擊 File
  • 懸停於下拉選單內的 New
  • 從第二個下拉選單中選擇 Dynamic Web Project(如果 Dynamic Web Project 沒有列出,可能需要通過 Other 選項找到該選項)。





回頁首


使用 Tomcat 6

由於進行的是 Tomcat 6 和 WASCE 部署,因此我們將需要在此處分別處理不同的伺服器。建立此專案的第一步是提供一個名字、目標執行時、模組版本和配置。它應類似圖 2 所示(基於這種情況下的設定和 Tomcat)。


圖 2. New Dynamic Web Project
New dynamic Web project 螢幕的快照。專案名稱是 RoleBasedNavTomcat6。專案內容是 Use default。目標執行時是 Apache Tomcat v6.0。Dynamic Web 模組版本是:2.5。配置:javaServer Faces v1.2 Project。配置一個 Dynamic Web 應用程式來使用 JSF v1.2。

第二個步驟要求配置 Web 模組設定。在這個步驟可以包括預設設定。第三個步驟要求定義專案的 JSF Capabilities,類似於圖 3。


圖 3. JSF Capabilities
 JSF Capabilities 視窗的螢幕快照。SUN-RI-1.2 預設選中。元件庫: JSTL。JSF 配置檔案:/WEB-INF/faces-config.xml。JSF Servelt 名稱: Faces Servlet。JSF Servlet 類名:javax.faces.webapp.FacesServlet。URL 對映模式:/faces/.




回頁首


安全性

現在,讓我們開始定義安全性。需要定義 Web 應用程式的安全約束。我們將定義這樣一種約束,這種約束將針對未經身份驗證的使用者保護 /WebContent/private 內的所有內容(我們將使用 UI 處理角色)。要建立這個約束,需要將清單 1 中所示程式碼新增到 /WebContent/WEB-INF/web.xml:


清單 1. web.xml 的示例程式碼


 
  
   Areas with authentication required
  
  /faces/private/* 
 
  
    * 
  
 
   NONE 
 

           

接下來,需要定義一個登入機制。我們將定義基於表單的身份驗證,並定義此表單的位置。將清單 2 中的程式碼新增到 web.xml:


清單 2. (接清單 1)web.xml 的示例程式碼

        

 FORM
 LDAP
 
  /public/login.html
  /public/loginError.html
 

            

我們需要對 web.xml 做的最後一個更新針對的是安全性角色。不過,由於我們通過 JSTL 處理角色,因此我們可以通過新增清單 3 中的程式碼來為所有角色定義約束。


清單 3. (接清單 2)web.xml 程式碼示例

        

 Authenticated Users
 *



為應用程式定義了安全性之後,還需要將其與一個用來管理 Web 應用程式使用者的 LDAP 解決方案進行連線。可以在 /WebContent/META-INF/context.xml 中定義 LDAP 伺服器。這個檔案類似於清單 4。


清單 4. context.xml



   

           





回頁首


使用 WASCE

現在,我們要用 WASCE 建立這個基於角色的導航專案。在接下來的步驟中,我們將展示如何建立並配置這個專案以及如何在 WASCE 中設定 Security LDAP。

依照以下步驟建立一個新的專案:

  • 單擊選單欄中的 File
  • 選擇 Dynamic Web Project
  • 鍵入專案名稱:RolesBasedNavWASCE
  • 選擇 IBM WASCE 作為執行時。
  • 在 Dynamic Web 模組下,選擇 Version 2.5。
  • 為配置欄位選擇 JavaServer Faces。


圖 4. 新建動態 Web 專案
新建動態 web 專案的螢幕快照,顯示了上面所述的選項。

  • 單擊 Modify 並新增 WASCE Deployment


圖 5. Project Facets
Project facets 螢幕的快照。選中 Dynamic web 模組、Java、Java Server Faces 和 WASCE 部署。

定義專案的 JSF 功能。請參照下面內容設定這個 JSF:


圖 6. JSF
JSF 庫的螢幕快照,顯示瞭如下內容:Server supplied JSF implementation 選中。元件庫:JSTL 和 SUN-RU-1.2。JSF 配置檔案:/WEB-INF/faces-config.xml。JSF Servlet 名稱:Faces Servlet。JSF Servlet 類名:javax.faces.webapp.FacesServlet。URL 對映模式:/faces/.

在 WASCE 中設定 Security LDAP

下面介紹如何配置 WASCE 以連線到 LDAP。LDAP 可以安裝在同一個伺服器上,也可以安裝在不同的伺服器上。只要指定了正確的連線 URL,WASCE 就能連線上它。

  • 訪問 WASCE admin 控制檯。進入 http://SERVERNAME:8080/console
  • 以使用者名稱/密碼 system/manager 登入。
  • 單擊 Security Realms


圖 7. 安全性
安全域的螢幕快照

  • 為安全域鍵入名稱:ldap-realm,並選擇 LDAP Realm 作為 Realm Type。
  • 單擊 Next


圖 8. 安全域
進行了上述選擇後安全域的第二個螢幕快照

安全域

需要在 Security Realm 頁面中輸入 LDAP 資訊以使 WASCE 可以與 LDAP 通訊。以下是基於我們的 LDAP 設定而需要輸入的欄位值。

  • Initial Context Factory:com.sun.jndi.ldap.LdapCtxFactory
  • Connection URL:"it should point to the LDAP server"
  • Connect Username:cn=ldaproot,dc=tnc,dc=org
  • Connect Password:xxxxxxx
  • Confirm password:xxxxxxx
  • Connect Protocol:"LEAVE IT BLANK"
  • Authentication:simple
  • User Base:ou=people,dc=tnc,dc=org
  • User Search Matching:uid={0}
  • User Search Subtree:false
  • Role Base:ou=people,dc=tnc,dc=org
  • Role Name:cn
  • Role User Search String:(objectClass={0})
  • Role Search Subtree:false

請注意:這些值可能會因您的 LDAP 設定的不同而有變化。

  • 單擊 Next
  • 要測試 LDAP 連線,需要為所建立的 LDAP 使用者輸入一個使用者名稱/密碼。
  • 測試成功後,單擊 Deploy Realm

要完成安全性配置,需要定義一個用來保護 /WebContent/private 中所有內容的約束。要建立這個約束,可以將下面的內容新增到 web.xml:


清單 5. web.xml 中的安全性約束


  FORM
  Not required for FORM. auth
  
    /faces/public/login.jps
    /faces/public/loginerror.jsp
  


  Authenticated users
  *


  
    Areas with authentication required
    /faces/private/*
    GET
    POST
  
  
    *
  


另外,您還需要依照清單 6 來將這個安全域新增到 geronimo-web.xml。


清單 6. geronimo-web.xml

ldap-realm
   
      
         
         
         
      
   
    

這個專案和檔案結構與 Tomcat 專案一樣,其主要區別在於可以充分利用 WASCE 來進行開放 LDAP 的身份驗證。

使用 WASCE 的優點


圖 9. WASCE
WASCe 和 Tomcat 的對比圖。此圖所描述的資訊列出如下。

比起 Tomcat,用 WASCE 有幾個優點:

  • WASCE 支援完整的 J2EE 堆疊,它包括:一個 Servlet 容器、一個 EJB 容器、一個訊息提供者(JMS)和一個 Java Connector(JCA)容器。
  • 像 Security 和 Authentication、Web Services、JMS 等服務均由 Geronimo Plug-in Kernel 提供。
  • 支援 EJB 與 JPA。
  • 額外的外掛也可被應用於 Kernel 並在應用程式程式碼內訪問,而不是嵌入在應用程式程式碼中。
  • 群集提供了更好的可靠性及效能。
  • 事務資料庫(Apache Derby)被包括在內。
  • 集中化的配置和控制
  • 執行時定製
  • 集中化使用者管理
  • Eclipse 外掛允許部署和除錯(甚至使用遠端方式)。
  • 有關於遷移的文章,可幫助從 Tomcat/JBoss 遷移到 WASCE。
  • 有 IBM 支援。





回頁首


使用者介面

這個應用程式頁面將存在於兩個目錄中。需要安全性的專用頁面存在於 /WebContent/private 中。無安全性要求的公共頁面存在於 /WebContent/public 中。

這個公共目錄包括不要求身份驗證的 html 頁面,其中包括登入頁面及錯誤頁面。依照以下步驟來建立登入頁面:

  • 右鍵單擊 public directory
  • 滑鼠懸停於選單內的 New 上。
  • 在第二個選單上單擊 HTML
  • 設定登入名稱並單擊 Finish

使用預設的身份驗證機制,但它要求必須將登入表單的動作定義為 j_security_check,並使用 j_usernamej_password。得到的 html 檔案如清單 7 所示:


清單 7. 登入頁面



Login


   
   
User ID

類似的,在公共目錄中建立另一個 HTML 檔案並將其命名為 loginError.html。這將是當使用者試圖用無效憑證登入時所顯示的頁面。清單 8 顯示了這個頁面:


清單 8. 登入錯誤頁面



Login Error


Your login attempt has failed.


           

您一定還想建立一個類似的頁面來顯示錯誤訊息,當一個使用者請求訪問他或她未被授權的功能時,就會顯示錯誤訊息。這個頁面很簡單,如清單 9 所示。


清單 9. 身份驗證錯誤頁面



Insert title here


You are not authorized to access this functionality.


           

在這個示例中,我們將使用一個簡單的主頁,它將模擬到應用程式功能的連結。我們還將建立 .jsp 頁面,它將模擬應用程式中的不同型別的功能。所有這些檔案都要被放在受保護的區域中(/WebContent/private)。這個主頁將使用清單 10 中匯入的標記庫:


清單 10. 標記庫匯入



           

這個 .jsp 頁面還使用了一個資源包以使內容可以被外部化:


這個 .jsp 頁面是靠後端 Java 程式碼來進行使用者身份驗證的。一旦使用者通過針對 LDAP 目錄的身份驗證,它們的憑證將通過 Java beans 持久化。.jsp 可以如清單 11 所示的那樣引用 bean:


清單 11. Bean 引用



            

在上面的片段中,一個歡迎訊息通過綜合來自資源包(由 'msg' 引用)的內容和來自這個 Java bean(由 userBean 引用)的姓名而被顯示出來。在這時,我們可以根據使用者的角色開始過濾。使用者的角色也包含在 Java bean 中。這讓 .jsp 頁面可以檢查使用者的角色並採取恰當的動作。例如,您可以控制基於當前的使用者角色而被顯示出來的功能連結。


清單 12. 角色驗證


   
Admin Functionality

清單 12 中的程式碼片段檢查當前使用者的角色是否是 ‘Admin’。如果是,它將顯示 admin 功能的連結。如果不是,則不顯示這個連結。我們將在這個 .jsp 頁面中增加額外的檢查,以便模擬保護功能頁面免受直接訪問的功能。得到的主頁應類似清單 13:


清單 13. 主頁







Home



   
   
   
   
Casual Functionality
Expert Functionality

Admin Functionality

我們將在專用目錄中建立另外三個 .jsp 頁面,每個頁面針對一種所模擬的功能:casual、expert、admin。如我們前面提到的,我們需要在 .jsp 頁面中做另一個檢查來避免對 .jsp 頁面的直接訪問。可以按清單 14 所示內容來進行這個檢查:


清單 14. 授權


   

            

在上面的程式碼片段中,我們檢查是否有預期的使用者角色。如果這個使用者角色不是我們預期的,就會把使用者重定向到一個錯誤頁面。對於 casual 功能我們則不需要做這種檢查,因為它對所有通過驗證的使用者都是開放的。

casual 功能頁面應類似清單 15:


清單 15. Casual 使用者功能






Insert title here


Casual user functionality is accessible here.


            

expert 功能頁面如清單 16 所示:


清單 16. expert 使用者功能






Insert title here





   


Expert user functionality is accessible here.


            

admin 功能如清單 17 所示:


清單 17. Admin 使用者功能






Insert title here






Admin user functionality is accessible here.



現在的目錄結構應類似下面的這個導航皮膚:


圖 10. 專案結構
專案結構導航皮膚的螢幕快照。Web 內容資料夾展開。在其下,如下的資料夾也是展開的:META-INF、private、public 和 WEB-INF。

身份驗證及永續性

出於本文的目的考慮,我們將所有後端程式碼放進一個程式包中,我們將這個程式包命名為 com.ibm.test。可以通過以下的步驟來建立這個程式包:

  • 右鍵單擊左側導航皮膚上的 Java Resources: src
  • 選擇 New 然後選擇 Package
  • 在名稱欄位中輸入 com.ibm.test 然後單擊 Finish

我們後面將要使用一個資源包,所以我們先依照下面的步驟來建立一個資源包:

  • 右鍵單擊新建立的程式包。
  • 選擇 New 然後選擇 Other
  • 雙擊新彈出視窗中的 General
  • 選擇 File 然後單擊 Next
  • 在名稱欄位中輸入 messages.properties,然後單擊 Finish

本文中的這個示例僅為歡迎頁面使用了資源包,因此,它只需下面這行程式碼:

 welcome=Welcome 

然而,這個檔案完全可以包括應用程式的所有內容。

應用程式的身份驗證是由一個名為 UserBean 的 Java 類處理的。通過下面的步驟來建立它:

  • 右鍵單擊 com.ibm.test package
  • 選擇 New 然後選擇 Class
  • 在名稱欄位中輸入 UserBean 並單擊 Finish

這個 UserBean 類將使用兩個 Java 設計模式:Data Access Object (DAO) 和 Transfer Object (TO)。DAO 負責訪問來自於 LDAP 目錄的使用者資料。TO 負責儲存這些資料。UserBean 類將針對 home.jsp 的引用進行例項化:


UserBean 類的建構函式需要獲取通過身份驗證的使用者的 ID。記住,我們正在使用的身份驗證機制是 Tomcat 的預設表單身份驗證。從本文的目的出發,我們將用 Tomcat 處理身份驗證,並使用 UserBean 類獲取並持久化通過驗證的使用者的資料。我們可以從 UserBean 類中獲取使用者 ID,見下面程式碼:

ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
           String userID = context.getRemoteUser();

我們現在可以使用通過驗證的使用者的 ID 來從 LDAP 目錄中檢索所有使用者資料。OpenLDAPDAO 類可實現此目的。依照以下步驟建立此類:

  • 右鍵單擊 com.ibm.test package
  • 選擇 New 然後選擇 Class
  • 在名稱欄位中輸入 OpenLDAPDAO 並單擊 Finish

OpenLDAPDAO 類在類變數中包含 LDAP 目錄的細節。其建構函式將會建立一個對 LDAP 目錄的連線。此外,還將包含一個方法,用來檢索特定使用者的屬性。UserBean 類通過 UserTransferObject 類保持使用者資料。這個類是一個使用者資料的容器。本文隨附的歸檔檔案中包含了所有類的一個副本。

這時的 Java 目錄結構應該與圖 11 中的導航皮膚結構相似。


圖 11. 專案 Java 結構
Project Java 結構導航皮膚的螢幕快照。

大功告成了!不妨啟動伺服器並對它做個測試。

如果未通過身份驗證,嘗試訪問主頁時,將會被重定向到登入頁面,如圖 12 所示。


圖 12. 登入頁面
登入頁面的螢幕快照,具有 User ID 和 password 欄位。

作為一個 casual 使用者,登入時將只會列出功能連結中的一個,如圖 13 所示。


圖 13. casual 使用者
一個螢幕快照顯示:Welcome username,以及一個到 Casual 功能的連結

如果使用者想要直接訪問 .jsp 頁面上一個未被授權的功能,就會顯示使用者錯誤訊息,如圖 14 所示。


圖 14. 身份驗證錯誤
錯誤訊息的螢幕快照:您無權訪問此功能。

以 admin 身份登入時,所有功能的連結都會出現,見圖 15。


圖 15. Admin
一個螢幕快照顯示:Welcome 使用者名稱,還有各種功能連結:Causal、Expert 和 Admin




回頁首


結束語

祝賀您!在很短的時間裡,您就已經建立了一個能實現授權的骨架應用程式。您現在可以圍繞著這個骨架,構建一個能夠基於您在 LDAP 目錄中定義的使用者角色控制對功能的訪問的應用程式。您可以在 Tomcat 或 WASCE 上繼續開發您的應用程式,還可以充分利用它的其他功能。這個應用程式骨架還實現了 JSF,本文沒有對此做過多介紹,但它很值得深入研究。

值得研究的另一點是 OpenLDAP。有關設定 OpenLDAP 的內容就可以自成一篇文章了。OpenLDAP Web 站點是一個豐富的資源。第三方軟體可用來協助 LDAP 伺服器的管理。我們發現 Jxplorer 是一個很好的工具。不過,您可能會希望為應用程式實現一個管理部分,這樣,管理員可以通過此應用程式來管理 LDAP 伺服器。通過使用現有的模板加上 JSF,可以很容易地將它構建到這個應用程式骨架中去。


 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/14789789/viewspace-610871/,如需轉載,請註明出處,否則將追究法律責任。

相關文章