SecurityManagerを使用してJavaRMIアプリケーションを実行しようとすると奇妙なエラーが発生します。サーバーの起動時に、コマンドライン引数として指定されたファイルからテキストを読み取ってほしい。私はEclipseを使用しており、このファイルはJavaプロジェクトのルートと同じディレクトリにあります(したがって、フルパスの代わりにコマンドライン引数でファイル名を指定できます)。RMIのSecurityManagerがデフォルトでファイルI/Oを禁止していることを知っているので、次のようなサーバー用のポリシーファイルを作成しました。
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";
ファイルの読み取り権限がないと主張しているのはなぜですか?Linuxコンピューターで同じプロジェクトを実行していて、同様のポリシーファイルを使用すると、ローカルプロジェクトディレクトリから正常に読み取ることができるため、これはWindowsの問題である可能性があります。
アップデート
でサーバーを実行する-Djava.security.debug=access,failure
と、ポリシーファイルの解析中に大量のデバッグメッセージが生成されました。このペーストビンでログ全体を見ることができますが、2つの重要な部分があるようです。
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>)
sun.misc.Launcher$AppClassLoader@74ba86ef
<no principals>
java.security.Permissions@7a8a44a6 (
("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で正常に機能することを忘れないでください。