Java RMI (Remote Method Invocation)

Java RMI
(Remote Method Invocation)
RPC in JAVA
Le RMI introducono la possibilità di richiedere
esecuzione di metodi remoti in JAVA integrando il
tutto con il paradigma OO
Accesso ad oggetti remoti
In Java non sono possibili riferimenti remoti
C1 instance
CLASS server S1
S1 instance
S1 instance
state
operations
Supporto di INTEGRAZIONE
Definizioni e generalità
per la DISTRIBUZIONE
Insieme di politiche e meccanismi che permettono ad
un’applicazione Java in esecuzione su una macchina
di invocare i metodi di un oggetto di una applicazione
Java in esecuzione su una macchina remota
Viene creato localmente solo il riferimento ad
un oggetto remoto, che è invece effettivamente
attivo su un nodo remoto
Un programma cliente invoca i metodi attraverso
questo riferimento locale
ma si possono costruire con RMI
Remote Method Invocation
due proxy,
stub dalla parte del cliente,
skeleton dalla parte del servitore
C1 instance
S1 instance
Unico ambiente di lavoro
come conseguenza del linguaggio Java ma
Eterogeneità di ambienti
C1 Stub
CLIENT node
Reti di calcolatori, Java RMI - 1
S1 Skeleton
SERVER node
Reti di calcolatori, Java RMI - 2
Architettura
Caratteristiche
Registry
Modello a oggetti distribuito
RMI System
Client Program
Server Program
Stubs
Skeletons
Remote Reference Layer
Remote Reference Layer
Transport Layer
Stub: proxy locale su cui vengono fatte le invocazioni
destinate all’oggetto remoto
Skeleton: entità remota che riceve le invocazioni fatte sullo
stub e le realizza effettuando le corrispondenti chiamate sul
server
Registry: servizio di nomi che consente al server di
pubblicare un servizio e al client di recuperarne il proxy
Remote Reference Layer:
- fornisce il supporto alle chiamate inoltrate dallo stub
- localizza il server RMI relativo all’oggetto remoto richiesto
Transport Layer:
definisce e supporta la semantica
dell’invocazione e della comunicazione, gestisce le
connessioni (TCP/IP, timeout) e le trasmissioni (sequenziali,
serializzate), usando un protocollo proprietario
Reti di calcolatori, Java RMI - 3
Nel modello ad oggetti distribuito di Java un oggetto
remoto consiste in:
- un oggetto i cui metodi sono invocabili da un'altra
JVM, potenzialmente in esecuzione su un host
differente
- un oggetto descritto tramite interfacce remote che
dichiarano i metodi accessibili da remoto
Chiamata locale vs. chiamata remota
Il cliente invoca un metodo di un oggetto non locale
Sintassi: uguale => trasparenza
Chiamata sincrona
Semantica: diversa
Chiamate locali:
affidabilità ≈ 100%
Chiamate remote: uso di comunicazione
possibilità di fallimento
semantica “at most once” con uso TCP
Server remoto come locale:
Ogni chiamata esegue in modo indipendente e
parallelo (?)
Reti di calcolatori, Java RMI - 4
SERVIZIO REMOTO RMI
Uso di RMI
Interfacce e Implementazione
Per sviluppare un’applicazione distribuita usando RMI
si deve:
Separazione tra
definizione del comportamento => interfacce
implementazione del comportamento => classi
Per realizzare componenti utilizzabili in remoto:
1. definizione del comportamento Ö
metodi disponibili in interfaccia che
- estende java.rmi.Remote e
- propaga java.rmi.RemoteException
2. implementare comportamento Ö
il server specificato in una classe che
- implementa l’interfaccia definita
- estende
1. Definire interfacce e implementazioni dei server
utilizzabili in remoto (implementazioni?)
2. Compilare le classi (con javac) e generare stub e
skeleton (con rmic) delle classi utilizzabili in
remoto
3. Pubblicare il servizio
- attivare il registry
- registrare il servizio
(il server deve fare una bind sul registry)
4. Il cliente deve ottenere il riferimento all’oggetto
remoto tramite il name service, facendo una
lookup sul registry
java.rmi.UnicastRemoteObject
A questo punto l’interazione tra il cliente e il server
può procedere
N.B.: questa è una descrizione di base, dettagli sul
registry e sul caricamento dinamico delle classi
saranno dati in seguito
Reti di calcolatori, Java RMI - 5
Reti di calcolatori, Java RMI - 6
Esempio:
servizio di echo remoto
Implementazione del Server
public class EchoRMIServer
extends java.rmi.server.UnicastRemoteObject
implements EchoInterface{
Definizione dell’interfaccia del servizio
public interface EchoInterface
extends java.rmi.Remote
{
String
getEcho(String echo)
throws java.rmi.RemoteException;
// Costruttore
public EchoRMIServer()
throws java.rmi.RemoteException
{ super(); }
// Implementazione del metodo remoto
dichiarato nell'interfaccia
public String getEcho(String echo)
throws java.rmi.RemoteException
{ return echo; }
}
public static void main(String[] args){
// Registrazione del servizio
try
{
EchoRMIServer serverRMI =
new EchoRMIServer();
Naming.rebind("EchoService", serverRMI);
}
catch (Exception e)
{e.printStackTrace(); System.exit(1); }
}
}
Reti di calcolatori, Java RMI - 7
Reti di calcolatori, Java RMI - 8
Implementazione del Client
Compilazione
public class EchoRMIClient
{
// Avvio del Client RMI
public static void main(String[] args)
{
BufferedReader stdIn=
new BufferedReader(
new InputStreamReader(System.in));
javac
try
{
// Connessione al servizio RMI remoto
EchoInterface serverRMI = (EchoInterface)
java.rmi.Naming.lookup("EchoService");
// Notare l’uso di cast
Con il compilatore RMI (con opzione –vcompat in
Java 1.5):
rmic [-vcompat] EchoRMIServer
// Interazione con l'utente
String message, echo;
System.out.print("Messaggio? ");
message = stdIn.readLine();
// Richiesta del servizio remoto
echo = serverRMI.getEcho(message);
System.out.println("Echo: "+echo+"\n");
}
catch (Exception e)
{ e.printStackTrace(); System.exit(1);
}
}
}
EchoInterface.java
EchoRMIClient.java
EchoRMIServer.java
Creazione dello Stub e dello Skeleton
Che genera i file:
EchoRMIServer_Stub.class
EchoRMIServer_Skel.class
Esecuzione
1. Avviamento del registry:
rmiregistry
2. Avviamento del server:
java EchoRMIServer
3. Avviamento del client:
java EchoRMIClient
Reti di calcolatori, Java RMI - 9
Reti di calcolatori, Java RMI - 10
Passaggio di parametri
Serializzazione
Trattamento dei parametri tra pari
Tipo
Tipi primitivi
Oggetti
Metodo Locale
Per valore
Per riferimento
Oggetti Remoti
Esportati
Per riferimento
Metodo Remoto
Per valore
Per valore
(deep copy)
Per riferimento
remoto
Shallow Copy vs Deep Copy
Passaggio per valore => Serializable Objects
Passaggio per riferimento => Remote Objects
Serializable Objects
Oggetti la cui locazione non è rilevante per lo stato
sono passati per valore: ne viene serializzata
l’istanza che sarà deserializzata a destinazione per
crearne una copia locale.
Remote Objects
Oggetti la cui funzione è strettamente legata alla
località in cui eseguono (server)
sono passati per riferimento: ne viene serializzato
lo stub, creato automaticamente dal proxy (stub o
skeleton) su cui viene fatta la chiamata in cui
compaiono come parametri
Reti di calcolatori, Java RMI - 11
Marshalling: processo di codifica degli argomenti e
dei risultati per la trasmissione
Unmarshalling: processo inverso di decodifica di
argomenti e risultati ricevuti
In Java questo problema è risolto attraverso la
semplice serializzazione, fatta in maniera trasparente
dal supporto (copia dei dati trasformati in una
sequenza e un messaggio e trasferiti tra le JVM)
Serializzazione:
trasformazione
di
complessi in semplici sequenze di byte
oggetti
=> metodo writeObject()
su uno stream di output
Deserializzazione: decodifica di una sequenza di
byte e costruzione di una copia dell’oggetto
originale
=> metodo readObject()
da uno stream di input
Utilizzo:
- storage
- trasmissione (parametri e valori di ritorno in RMI)
Reti di calcolatori, Java RMI - 12
Interazione con stream per TX/RX
Esempio
Esempio di storage
Record record = new Record();
FileOutputStream fos = new
FileOutputStream(“data.ser”);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(record);
FileInputStream fis = new
FileInputStream(“data.ser”);
ObjectInputStream ois = new ObjectInputStream(fis);
record = (Record)ois.readObject();
Riprendendo il server di echo
Ö messaggio come oggetto anziché come stringa
public class Message implements Serializable
{
String content;
// … altri eventuali campi
Si possono serializzare soltanto istanze di oggetti
serializzabili, ovvero che:
-
public Message(String msg)
{
content=msg;
}
implementano l’interfaccia Serializable
contengono esclusivamente oggetti (o riferimenti
a oggetti) serializzabili
public String toString()
{
return content;
}
NOTA BENE:
NON viene trasferito l’oggetto vero e proprio ma solo
le informazioni che caratterizzano l’istanza
=> no metodi, no costanti,
no variabili static, no variabili transient
}
Al momento della deserializzazione sarà ricreata una
copia dell’istanza “trasmessa” usando il .class (che
deve quindi essere accessibile!!!) dell’oggetto e le
informazioni ricevute.
Reti di calcolatori, Java RMI - 13
Reti di calcolatori, Java RMI - 14
Stub e Skeleton
Stub e Skeleton garantiscono una parziale trasparenza
e sono oggetti generati dal compilatore RMI che
gestiscono il supporto RMI via
serializzazione/deserializzazione e
comunicazione tra client e server
Procedura di comunicazione:
1. il client ottiene un’istanza dello stub
2. il client chiama metodi sullo stub
3. lo stub:
- crea una connessione con lo skeleton
(o ne usa una già esistente)
- fa la serializzazione delle informazioni per la
chiamata (id del metodo e argomenti)
- invia le informazioni allo skeleton
4. lo skeleton:
- fa deserializzazione dei dati ricevuti
- effettua la chiamata sull’oggetto che
implementa il server
- fa serializzazione del valore di ritorno
e invio allo allo stub
5. lo stub:
- fa deserializzazione del valore di ritorno e
restituzione del risultato al client
Reti di calcolatori, Java RMI - 15
Stub
Estende
java.rmi.server.RemoteStub
Implementa
java.rmi.Remote
InterfacciaRemotaServer
(es. EchoInterface)
Realizza le chiamate ai metodi dell’interfaccia remota
del server usando il metodo invoke(…)
di java.rmi.server.RemoteRef
public final class EchoRMIServer_Stub
extends java.rmi.server.RemoteStub
implements EchoInterface, java.rmi.Remote
{
…
// implementazione di getEcho
public Message getEcho(Message message)
throws java.rmi.RemoteException
{
try
{ …
// creazione della chiamata
java.rmi.server.RemoteCall remotecall =
super.ref.newCall(this, operations, 0,
0xca41fff3e3260b7aL);
// serializzazione dei parametri
try
{
ObjectOutput objectoutput =
remotecall.getOutputStream();
objectoutput.writeObject(message);
}
// cattura eccezioni di marshalling
…
Reti di calcolatori, Java RMI - 16
Stub segue
Skeleton
Implementa
// invio della chiamata
super.ref.invoke(remotecall);
// deserializzazione del valore di ritorno
Message message1;
try
{
ObjectInput objectinput =
remotecall.getInputStream();
message1 =
(Message)objectinput.readObject();
}
// cattura eccezioni di unmarshalling
…
// segnalazione chiamata andata a buon fine
finally
{
super.ref.done(remotecall);
}
// restituzione del risultato
return message1;
}
// cattura varie eccezioni
…
}
…
}
Reti di calcolatori, Java RMI - 17
java.rmi.server.Skeleton
Inoltra le richieste al server usando il
metodo dispatch(…)
public final class EchoRMIServer_Skel implements Skeleton
{
…
public void dispatch(Remote remote,
RemoteCall remotecall, int opnum, long hash)
throws Exception
{
// validazione e verifica di errori
…
EchoRMIServer echormiserver = (EchoRMIServer)remote;
switch(opnum)
{
case 0: // '\0'
Message message;
try
{
// deserializzazione dei parametri di invocazione
ObjectInput objectinput =
remotecall.getInputStream();
message = (Message)objectinput.readObject();
}
catch(IOException ioexception1)
{
throw new UnmarshalException("error
unmarshalling arguments", ioexception1);
}
catch(ClassNotFoundException classnotfoundexception)
{
throw new UnmarshalException("error ...”
unmarshalling arguments", classnotfoundexception);
}
finally
{
remotecall.releaseInputStream();
}
Reti di calcolatori, Java RMI - 18
Skeleton segue
// effettiva invocazione del metodo sul server
Message message1 = echormiserver.getEcho(message);
try
{
// serializzazione del valore di ritorno
ObjectOutput objectoutput =
remotecall.getResultStream(true);
objectoutput.writeObject(message1);
}
catch(IOException ioexception)
{
throw new MarshalException("error
marshalling return", ioexception);
}
break;
default:
throw new UnmarshalException("invalid ...");
}
}
…
}
Chi genera i thread che devono operare
sull’oggetto server, se non lo skeleton?
Questo si lega al fatto che skeleton e stub
sono generati non come sorgenti, ma come
class?
Interazione Client/Server:
Socket e Thread
Client
L’invocazione di un metodo remoto implica una connessione
TCP (Socket stream) con l’oggetto remoto
Condivisione delle connessioni tra la JVM client e la
JVM server:
richiesta di connessione per una stessa JVM
se c’è una connessione aperta Ö riuso
se non c’è una connessione aperta Ö nuova
Al completamento di una operazione la connessione
viene liberata e rimane attiva fino allo scadere di un
intervallo di timeout
RMI permette a più thread clienti di accedere ad uno stesso
oggetto server gestendo in modo automatico la
concorrenza delle operazioni
Ö l’implementazione del cliente non deve preoccuparsi
In caso di richieste da parte della stessa JVM, il canale di
comunicazione
unico
può
produrre
effetti
di
sequenzializzazione (era ciò che accadeva nelle prime
implementazioni)
Reti di calcolatori, Java RMI - 19
Reti di calcolatori, Java RMI - 20
Server
RMI Registry
Dipende
tutto
dall’implementazione.
Nel
seguito
consideriamo una possibile e semplice implementazione
concorrente.
L’esportazione di un oggetto remoto provoca la creazione di
• diversi thread per la gestione delle richieste (Server
Socket)
• un thread che riceve le richieste (Listener Thread)
associati all’oggetto remoto
Localizzazione del servizio: un client in esecuzione
su una macchina ha bisogno di localizzare un server a
cui vuole connettersi, che è in esecuzione su un’altra
macchina. Tre possibili soluzioni:
• Il client conosce staticamente dov’è il server
• L’utente dice all’applicazione client dov’è il server
• Un servizio standard (naming service) in una
locazione ben nota, che il client conosce,
funziona come sistema di nomi
Condivisione delle server socket e dei listener: server in
esecuzione nella stessa JVM possono condividere la porta
d’ascolto (soluzione di default se non la specificano) e il
listener che ne gestisce le richieste
Java RMI utilizza un naming service: RMI Registry
Ogni richiesta viene gestita da
• un thread che esegue la richiesta (Server Thread)
Mantiene un insieme di coppie {name, reference}
Name: stringa arbitraria non interpretata
Condivisione dei server thread: allocazione di un pool di
thread; all’accettazione di una nuova richiesta un Server
Thread viene estratto ed utilizzato.
E se i thread del pool vengono tutti allocati? Soluzioni
possibili?
In ogni caso: RMI permette a più thread di accedere ad
uno stesso oggetto server (gestione concorrente delle
richieste)
Ö l’implementazione dei metodi remoti
deve essere thread-safe
Reti di calcolatori, Java RMI - 21
Name
Echo
Server
Reference
Echo
Daytime
Server
Daytime
Login
Login
Server
Trasparenza alla locazione?!?
Reti di calcolatori, Java RMI - 22
Operazioni
Implementazione del Registry
Metodi della classe java.rmi.Naming:
Il Registry è un server RMI
public
public
public
public
public
Classe d’implementazione:
sun.rmi.registry.RegistryImpl
static
static
static
static
static
void bind(String name, Remote obj)
void rebind(String name, Remote obj)
void unbind(String name)
String[] list(String name)
Remote lookup(String name)
name -> combina la locazione del registry e il nome
logico del servizio, nel formato:
Interfaccia: java.rmi.registry.Registry
public interface Registry extends Remote {
public static final int REGISTRY_PORT = 1099;
//registryHost:port/logical_name
public Remote lookup(String name)
throws RemoteException, NotBoundException,
AccessException;
public void bind(String name, Remote obj)
throws RemoteException, AlreadyBoundException,
AccessException;
public static void rebind(String name, Remote obj)
throws RemoteException, AccessException;
public static void unbind(String name)
throws RemoteException, NotBoundException,
AccessException;
public static String[] list(String name)
throws RemoteException, AccessException;
A default:
registryHost = macchina su cui esegue
il programma che invoca il metodo
port = 1099
Il Registry è un server RMI
in esecuzione su registryHost
in ascolto su port
}
Ognuno di questi metodi crea una connessione
(socket) con il registry identificato da host e porta
Remote è il riferimento remoto
Perchè usare anche la classe Naming?
Reti di calcolatori, Java RMI - 23
Reti di calcolatori, Java RMI - 24
BOOTSTRAP
Uso del Registry
Problema di bootstrapping anche per localizzare il
registry Ö uso delle classi Naming e LocateRegistry
Due possibilità:
• Naming: metodi statici, no istanza
• LocateRegistry implementa i metodi
public static Registry createRegistry(int port)
public static Registry createRegistry(int port,
RMIClientSocketFactory csf,
RMIServerSocketFactory ssf)
public static Registry getRegistry()
public static Registry getRegistry(int port)
public static Registry getRegistry(String host)
public static Registry getRegistry(String host,
int port)
public static Registry getRegistry(String host,
int port, RMIClientSocketFactory csf)
1. Usare il programma rmiregistry di Sun, lanciato
specificando o meno la porta:
rmiregistry
rmiregistry 10345
Ö istanza separata della JVM
Ö struttura e comportamento standard
2. Creare all’interno del codice un proprio registry:
public static Registry createRegistry(int port)
Ö stessa istanza della JVM
Ö struttura e comportamento personalizzabile
(es. organizzazione gerarchica)
Soluzione al bootstrapping per il registry:
1. Naming.”metodo()” con host e porta
1. Invocazione di LocateRegistry.getRegistry() che
restituisce lo stub del registry
2. Invocazione di “metodo()” sullo stub
Reti di calcolatori, Java RMI - 25
Reti di calcolatori, Java RMI - 26
Sicurezza del registry
Organizzazione gerarchica Registry
Problema: accedendo al registry
(individuabile interrogando tutte le porte di un host)
è possibile ridirigere per scopi maliziosi le chiamate ai
server RMI registrati
(es. list()+rebind())
Un registry è un server RMI
=> è possibile registrarlo in un altro registry
Soluzione:
i metodi bind(), rebind() e unbind() sono invocabili
solo dall’host su cui è in esecuzione il registry
Ö
non si accettano modifiche della struttura client/server
da nodi esterni
Registry ourRegistry =
LocateRegistry.createRegistry(OUR_PORT);
Registry preexistingRegistry =
LocateRegistry.getRegistry(1099);
preexixtingRegistry.rebind
(“secondary registry”, ourRegistry);
Printer Registry
Name Reference
Primary Registry
Name
Ö sull’host in cui vengono effettuate le chiamate
al registry deve essercene almeno uno in
esecuzione
Registro Stampanti
Registro Installazioni
...
Reference
Postscript
Pdf
...
Program Registry
Name Reference
Antivirus
IDE
...
...
Ma…
• Tutti i registry si trovano sulla stessa macchina
dove è attivato il primary registry
• Lato client devo gestire una duplice
interrogazione
• RMI registry non supporta in alcun modo la
negoziazione dei servizi
Reti di calcolatori, Java RMI - 27
Reti di calcolatori, Java RMI - 28
Distribuzione delle classi
Classpath ed Esecuzione
In una applicazione RMI è necessario che siano
disponibili gli opportuni file .class nelle località che lo
richiedono
(per l’esecuzione o per la deserializzazione)
Rmiregistry, server e client devono poter accedere
alle classi necessarie per l’esecuzione. Si presti quindi
particolare attenzione al direttorio dove vengono
lanciati l’rmiregistry, il server e il client
Il Server deve poter accedere a:
•
•
•
•
interfacce che definiscono il servizio
implementazione del servizio
stub e skeleton delle classi di implementazione
altre classi utilizzate dal server
Il Client deve poter accedere a:
•
•
•
•
interfacce che definiscono il servizio
stub delle classi di implementazione del servizio
classi del server usati dal client (es. valori di ritorno)
altre classi utilizzate dal client
È necessario:
1. localizzare il codice (in locale o in remoto)
2. effettuare il download (se in remoto)
3. eseguire in modo sicuro il codice scaricato
Reti di calcolatori, Java RMI - 29
In particolare, ipotizzando di avere tutti i file .class nel
direttorio corrente (“.”), e di lanciare rmiregistry, client,
e server dal direttorio corrente, bisogna aggiungere al
CLASSPATH tale direttorio
Sotto Linux: ciò è possibile aggiungendo nella propria
directory HOME il file ".profile" (creandolo se
non esiste). In particolare, il file .profile deve
contenere le seguenti linee per aggiungere il
direttorio corrente al CLASSPATH:
CLASSPATH=.:$CLASSPATH
export CLASSPATH
E se volessimo lanciare il client, il server, e
l’rmiregistry in direttori diversi?
Si noti che questa è la modalità standard in Linux per
aggiungere/modificare una variabile di ambiente.
Nelle FAQ del corso, si veda anche il caso della
variabile di ambiente PATH
Reti di calcolatori, Java RMI - 30
Localizzazione del codice
Utilizzo del codebase
Sia il cliente sia il servitore devono avere a
disposizione le classi di supporto per la interazione
Il codebase viene usato dal client per scaricare le
classi necessarie relative al server (interfaccia, stub,
oggetti restituiti come valori di ritorno)
Le informazioni relative a dove reperire il codice delle
classi - se non disponibile localmente - sono
memorizzate sul server e passate al client by need
⇒ server RMI mandato in esecuzione specificando
nell’opzione
java.rmi.server.codebase
l’URL da cui prelevare le classi necessarie.
L’URL può essere:
una directory del file system locale (file://)
l’indirizzo di un server ftp (ftp://)
l’indirizzo di un server http (http://)
Il codebase viene usato dal server per scaricare le
classi necessarie relative al client (oggetti passati
come parametri nelle chiamate)
Il codebase è una proprietà del server che viene
annotata nel reference pubblicato sul registry
Le classi vengono cercate sempre prima nel
CLASSPATH locale, solo in caso di insuccesso
vengono cercate nel codebase
Reti di calcolatori, Java RMI - 31
Reti di calcolatori, Java RMI - 32
CODEBASE
ESEMPIO
Sia il server che il client devono essere lanciati
specificando il codebase che indica dove sono
disponibili le rispettive classi
Esempio con client e server sullo stesso host e classi
in direttori diversi:
java
–Djava.rmi.server.codebase
= file://c:\…\RMIdir\ServerDir\
EchoRMIServer
java
–Djava.rmi.server.codebase
= file://c:\…\RMIdir\ClientDir\
EchoRMIClient localhost
Client e Server su host diversi e classi scaricabili via
http:
java
–Djava.rmi.server.codebase
= http://server_host_name/…/RMIdir/ServerDir
EchoRMIServer
java
–Djava.rmi.server.codebase
= http://client_host_name/…/RMIdir/ClientDir
EchoRMIClient server_host_name
server_host
client_host
JVM 1
RMIregistry
RMIregistry
RMI
RMIClient
Client
RMI
RMIServer
Server
server&client_host
JVM 1
rmiregistry
rmiregistry
EchoRMIServer_stub
EchoInterface
JVM 3
JVM 2
JVM 2
JVM 3
EchoRMIServer_stub
EchoInterface
RMI
RMIClient
Client
RMI
RMIServer
Server
Message
EchoRMIServer_stub
Web
Webserver
server
Message
Web
Webserver
server
EchoRMIServer_stub
c:\…\ServerDir\
c:\…\ClientDir\
File System
Reti di calcolatori, Java RMI - 33
Reti di calcolatori, Java RMI - 34
Ambienti separati e protetti
Ogni JVM definisce ambienti di esecuzione
differenziati e protetti per diverse parti, in particolare
da remoto
Si usano ClassLoader come separatori associati a
SecurityManager per la specifica di protezione
Download del codice
Utilizzo di RMIClassLoader
usato dal supporto RMI per caricare le classi
FILE di POLICY
Il file di policy a cui il Secutiry Manager fa riferimento
per il controllo degli accessi contiene le autorizzazioni
consentite
Esempio:
grant {
permission java.net.SocketPermission
"*:1024-65535",
"connect, accept, resolve";
Esecuzione del codice
Utilizzo di RMISecurityManager
permission java.net.SocketPermission
"*:80", "connect";
Istanziato all’interno dell’applicazione RMI, sia client
che server, come controllore degli accessi, per
bloccare quelli non autorizzati
permission java.io.FilePermission
"/home/lfoschini/*", "read";
if (System.getSecurityManager() == null)
{ System.setSecurityManager(
new RMISecurityManager()); }
Sia il server che il client devono essere lanciati
specificando il file con le autorizzazioni che il security
manager deve caricare
Esempio
java -Djava.security.policy = echo.policy
EchoRMIServer
java -Djava.security.policy = echo.policy
EchoRMIClient remoteHost
Reti di calcolatori, Java RMI - 35
};
Il primo permesso consente al client e al server di
instaurare le connessioni necessarie all’interazione
remota (host qualunque, porta utente qualunque,
primitive consentite)
Il secondo permesso consente di prelevare il codice da
un server http (host qualunque, porta 80, connect)
Il terzo permesso consente di accedere in lettura ad un
qualsiasi direttorio del file system locale che sia sottodirettorio di “/home/lfoschini” (concessa solo lettura)
Reti di calcolatori, Java RMI - 36
Bibliografia
Sito della Sun:
http://java.sun.com/products/jdk/rmi/
W.Grosso, “Java RMI”, Ed. O’Reilly (2002)
E. Pitt, K. McNiff, “java.rmi, The Remote Methode
Invocation Guide”, Ed. Addison Wesley (2001)
R. Öberg, “Mastering RMI, Developing Enterprise
Applications in Java and EJB”, Ed. Wiley (2001)
Reti di calcolatori, Java RMI - 37