No es un bug, es una característica no documentada

sábado, 30 de enero de 2016

Procesos y servicios. RMI (I)

En RMI intervienen dos progamas java que están ejecutándose en el mismo o distintos ordenadores.

Uno de ellos, llamado servidor, “publica” algunos de los objetos/clases que tiene instanciadas, es decir, los pone visibles desde la red, de forma que otros programas java puedan llamar a sus métodos.

El otro programa, llamado cliente, localiza en el servidor el objeto publicado y llama a sus métodos. Estos métodos se ejecutan en el programa servidor y devuelven un resultado (por el return habitual) que recoge el cliente en su ordenador.

El cliente se queda “colgado” en la llamada hasta que el servidor termina de ejecutar el código y devuelve un resultado.


Los objetos que comparten el servidor se conocen como objetos remotos.



a)      Se crea una interface (remota) con los métodos que queremos que se publiquen, es decir, los métodos que queremso que pueda llamar el cliente
·         Esta interface debe heredar de la interface Remote.
·         Todos los métodos de ésta interface deben lanzar una RemoteException.
b)      Se implementa la interface remota creando una clase que herede de UnicastREmoteObjet con un constructor que lance una RemoteException.

public class ObjetoRemoto extends java.rmi.server.UnicastRemoteObject implements InterfaceRemota{
      public ObjetoRemoto() throws java.rmi.RemoteException{super();}
      public int suma(int a, int b){
            return a + b;
      }
}

c)       Se compila de forma habitual
d)      Al fichero .class se le pasa el comando rmic (está en $JAVA_HOME/bin) para generar el objeto stub.

rmic paquete.ObjetoRemoto

e)      Se inicia el servicio de registro RMI. Antes de lanzar nuestro servidor, debemos lanzar un programa llamado rmiregistry que también viene con java (está en $JAVA_HOME/bin). Este programa es el que realmente sabe todos los objetos que se publican en este ordenador. La llamada Naming.rebind() en realidad coneca con rmiregistry en este ordenador y le avisa que ObjetoRemoto debe publicarse al exterior.
Rmiregistry necesita encontrar la clase ObjetoRemoto_Stub.class, así que en el servidor debemos fijar la propiedad java.rmi.server.codebase con el path, en formato url, desde el que rmiregistry puede acceder a esta clase.

System.setProperty("java.rmi.server.codebase", "file:/un_path/");

f)       Se lanza el servidor
g)      En el cliente. Se escribe la clase cliente

InterfaceRemota objetoRemoto = (InterfaceRemota)Naming.lookup("//IP_del_Servidor/ObjetoRemoto");
System.out.println("2 + 3 = ");
System.out.println(objetoRemoto.suma(2, 3));

h)      Se compila de forma habitual. Para compilar necesitaremos el fichero InterfaceRemota.class
i)        Se lanza el cliente. Si no hemos puesto RMISecurityManager, necesitaremos los ficheros InterfaceRemota.class y ObjetoRemoto_Stub.class para ejecutar.

Arrancar un RMISecurityManager y escribir un fichero java.policy de permisos es peligroso por lo siguiente:
  • Si no instalamos el RMISecurityManager, tenemos una seguridad por defecto bastante restrictiva. Si no sabemos, es mejor dejar la de defecto.
  • Si instalamos el RMISecurityManager, estamos habilitando una cosa llamada carga dinámica de clases. La carga dinámica de clases consiste en que un cliente pueda enviarnos una clase hecha por él y que no esté en el servidor. Esa clase puede tener código malicioso.
  • Si instalamos el RMiSecurityManager, las clases tanto del servidor como las cargadas dinámicamente de los clientes, tienen permiso para hacer aquellas cosas que se les permite en el fichero java.policy. Es decir, el fichero java.policy dice si una clase concreta tiene o no permisos para escribir o leer en disco duro, establecer sockets, etc. En muchos tutoriales, para evitar problemas en el ejemplo y no extenderse en explicaciones, ponen el fichero java.policy con todos los permisos para todo el mundo. Cualquier clase que venga de un cliente podría borrarnos el disco duro.
  • Por ello se aconseja no poner RMISecurityManager, salvo que se necesite carga dinámica de clases. En ese caso, no dejar el fichero java.policy con todos los permisos para todo el mundo.

0 comentarios:

Publicar un comentario