2008-10-07 12 views
15

Gestern habe ich versucht mit Java RMI anzufangen. Ich habe dieses Sun Tutorial (http://java.sun.com/docs/books/tutorial/rmi/index.html) gefunden und mit der Serverimplementierung begonnen, aber jedes Mal starte ich das Programm rmiregistry läuft) ich erhalte eine Access mit folgendem Stacktrace:Java RMI Tutorial - AccessControlException: Zugriff verweigert (java.io.FilePermission

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) 

Meine server.policy Datei sieht wie folgt aus:

grant { 
    permission java.security.AllPermission; 
}; 

Aber Ive versuchte auch dieses ...

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

... und dieser (und einige andere :-():

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

Aber in jedem Fall ist das Ergebnis das gleiche. Und ja, die Richtliniendatei befindet sich im Pfad (ich sehe eine Parse-Ausnahme, wenn ich falsche Statements in die Richtliniendatei schreibe). Ich habe einige andere "/" und "\" Konstellationen ausprobiert, aber es hat keine Wirkung.

Ich benutze Eclipse und meine VM-Parameter sind wie folgt aus:

-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 

Die kompilierte Fern-Interface und die Schnittstelle-Implementierungsklasse (LoginImpl) Klassen sind in diesem Pfad: „C:/projX/Server/serverProj/bin/usermanager/". Die wichtigste Methode, wo ich instanziieren und den Stummel an der Registrierung rebind ist in einem anderen Paket und sieht wie folgt aus:

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(); 
    } 
} 

Hat jemand für mich einen Rat? Danke für die Hilfe.


So ist die Frage der gleiche ist (die java.rmi.UnmarshalException zeigt, dass die Code-Basis ändert nicht die Lösung meines Access ist). Und nein: Ich möchte kein Plugin "G B" kaufen ;-).

+0

Ich hatte ein ähnliches Problem. Ich löste es über diesen Ansatz - https://Stackoverflow.com/a/44275905/1509058 –

Antwort

7

Grant aller Berechtigungen für alle Code ist ein wirklich schlecht. Jeder RMI-Client könnte tun, was er als angemeldeter Benutzer wollte. Versuchen Sie im Allgemeinen, die Berechtigungen so weit wie möglich einzuschränken, insbesondere, wenn Sie nicht wissen, woher der Code stammt.

Zurück zur Frage ...

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

, die entweder "file:///C:/..." oder "file:/C:/..." sein sollte. Denke an http. "http://C:/..." bezieht sich auf einen Host mit dem Namen C. Beachten Sie, dass die Ausnahmebedingungsnachricht den Doppelpunkt gelöscht hat, da dies nur die Syntax für die Portnummer ist.

Der Grund, warum Sie eine Sicherheitsausnahme erhalten, selbst wenn Sie Berechtigungen für den gesamten Code erteilen, ist, dass RMI die Berechtigungen auf die entsprechenden URLs beschränkt (mit dem AccessController doPrivileged-Formular mit zwei Argumenten).

+0

Hey! Ich fand das sehr hilfreich. Können Sie mir bitte sagen, wo ich die server.policy Textdatei speichern soll? – user1799214

+0

@ user1799214 Das ursprüngliche Poster verwendete das aktuelle Arbeitsverzeichnis des Server, mit Angabe von -Djava.security.policy = server.policy'. (Wie immer ist das Entfernen von Beschränkungen für netzwerkzugänglichen Code nicht sicher.) –

0

Ich denke, die Ausnahme kommt tatsächlich aus der Zauberei. Dieser Teil des Stack-Trace ist der Grund, warum ich das denke. Der Stub für die Regierung erhält die Ausnahme und gibt sie als Ergebnis des Wiederanbindungsversuches weiter.

 
    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) 

laufen Versuchen rmiregistry mit -J-Djava.security.policy=all.policy, wo die Richtliniendatei alle Berechtigungen erteilt (zumindest um Dinge geht).

Eventuell möchten Sie auch zu einer HTTP-Codebasis-URL wechseln, nur damit Sie Clients auf einem anderen Computer als Ihrem Server ausführen können.

7

Ok, ich habe es. Es war ´ t die Eigenschaft rmiregistry (funktioniert ohne Parameter). Es gab zwei Fehler in meinen Code-Basis VM-Parametern:

-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 

... stattdessen soll wie folgt aussehen:

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

=> file:/(nur ein Schrägstrich) + falsches Paket Ende.

Aber die Spur war so verwirrend, mein erster Gedanke war, dass etwas mit der Policy-Datei oder der Policy-Konfiguration falsch sein muss.

Nichtsdestotrotz: Vielen Dank für Hilfe und Happy Hacking. ;-)

2

können Sie auch programmatisch java.rmi.server.codebase Eigenschaft:

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(); 
} 

für einige hypothetische Hello RMI-Service.

+0

Ich kann diese Eigenschaft nicht festlegen. Mein Java scheint es mir nicht zu erlauben, die set-Operation auszuführen. –

0

ich eine sehr kurze Frage ...

Warum er diesen Weg nicht verwendet: "file: // C:/projX/server/serverProj/bin/Usermanager" ich denke, er in Fenstern, und die Wege in den Fenstern geschrieben C: \ projX ...... ich frage, weil ich einige Probleme mit RMI zu haben, aber ich habe die Richtliniendatei auf diese Weise:

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

ist es falsch?

0

Es funktioniert einfach gut, wenn ich die Variable CLASSPATH vor dem Starten der RMI-Registrierung behoben habe. Ich denke, die Idee ist, dass die RMI-Registrierung Ihre Remote-Stubs lädt und es sollte Zugriff haben. Das war einfach, indem ich meine Klassen auf den CLASSPATH setzte, bevor ich die Registrierung ausführte. Es hängt also nicht mit einem anderen Grund wie JDK 7 oder file:/protocol zusammen.