2012-10-29 47 views
0

嘗試運行帶有SecurityManager的Java RMI應用程序時出現了一個奇怪的錯誤。當服務器啓動時,我希望它從作爲命令行參數提供的文件中讀取文本。我使用的是Eclipse,並且這個文件和Java項目的根目錄在同一個目錄下(所以我可以在命令行參數中給出文件名而不是完整的路徑)。我知道,RMI公司的安全管理器默認禁止的文件I/O,所以我創造了我的服務器策略文件看起來像這樣:儘管授予適當的文件權限,但Java AccessControlException

grant codeBase "file:///C:/Users/Edward/College/CS197/authmatch/bin/-" { 
    //Giving the server permission to make connections 
    permission java.net.SocketPermission "127.0.0.1:1024-", "connect, resolve"; 
    permission java.net.SocketPermission "127.0.0.1:1024-", "accept, resolve"; 
    //File I/O permissions 
    permission java.io.FilePermission "C:/Users/Edward/College/CS197/authmatch/-", "read,write,delete"; 
    permission java.util.PropertyPermission "user.dir", "read"; 
    permission java.lang.RuntimePermission "readFileDescriptor"; 
    permission java.lang.RuntimePermission "modifyThread"; 
}; 

(請注意,我的Eclipse項目的名稱是「authmatch」這在Windows上運行)。在我的Eclipse運行配置,我能夠用下面的VM標誌這一政策文件:

-Djava.rmi.server.codebase=file:///C:/Users/Edward/Documents/College/CS197/authmatch/bin/ 
-Djava.security.policy=server.policy 

我知道,政策文件被解析並加載,因爲如果我介紹的server.policy的Java抱怨它有語法錯誤(「錯誤解析文件」),當我的應用程序運行。然而,安全經理似乎在某種程度上忽略了我的保單我授予的權限,因爲當我運行該應用程序我得到這個錯誤:

Exception in thread "main" java.security.AccessControlException: access denied ("java.io.FilePermission" "smalltest.txt" "read") 
    at java.security.AccessControlContext.checkPermission(Unknown Source) 
    at java.security.AccessController.checkPermission(Unknown Source) 
    at java.lang.SecurityManager.checkPermission(Unknown Source) 
    at java.lang.SecurityManager.checkRead(Unknown Source) 
    at java.io.RandomAccessFile.<init>(Unknown Source) 
    at etremel.authmatch.text.TextFileFormatter.<init>(TextFileFormatter.java:39) 
    at etremel.authmatch.source.PatternMatcherSource.main(PatternMatcherSource.java:302) 

由於我要求它讀取文件(smalltest.txt )是在「authmatch」項目目錄,我明確了我的應用程序權限讀取該目錄與線

permission java.io.FilePermission "C:/Users/Edward/College/CS197/authmatch/-", "read,write,delete"; 

爲什麼它仍然堅持認爲它不具有讀取權限的文件嗎?我懷疑這可能是一個Windows問題,因爲我在Linux計算機上運行相同的項目,並且類似的策略文件允許它從本地項目目錄中讀取就好了。

UPDATE

我跑了服務器-Djava.security.debug=access,failure並在解析政策文件時,它產生一束調試消息。您可以在this pastebin看到整個日誌,但似乎有兩個重要部分:

access: access allowed ("java.security.SecurityPermission" "getPolicy") 
access: access allowed ("java.io.FilePermission" "C:\Users\Edward\Documents\College\CS197\authmatch\bin" "read") 
access: domain that failed ProtectionDomain (file:/C:/Users/Edward/Documents/College/CS197/authmatch/bin/ <no signer certificates>) 
[email protected] 
<no principals> 
[email protected] (
("java.io.FilePermission" "\C:\Users\Edward\Documents\College\CS197\authmatch\bin\-" "read") 
("java.net.SocketPermission" "localhost:1024-" "listen,resolve") 
... 

...以及更高版本:

access: access allowed ("java.io.FilePermission" "C:\Users\Edward\Documents\College\CS197\authmatch\bin\etremel\authmatch\text\TextFileFormatter.class" "read") 
access: access allowed ("java.util.PropertyPermission" "user.dir" "read") 
access: access denied ("java.io.FilePermission" "smalltest.txt" "read") 

它看起來像有某種「域名保護」因爲我的代碼庫沒有簽名,但我認爲可以使用grant codeBase安裝程序指定沒有簽名的安全策略。更令人費解的是,它看起來並不像它讀取根authmatch目錄的FilePermission,只是authmatch/bin目錄。然後它得出結論,它應該拒絕對「smalltest.txt」的訪問,但它永遠不會解析該文件的完整目錄路徑。

請記住,相同的項目和政策在Linux上運行良好。

+1

使用'-Djava.security-debug = access,failure'運行它,您將看到到底發生了什麼。在這裏發佈最後一點,這是包含失敗的一點。但是,除非客戶端使用java.rmi.server.codebase功能向服務器提供.class文件,否則在RMI服務器中並不需要'SecurityManager'。 – EJP

回答

1

問題出在您拼寫代碼庫URL的方式和拼寫方式之間:file:/C:/Users/Edward/Documents/College/CS197/authmatch/bin/。他們不一樣,所以你的grant塊不適用。查看「失敗的域名」打印輸出的內容:您的.policy內容不在此處。

關於簽署者證書的東西不是錯誤,它只是說沒有與'失敗的域'相關聯的簽名者。

+0

我將server.policy的第一行更改爲'grant codeBase'文件:/ C:/ Users/Edward/College/CS197/authmatch/bin/- 「',將VM運行時參數更改爲-Djava.rmi.server。 codebase = file:/ C:/ Users/Edward/Documents/College/CS197/authmatch/bin /',但這似乎沒有什麼區別 - 我在調試打印輸出中得到完全相同的「失敗」域。 – Edward

+0

@Edward你真的需要 - 在代碼庫字符串?這個目錄肯定包含很多.jar文件,或者是包結構的頭部?當您嘗試列出'失敗的域名'日誌時會發生什麼? – EJP

+0

我擺脫了「 - 」,並沒有改變任何東西。然後我試圖從日誌列表「失敗的域名」複製並粘貼,並且它工作正常。事實證明,在'codeBase'行中使用的路徑中存在拼寫錯誤 - 請注意,它不包含「Documents」文件夾,而實際的代碼庫路徑卻是。嗯,我覺得很愚蠢。 – Edward