2012-10-29 91 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