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

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

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

    迷途書童

    敏感、勤學、多思
    隨筆 - 77, 文章 - 4, 評論 - 86, 引用 - 0
    數據加載中……

    擴展JAAS實現類實例級授權

    “Java 認證和授權服務”(Java Authentication and Authorization Service,JAAS)是對 Java 2 SDK 的擴展。在 JAAS 下,可以給予用戶或服務特定的許可權來執行 Java 類中的代碼。在本文中,軟件工程師 Carlos Fonseca 向您展示如何為企業擴展 JAAS 框架。向 JAAS 框架添加類實例級授權和特定關系使您能夠構建更動態、更靈活并且伸縮性更好的企業應用程序。請單擊文章頂部或底部的 討論,在 討論論壇與作者和其他讀者分享您對本文的想法。

    大多數 Java 應用程序都需要某種類實例級的訪問控制。例如,基于 Web 的、自我服務的拍賣應用程序的規范可能有下列要求:

    任何已注冊(經過認證)的用戶都可以創建一個拍賣,但只有創建拍賣的用戶才可以修改這個拍賣。

    這意味著任何用戶都可以執行被編寫用來創建 Auction 類實例的代碼,但只有擁有該實例的用戶可以執行用來修改它的代碼。通常情況下,創建 Auction 實例的用戶就是所有者。這被稱為 類實例所有者關系(class instance owner relationship)

    該應用程序的另一個要求可能是:

    任何用戶都可以為拍賣創建一個投標,拍賣的所有者可以接受或拒絕任何投標。

    再一次,任何用戶都可以執行被編寫用來創建 Bid 類實例的代碼,但只有擁有該實例的用戶會被授予修改該實例的許可權。而且, Auction 類實例的所有者必須能夠修改相關的 Bid 類實例中的接受標志。這意味著在 Auction 實例和相應的 Bid 實例之間有一種被稱為 特定關系(special relationship)的關系。

    不幸的是,“Java 認證和授權服務”(JAAS)― 它是 Java 2 平臺的一部分 ― 沒有考慮到類實例級訪問控制或者特定關系。在本文中,我們將擴展 JAAS 框架使其同時包含這兩者。推動這種擴展的動力是允許我們將訪問控制分離到一個通用的框架,該框架使用基于所有權和特定關系的策略。然后管理員可以在應用程序的生命周期內更改這些策略。

    在深入到擴展 JAAS 框架之前,我們將重溫一下 Java 2 平臺的訪問控制機制。我們將討論策略文件和許可權的使用,并討論 SecurityManagerAccessController 之間的關系。

    Java 2 平臺中的訪問控制

    在 Java 2 平臺中,所有的代碼,不管它是本地代碼還是遠程代碼,都可以由策略來控制。 策略(policy)由不同位置上的代碼的一組許可權定義,或者由不同的簽發者定義、或者由這兩者定義。 許可權允許對資源進行訪問;它通過名稱來定義,并且可能與某些操作關聯在一起。

    抽象類 java.security.Policy 被用于表示應用程序的安全性策略。缺省的實現由 sun.security.provider.PolicyFile 提供,在 sun.security.provider.PolicyFile 中,策略被定義在一個文件中。清單 1 是一個典型策略文件示例:


    清單 1. 一個典型的策略文件
    														
    																// Grant these permissions to code loaded from a sample.jar file
    // in the C drive and if it is signed by XYZ
    grant codebase "file:/C:/sample.jar", signedby "XYZ" {
    	// Allow socket actions to any host using port 8080
    	permission java.net.SocketPermission "*:8080", "accept, connect, 
    	  listen, resolve";
    	// Allows file access (read, write, execute, delete) in
    	// the user's home directory.
    	Permission java.io.FilePermission "${user.home}/-", "read, write, 
    	  execute, delete";
    };
    
    														
    												

    SecurityManager 對 AccessController

    在標準 JDK 分發版中,控制代碼源訪問的機制缺省情況下是關閉的。在 Java 2 平臺以前,對代碼源的訪問都是由 SecurityManager 類管理的。 SecurityManager 是由 java.security.manager 系統屬性啟動的,如下所示:

    														
    																java -Djava.security.manager
    
    														
    												

    在 Java 2 平臺中,可以將一個應用程序設置為使用 java.lang.SecurityManager 類或者 java.security.AccessController 類管理敏感的操作。 AccessController 在 Java 2 平臺中是新出現的。為便于向后兼容, SecurityManager 類仍然存在,但把自己的決定提交 AccessController 類裁決。 SecurityManagerAccessController 都使用應用程序的策略文件確定是否允許一個被請求的操作。清單 2 顯示了 AccessController 如何處理 SocketPermission 請求:


    清單 2. 保護敏感操作
    														
    																Public void someMethod() {
    	Permission permission = 
    	  new java.net.SocketPermission("localhost:8080", "connect");
    	AccessController.checkPermission(permission);
    	// Sensitive code starts here
    	Socket s = new Socket("localhost", 8080);
    }
    
    														
    												

    在這個示例中,我們看到 AccessController 檢查應用程序的當前策略實現。如果策略文件中定義的任何許可權暗示了被請求的許可權,該方法將只簡單地返回;否則拋出一個 AccessControlException 異常。在這個示例中,檢查實際上是多余的,因為缺省套接字實現的構造函數也執行相同的檢查。

    在下一部分,我們將更仔細地看一下 AccessController 如何與 java.security.Policy 實現共同合作安全地處理應用程序請求。





    回頁首


    運行中的 AccessController

    AccessController 類典型的 checkPermission(Permission p) 方法調用可能會導致下面的一系列操作:

    1. AccessController 調用 java.security.Policy 類實現的 getPermissions(CodeSource codeSource) 方法。
    2. getPermissions(CodeSource codeSource) 方法返回一個 PermissionCollection 類實例,這個類實例代表一個相同類型許可權的集合。
    3. AccessController 調用 PermissionCollection 類的 implies(Permission p) 方法。
    4. 接下來, PermissionCollection 調用集合中包含的單個 Permission 對象的 implies(Permission p) 方法。如果集合中的當前許可權對象暗示指定的許可權,則這些方法返回 true ,否則返回 false

    現在,讓我們更詳細地看一下這個訪問控制序列中的重要元素。

    PermissionCollection 類

    大多數許可權類類型都有一個相應的 PermissionCollection 類。這樣一個集合的實例可以通過調用 Permission 子類實現定義的 newPermissionCollection() 方法來創建。 java.security.Policy 類實現的 getPermissions() 方法也可以返回 Permissions 類實例 ― PermissionCollection 的一個子類。這個類代表由 PermissionCollection 組織的不同類型許可權對象的一個集合。 Permissions 類的 implies(Permission p) 方法可以調用單個 PermissionCollection 類的 implies(Permission p) 方法。

    CodeSource 和 ProtectionDomain 類

    許可權組合與 CodeSource (被用于驗證簽碼(signed code)的代碼位置和證書)被封裝在 ProtectionDomain 類中。有相同許可權和相同 CodeSource 的類實例被放在相同的域中。帶有相同許可權,但不同 CodeSource 的類被放在不同的域中。一個類只可屬于一個 ProtectionDomain 。要為對象獲取 ProtectionDomain ,請使用 java.lang.Class 類中定義的 getProtectionDomain() 方法。

    許可權

    賦予 CodeSource 許可權并不一定意味著允許所暗示的操作。要使操作成功完成,調用棧中的每個類必須有必需的許可權。換句話說,如果您將 java.io.FilePermission 賦給類 B,而類 B 是由類 A 來調用,那么類 A 必須也有相同的許可權或者暗示 java.io.FilePermission 的許可權。

    在另一方面,調用類可能需要臨時許可權來完成另一個擁有那些許可權的類中的操作。例如,當從另一個位置加載的類訪問本地文件系統時,我們可能不信任它。但是,本地加載的類被授予對某個目錄的讀許可權。這些類可以實現 PrivilegedAction 接口來給予調用類許可權以便完成指定的操作。調用棧的檢查在遇到 PrivilegedAction 實例時停止,有效地將執行指定操作所必需的許可權授予所有的后繼類調用。





    回頁首


    使用 JAAS

    顧名思義,JAAS 由兩個主要組件組成:認證和授權。我們主要關注擴展 JAAS 的授權組件,但開始我們先簡要概述一下 JAAS 認證,緊接著看一下一個簡單的 JAAS 授權操作。

    JAAS 中的用戶認證

    JAAS 通過添加基于 subject 的策略加強了 Java 2 中定義的訪問控制安全性模型。許可權的授予不僅基于 CodeSource ,還基于執行代碼的用戶。顯然,要使這個模型生效,每個用戶都必須經過認證。

    JAAS 的認證機制建立在一組可插登錄模塊的基礎上。JAAS 分發版包含幾個 LoginModule 實現。 LoginModules 可以用于提示用戶輸入用戶標識和密碼。 LoginContext 類使用一個配置文件來確定使用哪個 LoginModule 對用戶進行認證。這個配置可以通過系統屬性 java.security.auth.login.config 指定。一個示例配置是:

    														
    																java -Djava.security.auth.login.config=login.conf
    
    														
    												

    下面是一個登錄配置文件的樣子:

    														
    																Example {
      com.ibm.resource.security.auth.LoginModuleExample required 
        debug=true userFile="users.xml" groupFile="groups.xml";
    };
    
    														
    												

    認識您的主體

    Subject 類被用于封裝一個被認證實體(比如用戶)的憑證。一個 Subject 可能擁有一個被稱為 主體(principal)的身份分組。例如,如果 Subject 是一個用戶,用戶的名字和相關的社會保險號可能是 Subject 的某些身份或主體。主體是與身份名關聯在一起的。

    Principal 實現類及其名稱都是在 JAAS 策略文件中指定的。缺省的 JAAS 實現使用的策略文件與 Java 2 實現的策略文件相似 ― 除了每個授權語句必須與至少一個主體關聯在一起。 javax.security.auth.Policy 抽象類被用于表示 JAAS 安全性策略。它的缺省實現由 com.sun.security.auth.PolicyFile 提供,在 com.sun.security.auth.PolicyFile 中策略定義在一個文件中。清單 3 是 JAAS 策略文件的一個示例:


    清單 3. 示例 JAAS 策略文件
    														
    																// Example grant entry
    grant codeBase "file:/C:/sample.jar", signedby "XYZ",
      principal com.ibm.resource.security.auth.PrincipalExample "admin" {
        // Allow socket actions to any host using port 8080
        permission java.net.SocketPermission 
          "*:8080", "accept, connect, listen, resolve";
        // Allows file access (read, write, execute, delete) in
        // the user's home directory.
        Permission java.io.FilePermission 
          "${user.home}/-", "read, write, execute, delete";
    };
    
    														
    												

    這個示例與清單 1 中所示的標準 Java 2 策略文件相似。實際上,唯一的不同是主體語句,該語句聲明只有擁有指定主體和主體名字的 subject(用戶)被授予指定的許可權。

    再一次,使用系統屬性 java.security.auth.policy 指出 JAAS 策略文件駐留在何處,如下所示:

    														
    																java -Djava.security.auth.policy=policy.jaas
    
    														
    												

    Subject 類包含幾個方法來作為特殊 subject 執行工作;這些方法如下所示:

    														
    																public static Object 
      doAs(Subject subject, java.security.PrivilegedAction action)
    public static Object 
      doAs(Subject subject, java.security.PrivilegedAction action)
      throws java.security.PrivilegedActionException	
    
    														
    												

    注意,用來保護敏感代碼的方法與“Java 2 代碼源訪問控制”(Java 2 CodeSource Access Control)概述中描述的方法相同。請參閱 參考資料部分以了解更多關于 JAAS 中代碼源訪問控制和認證的信息。





    回頁首


    JAAS 中的授權

    清單 4 顯示一個授權請求的結果,該請求使用清單 3 中顯示的 JAAS 策略文件。假設已經安裝了 SecurityManager ,并且 loginContext 已經認證了一個帶有名為“admin”的 com.ibm.resource.security.auth.PrincipalExample 主體的 Subject


    清單 4. 一個簡單的授權請求
    														
    																public class JaasExample {
    	public static void main(String[] args) {
    		...
    		// where authenticatedUser is a Subject with
    		// a PrincipalExample named admin.
    		Subject.doAs(authenticatedUser, new JaasExampleAction());
    		...
    	}
    }
    
    public class JaasExampleAction implements PrivilegedAction {
    	public Object run() {
    		FileWriter fw = new FileWriter("hi.txt");
    		fw.write("Hello, World!");
    		fw.close();
    	}
    }	
    
    														
    												

    這里,敏感代碼被封裝在 JaasExampleAction 類中。還要注意,調用類不要求為 JaasExampleAction 類代碼源授予許可權,因為它實現了一個 PrivilegedAction





    回頁首


    擴展 JAAS

    大多數應用程序都有定制邏輯,它授權用戶不僅僅在類上執行操作,而且還在該類的實例上執行操作。這種授權通常建立在用戶和實例之間的關系上。這是 JAAS 的一個小缺點。然而,幸運的是,這樣設計 JAAS 使得 JAAS 可以擴展。只要做一點工作,我們將可以擴展 JAAS,使其包含一個通用的、類實例級的授權框架。

    在文章開頭處我已經說明了,抽象類 javax.security.auth.Policy 被用于代表 JAAS 安全性策略。它的缺省實現是由 com.sun.security.auth.PolicyFile 類提供。 PolicyFile 類從 JAAS 格式的文件(象清單 3 中顯示的那個一樣)中讀取策略。

    我們需要向這個文件添加一個東西為類實例級授權擴展策略定義:一個與許可權語句相關的可選關系參數。

    缺省 JAAS 許可權語句的格式如下:

    														
    																permission <permission implementation class> [name], [actions];	
    
    														
    												

    我們在這個許可權語句的末尾添加一個可選的關系參數來完成策略定義。下面是新許可權語句的格式:

    														
    																permission <permission implementation class> 
      [name], [actions], [relationship];
    
    														
    												

    在為類實例級授權擴展 JAAS 時要注意的最重要的一點是:許可權實現類必須有一個帶三個參數的構造函數。第一個參數是名稱參數,第二個是行為參數,最后一個是關系參數。

    解析新文件格式

    既然文件格式已經改變,就需要一個新的 javax.security.auth.Policy 子類來解析文件。

    為簡單起見,我們的示例使用了一個新的 javax.security.auth.Policy 子類 com.ibm.resource.security.auth.XMLPolicyFile ,來從 XML 文件讀取策略。在實際的企業應用程序中,關系數據庫更適合執行這個任務。

    使用 XMLPolicyFile 類代替缺省的 JAAS 訪問控制策略實現的最容易的方法是向 java.security 屬性文件添加 auth.policy.provider=com.ibm.resource.security.auth.XMLPolicyFile 條目。 java.security 屬性文件位于 Java 2 平臺運行時的 lib/security 目錄下。清單 5 是與 XMLPolicyFile 類一起使用的樣本 XML 策略文件:


    清單 5. 一個 XML 策略文件
    														
    																<?xml version="1.0"?>
    <policy>
        <grant codebase="file:/D:/sample_actions.jar">
          <principal classname=
            "com.ibm.resource.security.auth.PrincipalExample" name="users">
            <permission classname=
              "com.ibm.resource.security.auth.ResourcePermission"
              name="com.ibm.security.sample.Auction"
              actions="create" />
            <permission classname=
             "com.ibm.resource.security.auth.ResourcePermission"
              name="com.ibm.security.sample.Auction"
              actions="read" />
            <permission classname=
             "com.ibm.resource.security.auth.ResourcePermission"
              name="com.ibm.security.sample.Auction"
              actions="write"
              relationship="owner" />
            <permission classname=
             "com.ibm.resource.security.auth.ResourcePermission"
              name="com.ibm.security.sample.Bid"
              actions="create" />
            <permission classname=
             "com.ibm.resource.security.auth.ResourcePermission"
              name="com.ibm.security.sample.Bid"
              actions="read" />
            <permission classname=
             "com.ibm.resource.security.auth.ResourcePermission"
              name="com.ibm.security.sample.Bid"
              actions="write"
              relationship="owner" />
            <permission classname=
             "com.ibm.resource.security.auth.ResourcePermission"
              name="com.ibm.security.sample.Bid"
              actions="accept"
              relationship="actionOwner" />
        </principal>
      </grant>
    </policy>	
    
    														
    												

    在這個示例策略文件中,任何與名為 PrincipalExample 的用戶有關的用戶( Subject )都可以創建并讀取一個 Auction.class 實例。但是,只有創建該實例的用戶才可以更新(寫)它。這是第三個 permission 元素定義的,該元素包含值為 owner 的 relationship 屬性。 Bid.class 實例也是一樣,除了相應 Auction.class 實例的所有者可以更改投標接受標志。

    Resource 接口

    要求類實例級訪問控制的類必須實現 Resource 接口。該接口的 getOwner() 方法返回類實例的所有者。 fulfills(Subject subject, String relationship) 方法被用于處理特定關系。另外,這些類使用 com.ibm.resource.security.auth.ResourcePermission 類保護敏感代碼。例如, Auction 類擁有下列構造函數:

    														
    																public Auction() {
      Permission permission = 
        new ResourcePermission("com.ibm.security.sample.Auction", "create");
      AccessController.checkPermission(permission);
    	}	
    
    														
    												

    所有者關系

    ResourcePermission 類的 implies(Permission p) 方法是這個框架的關鍵。 implies() 方法就等同性比較名稱和行為屬性。如果定義了一個關系,那么必須把受保護的類實例( Resource )傳遞到 ResourcePermission 構造函數中。 ResourcePermission 類理解所有者關系。它將類實例的所有者與執行代碼的 subject(用戶)進行比較。特定關系被委托給受保護類的 fulfills() 方法。

    例如,在清單 5 中所示的 XML 策略文件中,只有 Auction 類實例的所有者可以更新(寫)文件。該類的 setter 方法使用清單 6 中顯示的保護代碼:


    清單 6. 運行中的 implies(Permission) 方法
    														
    																public void setName(String newName) {
      Permission permission = 
        new ResourcePermission("com.ibm.security.sample.Auction", "write", this);
      AccessController.checkPermission(permission);
      // sensitive code
      this.name = newName;
    }
    
    														
    												

    被傳遞到 ResourcePermission 構造函數中的 this 引用代表 Auction 類實現的 Resource 接口。由于策略文件中列出的關系是 owner,所以 ResourcePermission 類使用這個引用檢查當前 Subject (用戶)是否擁有與實例所有者相匹配的主體。如果指定了另一個關系,那么 ResourcePermission 類調用 Auction 類的 fulfills(Subject subject, String relationship) 方法。由 Resource 實現類提供 fulfills() 方法中的邏輯。

    XML 策略文件中列出的 Bid 類擁有清單 7 中所示的方法(假設 Bid 類實例有一個對相應 Auction 類實例的引用 ― auction)。


    清單 7. 處理特定關系
    														
    																public void setAccepted(boolean flag) {
      Permission permission = 
        new ResourcePermission("com.ibm.security.sample.Auction", "accept", this);
      AccessController.checkPermission(permission);
      // sensitive code
      this.accepted = flag;
      }
    	
    public boolean fulfills(Subject user, String relationship) {
      if( relationship.equalsIgnoreCase("auctionOwner") ) {
        String auctionOwner = auction.getOwner();
        Iterator principalIterator = user.getPrincipals().iterator();
        while(principalIterator.hasNext()) {
          Principal principal = (Principal) principalIterator.next();
          if( principal.getName().equals(auctionOwner) )
            return true;
        }
      }
      return false;
    }
    
    														
    												

    傳遞到 fulfills() 方法中的關系字符串是策略文件中列出的關系。在這個案例中,我們使用了“ auctionOwner ”字符串。

    缺省情況下, XMLPolicyFile 類在當前工作目錄中查找名為 ResourcePolicy.xml 的文件。系統屬性 com.ibm.resource.security.auth.policy 可以用于指定另一個不同的文件名和位置。

    WebSphere Application Server 示例

    除命令行示例之外,您可能還想運行這個簡單的程序,該程序 為了 IBM WebSphere Application Server,version 4.0.2 而被優化





    回頁首


    一個可運行的示例

    綜合這些信息,我們將運行一個簡單的命令行示例。該示例程序包含三個 jar 文件:

    • resourceSecurity.jar
    • example.jar
    • exampleActions.jar

    resourceSecurity.jar 文件包含允許實例級訪問控制的 JAAS 擴展框架。它還包含一個 LoginModuleExample 類,這個類從 XML 文件讀取用戶認證信息。用戶標識和密碼存儲在 users.xml 文件中。用戶組存儲在 groups.xml 文件中。關于 LoginModuleExample 的更多信息,請參閱 參考資料部分。

    該示例包含四個附加的文件:

    • login.conf
    • policy
    • resourcePolicy.xml
    • run.bat

    在試圖運行這個示例程序之前,請確保更新了 run.bat、policy 和 resourcePolicy.xml 文件中的路徑。缺省情況下,所有的密碼都是“passw0rd”。

    示例如何工作

    該示例程序提示輸入用戶標識和密碼。它用 users.xml 文件中的條目核對所提供的用戶標識和密碼。在認證了用戶之后,程序設法創建一個 UserProfile 類實例,修改它并從中讀取。缺省情況下, UserProfile 類的所有者是 Jane(jane)。當 Jane 登錄時,三個操作全部成功。當 John(john)登錄時,只有創建操作成功。當 Jane 的經理 Lou(lou)登錄時,只有第一個和最后一個操作成功。當系統管理員(admin)登錄時,操作全部成功。當然,只有當提供的 ResourcePolicy.xml 文件未被修改時,上述這些才都是真的。

    示例安裝
    下面的安裝指導假設您正在使用 JDK 1.3 并且已經把文件解壓縮到 d:\JaasExample 目錄。通過將文件解壓縮到這個目錄,您可以省去一些工作;否則您就必須使用正確的路徑名修改 policy 和 ResourceSecurity.xml 策略文件。

    下面是運行該示例需要做的工作:

    1. 下載這個示例的 源文件
    2. 把 jaas.jar 和 jaasmod.jar 復制到 JDK jre\lib\ext 目錄(即 D:\JDK1.3\jre\lib\ext)。
    3. 向位于 JDK 的 jre\lib\security 目錄(即 D:\JDK1.3\jre\lib\security)中的 java.security 文件的末尾添加下面的字符串: auth.policy.provider=com.ibm.resource.security.auth.XMLPolicyFile
    4. 執行 run.bat 文件。




    回頁首


    結束語

    類實例級授權把訪問控制分離到一個通用框架(該框架使用基于所有權和特定關系的策略)中。然后管理員可以在應用程序的生命周期內更改這些策略。用這種方法擴展 JAAS 減少了您或另一個程序員必須在應用程序生命周期內業務規則發生更改時重寫代碼的可能性。

    通過將關系字符串抽象為類可以進一步擴展特定關系這個概念。不調用 Resource 實現類的 fulfills(Subject user, String relationship) 方法,而只要調用 Relationship 實現類中定義的新 fulfills(Subject user, Resource resource) 方法。這樣就會允許許多 Resource 實現類使用相同的關系邏輯。

    posted on 2006-05-06 16:05 迷途書童 閱讀(705) 評論(0)  編輯  收藏 所屬分類: java應用

    主站蜘蛛池模板: 成人av免费电影| 99久久综合精品免费| 国产aa免费视频| 亚洲av永久中文无码精品| 在线免费一区二区| 亚洲无人区码一二三码区别图片| 久草在视频免费福利| 亚洲人成影院在线高清| 免费无码毛片一区二区APP| 亚洲激情黄色小说| 成年女人18级毛片毛片免费 | 丁香五月亚洲综合深深爱| 久久九九久精品国产免费直播| 国产成A人亚洲精V品无码性色| 免费人成激情视频在线观看冫| 亚洲∧v久久久无码精品| 99在线视频免费| 中文字幕乱码亚洲无线三区| 免费观看理论片毛片| 久久免费国产视频| 亚洲午夜精品一区二区| 波多野结衣在线免费观看| 亚洲国产精品无码中文lv| 亚洲精品综合久久| 久久免费国产视频| 亚洲 暴爽 AV人人爽日日碰| 青青青国产色视频在线观看国产亚洲欧洲国产综合 | 久久国产福利免费| 自怕偷自怕亚洲精品| 四虎成人免费观看在线网址 | 哒哒哒免费视频观看在线www| 产传媒61国产免费| 久久亚洲精精品中文字幕| 四虎影院免费在线播放| 9久热精品免费观看视频| 亚洲色图.com| 亚洲AV无码乱码在线观看| 一级毛片免费不卡在线| 亚洲成在人线在线播放无码| 亚洲成AV人片在线观看ww| 中文字幕无码免费久久99 |