2008-10-07 19 views
15

Ayer traté de comenzar con Java RMI. Encontré este tutorial de sol (http://java.sun.com/docs/books/tutorial/rmi/index.html) y comencé con la implementación del servidor. Pero cada vez que inicio el pograma (el rmiregistry se está ejecutando) me sale un AccessControlException con la siguiente StackTrace:Java RMI Tutorial - AccessControlException: acceso denegado (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) 

Mi archivo server.policy se ve así:

grant { 
    permission java.security.AllPermission; 
}; 

Pero también he intentado éste ...

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

... y éste (y varios otros :-():

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

Pero en todos los casos el resultado es el mismo. Y sí, el archivo de política está en la ruta (veo una Excepción de Parse, cuando escribo declaraciones incorrectas en el archivo de política). Probé varias otras constelaciones "/" y "\" pero no tiene ningún efecto.

utilizo Eclipse y mis VM-parámetros son así:

-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 remoto-Interface compilado y la clase de interfaz de aplicación (LoginImpl) las clases se encuentran en esta ruta: "C:/projx/servidor/serverProj/bin/usermanager/". El método principal, donde instanciate y volver a vincular el empalme hacia el registro está en otro paquete y se parece a esto:

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

¿Alguien tiene un consejo para mí? Gracias por ayudar.


Así que la pregunta es la misma (la java.rmi.UnmarshalException muestra que el cambio de la base de código no es la solución de mi AccessControlException). Y no: no quiero comprar un plugin "G B" ;-).

+0

Tuve un problema similar. Lo resolví a través de este enfoque: https://stackoverflow.com/a/44275905/1509058 –

Respuesta

7

La concesión de todos los permisos a todos los códigos es realmente mala. Cualquier cliente de RMI podría hacer lo que quisiera como usuario conectado. En general, intente restringir los permisos tanto como sea razonable, particularmente cuando no sabe de dónde viene el código.

Volviendo a la pregunta ...

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

Eso debería ser "file:///C:/..." o "file:/C:/...". Piensa en http. "http://C:/..." se refiere a un host llamado C. Tenga en cuenta que el mensaje de excepción ha eliminado los dos puntos, porque eso es solo la sintaxis del número de puerto.

La razón por la que obtiene una excepción de seguridad incluso si otorga permisos a todo el código, es que RMI está restringiendo los permisos a los apropiados dado las URL implicadas (utilizando AccessController doPrivileged dos forma de argumento).

+0

¡Hola! Me pareció muy útil. ¿Podría decirme dónde almacenar el archivo de texto server.policy? – user1799214

+0

@ user1799214 El póster original usó el directorio de trabajo actual del servidor hte, especificando con '-Djava.security.policy = server.policy'. (Como siempre, eliminar las restricciones en el código de acceso a la red es complicado de realizar de manera segura.) –

0

Creo que la excepción está saliendo de rmiregistry. Esta parte del rastro de la pila es lo que me hace pensar eso. El apéndice de rmiregistry está recibiendo la excepción y devolviéndola como resultado del intento de volver a enlazar.

 
    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) 

intente ejecutar rmiregistry con -J-Djava.security.policy=all.policy, donde el archivo de política otorga todos los permisos (por lo menos para que funcione).

Finalmente, es posible que también desee cambiar a una URL de base de código HTTP, solo para que pueda ejecutar clientes en una máquina separada de la de su servidor.

7

Ok, lo tengo. No fue ´ t la propiedad rmiregistry (funciona sin ningún parámetro). Había dos errores en mi código base VM-Parámetro:

-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 

... en lugar debería tener este aspecto:

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

=> file:/(sólo una barra) + paquete de coda mal.

Pero la traza era tan confusa, mi primer pensamiento fue, que algo debe estar mal con el archivo de política o la configuración de la política.

Sin embargo: gracias por su ayuda y feliz piratería. ;-)

2

También puede establecer mediante programación la propiedad 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(); 
} 

por alguna hipotética Hello servicio RMI.

+0

Parece que no puedo establecer esta propiedad. Mi Java parece no permitirme ejecutar la operación de configuración. –

0

Tengo una pregunta muy corto ...

¿Por qué usa esta ruta: "file: // C:/projx/servidor/serverProj/bin/UserManager" supongo que está en las ventanas, y los caminos en las ventanas están escritos C: \ projx ...... lo pregunto porque tengo algunos problemas con RMI también, pero tengo el archivo de política de esta manera:

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

se que está mal?

0

Simplemente funciona bien cuando arreglé la variable CLASSPATH antes de iniciar el registro de rmi. Creo que la idea es que el Registro de RMI cargue sus stubs remotos y debería tener acceso. Eso fue fácil al poner mis clases en CLASSPATH antes de ejecutar el registro. Por lo tanto, no está relacionado con ninguna otra razón, como JDK 7 o file:/protocol.