1. 程式人生 > >java安全管理器

java安全管理器

為什麼要有安全管理器?
安全管理器讓java程式碼訪問外部資源的時候受到一層過濾。就像classloader和class檔案檢驗器是檢測java檔案一樣,從2個方面保證了程式碼的安全性。
在Java應用中,安全管理器是由System類中的方法setSecurityManager設定的。要獲得當前的安全管理器,可以使用方法getSecurityManager。
  java.lang.SecurityManager類包含了很多checkXXXX方法,如用於判斷對檔案訪問許可權的checkRead(String file)方法。這些檢查方法呼叫SecurityManager.checkPermission方法,後者根據安全策略檔案判斷呼叫應用是否有執行所請求的操作許可權。如果沒有,將引發SecurityException。

如果想讓應用使用安全管理器和安全策略,可在啟動JVM時設定-Djava.security.manager選項,還可以同時指定安全策略檔案。如果在應用中啟用了Java安全管理器,卻沒有指定安全策略檔案,那麼Java安全管理器將使用預設的安全策略,它們是由位於目錄$JAVA_HOME/jre/lib/security中的java.policy定義的。

概念
策略(Policy)
    類裝載器用Policy物件幫助它們決定,把一段程式碼匯入虛擬機器時應該給它們什麼樣的許可權. 任何時候,每一個應用程式都只有一個Policy物件.
策略檔案
    Sun的java1.2平臺具體的Policy子類採用在一ASCII策略檔案中用上下文無關文法描述安全策略.
    一個策略檔案包括了一系列grant子句,每一個grant子句將一些許可權授給一個程式碼來源。
保護域(ProtectionDomain)
    當類裝載器將型別裝入java虛擬機器時,它們將為每一個型別指派一個保護域,保護域定義了授予
   一段特定的程式碼的所有許可權.裝載入java虛擬機器的每一個型別都屬於一個且僅屬於一個保護域.
訪問控制器(AccessController)
     implies()
          判斷一個Permissioin物件的許可權,是否隱含(imply)在另一個Permissioin物件的許可權中。
    checkPermission()
         AccessController的核心方法,這個方法決定一個特定的操作能否被允許.
         它自頂向下檢查棧,只要它遇到一個沒有許可權楨,它將丟擲一個AccessControlException導常。
    doPrivileged()
         有的時候,呼叫棧較上層(更靠近棧頂)的程式碼可能希望執行一段程式碼,而這段程式碼在呼叫棧的較
         下層是不允許執行的。
          為了使可信的程式碼執行較不可靠的程式碼操作(這段不可靠的程式碼位於呼叫棧的較下層且沒有執行
          這個操作的許可權),AccessController類過載了四個名為doPrivileged()的靜態方法.
          AccessController會忽略呼叫doPrivileged()方法的呼叫者的呼叫者的許可權.
    Permission:
          許可權是用抽象類java.security.Permission的一個子類的例項表示的.
    CodeSource:
         程式碼來源,包含程式碼庫URL和簽名者.
    Permissions:
        PermissionCollection(許可權集合)的子類

裝載時生成保護域的步驟:
1           根據指定的Policy檔案生成一個Policy物件
2           生成CodeSource
3           用CodeSource在Policy中找到CodeSource對應的Permissions
4           用CodeSource和Permissons構造一個ProtectionDomain
5           把ProtectionDomain同這個類在方法區中的類資料聯絡起來(ClassLoader.defineClass()).