2008-10-07 5 views
15

Hier, j'ai essayé de commencer avec Java RMI J'ai trouvé ce tutoriel solaire (http://java.sun.com/docs/books/tutorial/rmi/index.html) et j'ai commencé avec la mise en oeuvre du serveur. rmiregistry est en cours d'exécution), je reçois un AccessControlException avec le StackTrace suivant:Java RMI Tutorial - AccessControlException: accès refusé (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) 

Mon fichier server.policy ressemble à ceci:

grant { 
    permission java.security.AllPermission; 
}; 

Mais aussi Ive a essayé celui-ci ...

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

... et celui-ci (et plusieurs autres :-():

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

Mais dans tous les cas, le résultat est le même. Et oui, le fichier de politique est dans le chemin (je vois une exception d'analyse, quand j'écris de fausses déclarations dans le fichier de politique). J'ai essayé plusieurs autres constellations "/" et "\" mais cela n'a aucun effet.

J'utilise Eclipse et mes VM-paramètres sont comme ceci:

-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 

La compilation des classes à distance Interface et la classe de mise en œuvre de l'interface (LoginImpl) sont dans ce chemin: « C:/projx/serveur/serverProj/bin/usermanager/". La principale méthode, où j'instancier et REBIND le talon au registre est dans un autre paquet et ressemble à ceci:

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

Est-ce que quelqu'un a un conseil pour moi? Merci pour l'aide.


La question est la même (la java.rmi.UnmarshalException montre que le changement du code de base n'est pas la solution de mon AccessControlException). Et non: je ne veux pas acheter un plugin "G B" ;-).

+0

J'ai eu un problème similaire. Je l'ai résolu via cette approche - https://stackoverflow.com/a/44275905/1509058 –

Répondre

7

L'octroi de toutes les autorisations à tout le code est vraiment mauvais. Tout client RMI peut faire ce qu'il veut en tant qu'utilisateur connecté. En général, essayez de limiter autant que possible les autorisations, en particulier lorsque vous ne savez pas d'où provient le code.

Retour à la question ...

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

Cela devrait être soit "file:///C:/..." ou "file:/C:/...". Pensez à http. "http://C:/..." fait référence à un hôte nommé C. Notez que le message d'exception a supprimé les deux-points, car il ne s'agit que de la syntaxe du numéro de port. La raison pour laquelle vous obtenez une exception de sécurité même si vous accordez des autorisations à tout le code, est que RMI restreint les permissions à celle appropriée étant donné les URL impliquées (en utilisant AccessController doPrivileged deux arguments).

+0

Hey! J'ai trouvé cela très utile. Pourriez-vous s'il vous plaît me dire où stocker le fichier texte server.policy? – user1799214

+0

@ user1799214 L'affiche d'origine utilisait le répertoire de travail courant du serveur hte, en spécifiant '-Djava.security.policy = server.policy'. (Comme toujours, la suppression des restrictions sur le code accessible par le réseau est difficile à effectuer en toute sécurité.) –

0

Je pense que l'exception vient en fait de rmiregistry. Cette partie de la trace de la pile est ce qui me fait penser. Le talon pour rmiregistry reçoit l'exception et la remonte à la suite de la tentative de relier.

 
    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) 

Essayez d'exécuter rmiregistry avec -J-Djava.security.policy=all.policy, où le fichier de stratégie accorde toutes les autorisations (au moins pour faire avancer les choses). Finalement, vous voudrez peut-être également passer à une URL de base de code HTTP, juste pour pouvoir exécuter des clients sur une machine distincte de celle de votre serveur.

7

Ok, je l'ai. Il n'était pas ´ t la propriété rmiregistry (fonctionne sans aucun paramètre). Il y avait deux erreurs dans mon code de base VM-Paramètre:

-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 

... devrait plutôt ressembler à ceci:

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

=> fichier:/(une seule barre oblique) + faux se terminant paquet.

Mais la trace était tellement confuse, ma première pensée a été, que quelque chose doit être faux avec le fichier de politique ou la configuration de politique. Néanmoins, merci de votre aide et de votre piratage. Nous vous remercions de votre aide. ;-)

2

Vous pouvez également définir la propriété programatically 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(); 
} 

pour certains Hello hypothétique services RMI.

+0

Il semble que je ne puisse pas définir cette propriété. Mon Java semble m'interdire d'exécuter l'opération. –

0

J'ai une question très courte ...

Pourquoi il utilise ce chemin: "file: // C:/projx/server/serverProj/bin/usermanager" je suppose qu'il est dans les fenêtres, et les chemins dans les fenêtres sont écrites C: \ projx ...... Je demande parce que j'ai quelques problèmes avec RMI aussi, mais j'ai le fichier de stratégie de cette façon:

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

est-ce qui ne va pas?

0

Cela fonctionne très bien lorsque j'ai corrigé la variable CLASSPATH avant de démarrer le registre rmi. Je pense que l'idée est que le Registre RMI chargera vos talons distants et qu'il devrait y avoir accès. C'était facile en mettant mes classes sur le CLASSPATH avant d'exécuter le registre. Donc, il n'est pas lié à d'autres raisons telles que JDK 7 ou fichier:/protocole.

Questions connexes