web-dev-qa-db-ja.com

Java RMIチュートリアル-AccessControlException:アクセスが拒否されました(Java.io.FilePermission

昨日、Java RMIを使い始めようとしました。このSunチュートリアルを見つけました( http://Java.Sun.com/docs/books/tutorial/rmi/index.html )そしてサーバーの実装から開始しました。しかし、pogramを開始するたびに(rmiregistryが実行されている)、次のStackTraceでAccessControlExceptionが発生します。

LoginImpl exception:
Java.security.AccessControlException: access denied (Java.io.FilePermission \\\C\ProjX\server\serverProj\bin\usermanager read)
    at Java.security.AccessControlContext.checkPermission(AccessControlContext.Java:264)
    at Java.security.AccessController.checkPermission(AccessController.Java:427)
    at Java.lang.SecurityManager.checkPermission(SecurityManager.Java:532)
    at Java.lang.SecurityManager.checkRead(SecurityManager.Java:871)
    at Java.io.File.exists(File.Java:700)
    at Sun.net.www.protocol.file.Handler.openConnection(Handler.Java:80)
    at Sun.net.www.protocol.file.Handler.openConnection(Handler.Java:55)
    at Java.net.URL.openConnection(URL.Java:943)
    at Sun.rmi.server.LoaderHandler.addPermissionsForURLs(LoaderHandler.Java:1020)
    at Sun.rmi.server.LoaderHandler.access$300(LoaderHandler.Java:52)
    at Sun.rmi.server.LoaderHandler$Loader.<init>(LoaderHandler.Java:1108)
    at Sun.rmi.server.LoaderHandler$Loader.<init>(LoaderHandler.Java:1089)
    at Sun.rmi.server.LoaderHandler$1.run(LoaderHandler.Java:861)
    at Java.security.AccessController.doPrivileged(Native Method)
    at Sun.rmi.server.LoaderHandler.lookupLoader(LoaderHandler.Java:858)
    at Sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.Java:541)
    at Java.rmi.server.RMIClassLoader$2.loadProxyClass(RMIClassLoader.Java:628)
    at Java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.Java:294)
    at Sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStream.Java:238)
    at Java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.Java:1494)
    at Java.io.ObjectInputStream.readClassDesc(ObjectInputStream.Java:1457)
    at Java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.Java:1693)
    at Java.io.ObjectInputStream.readObject0(ObjectInputStream.Java:1299)
    at Java.io.ObjectInputStream.readObject(ObjectInputStream.Java:339)
    at Sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
    at Sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.Java:375)
    at Sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.Java:240)
    at Sun.rmi.transport.Transport$1.run(Transport.Java:153)
    at Java.security.AccessController.doPrivileged(Native Method)
    at Sun.rmi.transport.Transport.serviceCall(Transport.Java:149)
    at Sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.Java:460)
    at Sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.Java:701)
    at Java.lang.Thread.run(Thread.Java:595)
    at Sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Unknown Source)
    at Sun.rmi.transport.StreamRemoteCall.executeCall(Unknown Source)
    at Sun.rmi.server.UnicastRef.invoke(Unknown Source)
    at Sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)
    at startserver.StartServer.main(StartServer.Java:22)

私のserver.policyファイルは次のようになります。

grant {
    permission Java.security.AllPermission;
};

しかし、私もこれを試しました...

grant {
    permission Java.security.AllPermission;
    permission Java.io.FilePermission "file://C:/ProjX/server/serverProj/bin/usermanager", "read";
};

...そしてこれ(そして他のいくつか:-():

grant codeBase "file:///-" {
    permission Java.security.AllPermission;
};

しかし、いずれの場合も結果は同じです。はい、ポリシーファイルはパス内にあります(ポリシーファイルに間違ったステートメントを書き込むと、解析例外が表示されます)。他のいくつかの「/」と「\」の星座を試しましたが、効果がありません。

私はEclipseを使用しており、VM-パラメーターは次のようになっています。

-cp C:\ProjX\server\serverProj\bin\usermanager\
-Djava.rmi.server.codebase=file://C:/ProjX/server/serverProj/bin/usermanager/
-Djava.rmi.server.hostname=XYZ (anonymized)
-Djava.security.policy=server.policy

コンパイルされたRemote-Interfaceクラスとinterface-implementationクラス(LoginImpl)クラスは、「C:/ ProjX/server/serverProj/bin/usermanager /」のパスにあります。スタブをインスタンス化してレジストリに再バインドするmainメソッドは、別のパッケージにあり、次のようになります。

public static void main(String[] args) {
    if (System.getSecurityManager() == null) {
        System.setSecurityManager(new SecurityManager());
    }
    try {
        String name = "Login";
        Login login = new LoginImpl();
        Login stub = (Login) UnicastRemoteObject.exportObject(login, 0);
        Registry registry = LocateRegistry.getRegistry();
        registry.rebind(name, stub);
        System.out.println("LoginImpl bound");
    } catch (Exception e) {
        System.err.println("LoginImpl exception:");
        e.printStackTrace();
    }
}

誰かアドバイスはありますか?ご協力ありがとう御座います。


したがって、質問は同じです(Java.rmi.UnmarshalExceptionは、コードベースの変更が私のAccessControlExceptionの解決策ではないことを示しています)。いいえ:プラグイン「GB」を購入したくありません;-)。

15
user25913

すべてのコードにすべての権限を付与することは本当に悪いことです。すべてのRMIクライアントは、ログインしたユーザーとして必要なことを実行できます。一般に、特にコードの出所がわからない場合は、許可をできるだけ制限するようにしてください。

質問に戻る...

-Djava.rmi.server.codebase=file://C:/ProjX/server/serverProj/bin/usermanager/

それは"file:///C:/..."または"file:/C:/..."。 httpについて考えてください。 "http://C:/..."は、Cという名前のホストを指します。これはポート番号の構文にすぎないため、例外メッセージでコロンが削除されていることに注意してください。

すべてのコードにアクセス許可を付与してもセキュリティ例外が発生する理由は、RMIが関連するURLを指定して適切なアクセス許可に制限しているためです(AccessController doPrivileged 2引数形式を使用)。

はい、あります。これはrmiregistryプロパティではありませんでした(パラメーターなしで機能します)。コードベースVMに2つのエラーがありました-パラメータ:

-cp C:\ProjX\server\serverProj\bin\usermanager\
-Djava.rmi.server.codebase=file://C:/ProjX/server/serverProj/bin/usermanager/
-Djava.rmi.server.hostname=XYZ (anonymized)
-Djava.security.policy=server.policy

...代わりに次のようになります。

-Djava.rmi.server.codebase=file:/C:/ProjX/server/serverProj/bin/
-Djava.rmi.server.hostname=XYZ (anonymized)
-Djava.security.policy=server.policy

=>ファイル:/(スラッシュは1つだけ)+間違ったパッケージの終了。

しかし、トレースは非常に紛らわしく、私の最初の考えは、ポリシーファイルまたはポリシー構成に何か問題があるに違いないということでした。

それにもかかわらず:助けと幸せなハッキングをありがとう。 ;-)

7
user25913

プログラムでJava.rmi.server.codebaseプロパティを設定することもできます。

Hello h = null;
Properties props = System.getProperties();
System.setProperty("Java.rmi.server.codebase", "file:/C:/PROJECTX/bin/");
try {
  h = new HelloImpl();
  Naming.bind("//localhost:1099/HelloService", h);
  System.out.println("Serwis gotów...");
} catch (RemoteException e) {
  e.printStackTrace();
} catch (MalformedURLException e) {
  e.printStackTrace();
} catch (AlreadyBoundException e) {
  e.printStackTrace();
}

いくつかの架空のHelloRMIサービスの場合。

2

非常に短い質問があります...

なぜ彼はこのパスを使用するのですか: "file:// C:/ ProjX/server/serverProj/bin/usermanager"私は彼がWindowsにいると思います、そしてWindowsのパスはC:\ ProjX ...... Iと書かれています。私もRMIに問題があるので尋ねますが、私はこの方法でポリシーファイルを持っています:

grant codebase     
"file:///C:\Users\anna\Desktop\lab5\Eclipse\ProgramareServer\programare.jar-" { 
    permission Java.security.AllPermission;
};

間違っていますか?

0
Madrugada

例外は実際にはrmiregistryから出ていると思います。スタックトレースのこの部分は、私がそう思う理由です。 rmir​​egistryのスタブは例外を受け取り、再バインドの試みの結果としてそれを元に戻しています。

 Sun.rmi.transport.StreamRemoteCallで。exceptionReceivedFromServer(不明なソース)
 at Sun.rmi.transport.StreamRemoteCall.executeCall(不明なソース)
 at Sun.rmi.server.UnicastRef.invoke(不明なソース)
 at Sun. rmi.registry.RegistryImpl_Stub.rebind(不明なソース)

-J-Djava.security.policy=all.policyを指定してrmiregistryを実行してみてください。ここで、ポリシーファイルはすべてのアクセス許可を付与します(少なくとも作業を進めるため)。

最終的には、サーバーとは別のマシンでクライアントを実行できるようにするために、HTTPコードベースURLに切り替えることもできます。

0
bhavanki

Rmiレジストリを開始する前にCLASSPATH変数を修正すると、問題なく動作します。 RMIレジストリがリモートスタブをロードし、アクセスできるようにするという考え方だと思います。レジストリを実行する前にクラスをCLASSPATHに配置することで、これは簡単でした。したがって、JDK 7やfile:/プロトコルなどの他の理由とは関係ありません。

0
Tarek