1. 程式人生 > >關於java.security.AccessControlException: access denied 的解決方法

關於java.security.AccessControlException: access denied 的解決方法

今天除錯了您的JDBCUpdateApplet程式.您說在直接用ie開啟RunApplet.html檔案.會在java控制檯報java.security.AccessControlException: access denied
(java.lang.RuntimePermission accessClassInPackage.sun.jdbc.odbc)錯誤.我這裡也出現了這個錯誤提示!根據網上搜索的有關問題的分析.這是因為applet在沒有被允許的情況下去獲取系統資源.同時,錯誤提示需要一個RuntimePermission,它將使applet去獲得sun.jdbc.odbc 包.所以可以在您系統的java執行時包修改一個關於安全的一檔案.具體做法是:找到您的ie瀏覽器使用的jre包,我家的是:D:\Program Files\Java\jre1.6.0\lib\security,在這個包下面有個java.policy檔案,開啟編輯它:在grant裡增加2個語句:permission java.lang.RuntimePermission "accessClassInPackage.sun.jdbc.odbc"; 
permission java.util.PropertyPermission "file.encoding", "read"; 再關閉ie,重新執行就可以解決這個問題.我在家裡的機子中,增加以後就沒有在出現上面的錯誤資訊了. 增加第二個語句是因為讓applet能讀一些二進位制檔案.不然可能會出現java.security.AccessControlException:
  access denied (java.lang.RuntimePermission
  file.encoding read)
錯誤. 解決的方案來自於網上的討論:
http://java.sun.com/developer/onlineTraining/Programming/BasicJava1/dba.html
http://www.javaworld.com.tw/jute/post/view?bid=29&id=71700&tpg=1&ppg=1&sty=1&age=0

這兩個地址是關於這個問題的討論和分析.

眾所周知,Java語言具有完善的安全框架,從程式語言,編譯器、解釋程式到Java虛擬機器,都能確保Java系統不被無效的程式碼或敵對的編譯器暗中破壞,基本上,它們保證了Java程式碼按預定的規則運作。但是,當我們需要逾越這些限制時,例如,讀寫檔案,監聽和讀寫Socket,退出Java系統等,就必須使用數字簽名或安全策略檔案(*.Policy)。
  在企業內部網中,本文提出了使用安全策略檔案來設定java程式許可權的一種簡單的方法。由於企業內部網中各臺計算機的位置、用途和安全性明確,更適於使用安全策略檔案來設定java的許可權,軟體的安裝、設定、升級和遷移都非常的方便,並且,還可以和數字簽名配合使用,更重要的是,可以細分每個java程式的許可權,使用起來靈活方便。
一. Java中安全策略的概念
  Java應用程式環境的安全策略,詳細說明了對於不同的程式碼所擁有的不同資源的許可,它由一個Policy物件來表達。為了讓applet(或者執行在SecurityManager下的一個應用程式)能夠執行受保護的行為,例如讀寫檔案,applet(或Java應用程式)必須獲得那項操作的許可,安全策略檔案就是用來實現這些許可。
  Policy物件可能有多個實體,雖然任何時候只能有一個起作用。當前安裝的Policy物件,在程式中可以通過呼叫getPolicy方法得到,也可以通過呼叫setPolicy方法改變。Policy物件評估整個策略,返回一個適當的Permissions物件,詳細說明那些程式碼可以訪問那些資源。
  策略檔案可以儲存在無格式的ASCII檔案,或Policy類的二進位制檔案,或資料庫中。本文僅討論無格式的ASCII檔案的形式。
二. Policy檔案的格式
  為了能夠更好地理解下面的內容,建議在閱讀時參照\jdk1.2\jre\lib\security\java.policy檔案和\jdk1.2\jre\lib\security\java.security檔案的內容。
  1. Policy檔案的語法格式與說明
  一個Policy檔案實質上是一個記錄列表,它可能含有一個“keystore”記錄,以及含有零個或多個“grant”記錄。其格式如下:
keystore "some_keystore_url", "keystore_type";
grant [SignedBy "signer_names"] [, CodeBase "URL"] {
Permission permission_class_name
[ "target_name" ] [, "action"] [, SignedBy "signer_names"];
Permission ...};
  1.1"keystore"記錄
  一個keystore是一個私有金鑰(privatekeys)資料庫和相應的數字簽名,例如X.509證書。Policy檔案中可能只有一條keystore記錄(也可能不含有該記錄),它可以出現在檔案中grant記錄以外的任何地方。Policy配置檔案中指定的keystores用於尋找grant記錄中指定的、簽名者的公共金鑰(publickeys),如果任何grant記錄指定簽名者(signer_names),那麼,keystore記錄必須出現在policy配置檔案中。
  "some_keystore_url"是指keystore的URL位置,"keystore_type"是指keystore的型別。第二個選項是可選項,如果沒有指定,該型別則假定由安全屬性檔案(java.security)中的"keystore.type"屬性來確定。keystore型別定義了keystore資訊的儲存和資料格式,用於保護keystore中的私有金鑰和keystore完整性的演算法。SunMicrosystems支援的預設型別為“JKS”。
  1.2"grant"記錄
  在Policy檔案中的每一個grant記錄含有一個CodeSource(一個指定的程式碼)及其permission(許可)。
  Policy檔案中的每一條grant記錄遵循下面的格式,以保留字“grant”開頭,表示一條新的記錄的開始,“Permission”是另一個保留字,在記錄中用來標記一個新的許可的開始。每一個grant記錄授予一個指定的程式碼(CodeBase)一套許可(Permissions)。
  permission_class_name必須是一個合格並存在的類名,例如java.io.FilePermission,不能使用縮寫(例如,FilePermission)。
  target_name用來指定目標類的位置,action用於指定目標類擁有的許可權。
  target_name可以直接指定類名(可以是絕對或相對路徑),目錄名,也可以是下面的萬用字元:
directory/* 目錄下的所有檔案
*當前目錄的所有檔案
directory/-目錄下的所有檔案,包括子目錄
- 當前目錄下的所有檔案,包括子目錄
《ALL FILES》檔案系統中的所有檔案
對於java.io.FilePermission,action可以是:
read, write, delete和execute。
對於java.net.SocketPermission,action可以是:
listen,accept,connect,read,write。
  1.3 Policy檔案中的屬性擴充套件(Property Expansion)
  屬性擴充套件與shell中使用的變數擴充套件類似,它的格式為:
"${some.property}"
實際使用的例子為:
permission java.io.FilePermission "${user.home}", "read"; "${user.home}"的值為"d:\Project",
因此,下面的語句和上面的語句是一樣的:
permission java.io.FilePermission " d:\Project ", "read";
三. 例項
  當初始化Policy時,首先裝載系統Policy,然後再增加使用者Policy,如果兩者都不存在,則使用預設的Policy,即原始的沙箱模型。
  系統Policy檔案的預設位置為:
{java.home}/lib/security/java.policy (Solaris)
{java.home}\lib\security\java.policy (Windows)
使用者Policy檔案的預設位置為:
{user.home}/.java.policy (Solaris)
{user.home}\.java.policy (Windows)
  其實,在實際使用中,我們可能不會象上面介紹的那麼複雜,特別是在不使用數字簽名時。這時,我們完全可以借鑑JDK1.2提供給我們的現成的\jdk1.2\jre\lib\security\java.policy檔案,根據我們的需要作相應的修改,本文就針對不使用數字簽名情況詳細說明安全策略檔案的用法。
  下面,是一個完整的在Windows 95/98/NT下使用的.java.policy檔案。在檔案中,分別使用註釋的形式說明了每個“permission”記錄的用途。
// For LanServerTalk.java and LanClientTalk.java
grant {
//對系統和使用者目錄“讀”的許可權
permission java.util.PropertyPermission "user.dir", "read";
permission java.util.PropertyPermission "user.home", "read";
permission java.util.PropertyPermission "java.home", "read";
permission java.util.PropertyPermission "java.class.path", "read";
permission java.util.PropertyPermission "user.name", "read";
//對執行緒和執行緒組的操作許可權
permission java.lang.RuntimePermission "modifyThread";
permission java.lang.RuntimePermission "modifyThreadGroup";
//操作Socket埠的各種許可權
permission java.net.SocketPermission "-", "listen";
permission java.net.SocketPermission "-", "accept";
permission java.net.SocketPermission "-", "connect";
permission java.net.SocketPermission "-", "read";
permission java.net.SocketPermission "-", "write";
//讀寫檔案的許可權
permission java.io.FilePermission "-", "read";
permission java.io.FilePermission "-", "write";
//退出系統的許可權,例如System.exit(0)
permission java.lang.RuntimePermission "exitVM";
};
四. java.policy檔案的使用
  對於windows 95/98/NT,使用.java.policy檔案的方法主要有下面兩種。
  1. 使用預設目錄
  我們可以簡單地將編輯好的.java.policy檔案拷貝到windows95/98/NT的HOME目錄,這時,所有的applet(或Java應用程式)可能都擁有某些相同的許可權,使用起來簡單,但不靈活(例如:對於java.io.FilePermission,其目標類的target_name必須使用絕對路徑),如果不是在企業內部網中使用,還可能存在一定安全隱患。
  2. 在命令列中指定
  在命令列,如果我們希望傳遞一個Policy檔案給appletviewer,還可以使用"-J-Djava.security.policy"引數來指定policy的位置:
appletviewer -J-Djava.security.
policy=pURL myApplet
  pURL為Policy檔案的位置。下面,是一個實際的例子,以當前目錄的.java.policy檔案所指定的安全策略運行當前目錄的LanServerTalk.html(檔案中裝載並執行LanServerTalk.java):
appletviewer -J-Djava.security.policy
=.java.policy LanServerTalk.html
  這種方法使用靈活,特別是作為一個軟體包在企業內部網中釋出時,安裝、設定和遷移軟體,基本無須修改Policy檔案的內容,使用起來相當簡單,而且,安全許可的範圍控制較精細。