# [RMI] Allgemeine Fragen



## siassei84 (23. Jan 2007)

Hallo,

bei meinem kleinen "privaten" Projekt kommt nun die Erstellung des Servers. Die
Anwendung soll mittels RMI im Netz bereitstellen. Um die Sicherheit zu
erhöhen, muss dies Verbindung möglichst sicher gestalltet werden. Somit
kommt nur die Verbindung von RMI + SSL in betracht. Doch wie geht man
dies am besten an, da ich RMI nur vom hören und sagen kenne.

So also,
- es müssen zwei Registry vorhanden sein, da die Protokolle TCP/IP und
UDP verwendet werden sollen
- die Clients müssen sich einer Auth. unterziehen. Damit meine ich, dass
der Client zusätzlich nochmal zwei char[] mit jeweils 256 chars
übermitteln soll. Dies soll sicherstellen, dass sich nur Regestrierte Clients sich mit
dem Server verbinden
- danach soll der angefordete Dienst ausgeführt werden

bei meiner Suche nach vorgefertigten Klassen bin ich auf
javax.rmi.ssl.SslRMIClientSocketFactory und
javax.rmi.ssl.SslRMIServerSocketFactory gestossen. Doch wie kann ich nun
den 2 Punkt erfüllen? Müsste man hierfür jeweils die Klassen
überschreiben oder kann dies auch einfacher gelösst werden? Und wofür
stehen die Parameter für
SslRMIServerS...(enabledCipherSuites, enabledProtocols, port)?
enabledCipherSuites = ?
enabledProtocols = freigegebene Protokolle z.B. "UDP" ?
port = lokaler Port, auf dem die Registry läuft ?

Unter http://java.sun.com/j2se/1.5.0/docs/guide/rmi/socketfactory/index.html
bin ich auf eine Beschreibung zum erstellen von eigene Sockets und
Factorys gestossen. Hier müsste ich doch dann das Auth.-Verfahren
festlegen können. Gut, da ich in die Methode ServerSocket->accept() die Auth
 packen würde, müsste ich noch zwei kleine Fragen stellen.
1.) Darf diese Methode null zurück geben? (Auth. ist fehlgeschlagen)
2.) Wird der Methodenaufruf nur von einem Thread gesteuert oder wird pro
accpet()-Aufruf  ein Thread zu verfügung gestellt?
Oder kann ich das beinflussen? Wenn ja, bei welcher Klasse?

Oder habe ich nun die falsche Richtung eingeschlagen?

MfG,
  Thomas


----------



## Yzebär (23. Jan 2007)

Ich glaube du bist schon eine Ebene zu tief. Wenn du RMI verwenden willst, brauchst du dich normalerweise um Sockets und Protokolle nicht zu sorgen. Wenn du eine sichere Übertragung wünschst, dann verschlüssele doch einfach alles was an Daten übertragen wird.


----------



## siassei84 (23. Jan 2007)

Yzebär hat gesagt.:
			
		

> Ich glaube du bist schon eine Ebene zu tief. Wenn du RMI verwenden willst, brauchst du dich normalerweise um Sockets und Protokolle nicht zu sorgen. Wenn du eine sichere Übertragung wünschst, dann verschlüssele doch einfach alles was an Daten übertragen wird.



Hallo Yzebär,

natürlich ist das von mir eine kleine spielerei, doch sollte der Overhead beim Verschüsseln mit beachtet werden und das Problem des Mithörens wurde damit auch nicht wirklich gelösst.

Ich habe mir meinen Aufsatz *nöff* auch mal durchgelessen. Könnte es sein, dass er nicht verständlich ist  Jeep, auf jeden Fall. Nochmal von vorn.
Bei meiner Anwendung müssen sich die Clients erstmal über eine Socket-Verbindung regestrieren. Hierbei erhalten sie einen Key [String]. Mit diesem Key + ihrere Client-Id sollen sie danach die Dienste des Servers in anspruchnehmen können. Da der RMi-Server vom WWW aus zugänglich sein soll und irgendwie muss man ja den Client identifizieren. *So jetzt mal eine kleine Denkpause*
  :### 
SSL: Dient  *nur* zur sicheren Übertragung von Daten

Übrigens, es sollen zwei RMi-Server auf dem Rechner laufen
1. RMI + SSL -> dieser Server bearbeit "geheime" Daten
2. RMI -> dieser Server stellt ein paar Standart Funktionen bereit.

So, wo kann ich nun die Ident. der Clients unterbringen, da für die Auth. ein Zeitaufwend von Stream.getSoTimeOut(). 
Mein gedanke ist, die Auth. in die ServerSocket.accept() zu integrieren, doch die Methode soll nicht dadurch blockiert werden oder wie lösst ihr den so was :?:  

MfG,
  Thomas


----------



## Yzebär (23. Jan 2007)

Warum über den ganzen Socket-Accept-Blabla-Kram? Der Client stellt eine Verbindung zum RMI-Server her und will sich dort registrieren(Methode bei der Parameter zur Identifizierung übergeben werden), bei einer erfolgreichen Registrierung gibt der Server einen Schlüssel zurück, den der Client beim Aufruf der anderen Methoden mit angeben muß. Der Schlüssel wird bei jeder Anmeldung neu generiert (Server kann sich auch merken, wer welchen Schlüssel bekommen hat und bei Aufrufen abgleichen) und verfällt nach einem Timeout (Client benutzt den Schlüssel nicht, Verbindung unterbrochen etc.) oder wenn sich der Client abmeldet (kann automatisch passieren, wenn der Client beendet wird).

Du könntest auch zwei RMI-Server machen, einen für die Authentifizierung und einen der nach erfolgreicher Authentifizierung dem User zur Verfügung gestellt wird (dabei kann man bspw auch individuelle Ports verwenden, der Server wird dann wieder "geschlossen" sobald der User sich abmeldet) usw... man kann das Spiel ziemlich weit treiben. Wenn man sich merkt welchen Key man an welche IP vergeben hat, sollte das eigentlich auch reichen.


----------



## siassei84 (23. Jan 2007)

:idea:  Thanks



> Der Client stellt eine Verbindung zum RMI-Server her und will sich dort registrieren(Methode bei der Parameter zur Identifizierung übergeben werden)



Welche Methode ist für die Parameter zuständig (Server- u. Clientseitig)


----------



## siassei84 (24. Jan 2007)

Eine Nacht darüber geschlafen und *schwupps* . Irgendwie hat sich mein Verstand gestern komplett ausgeschaltet und somit war alles nur *Käse* :bahnhof:  Jedenfalls muss ich das ganze noch einmal von vorn überarbeiten. :### 

Bitte korregiert mich, wenn ich etwas falsch interpretiere bzw. verstanden habe. Mit 
	
	
	
	





```
LocateRegistry.createRegistry(port, cf, sf)
```
 kann ich einen RMI-Dienst an dem Port xyz per Code starten. An diesen Dienst können absofort Remote-Objekte gebunden werden. Diese Objekte können nun von anderen Clients (falls der Stub & Co. bekannt ist) genutzt werden. Die Remote-Objekte können auch wieder vom Dienst genommen werden. *Doch nun eine blöde Frage*, kann man den Server auch wieder irgendwie beenden? Oder geht das nur über das Abwürgen der Application mittels
	
	
	
	





```
System.exit()
```

Nun besitzt ich eine DB wo sich ein Client registrieren muss, um sich mit dem RMI-Dienst verbinden zu können.
Table->Client:
  - Id
  - Password
Wenn sich nun der Client sich mit dem RMI-Dienst verbinden möchte, dann soll dieser sich zuerst über eine Socket-Verbindung Auth. und bekommt bei einer erfollgreichen Überprüfung einen Key zugesand. Dieser Key wird auch auf Server-Seite in einer HashMap (Key = Client->Id ; Value = Key) abgespeichert. Der Client soll also nur dann eine erfolgreiche RMI-Verbindung bekommen, wenn dieser sich mittels Id + Key nochmals bei diesem erfolgreich Auth. hat.
Sinn des ganzen: Der Key ist auf eine bestimmte Zeit begrenzt und soll die Nutzung des Servers für den Client begrenzen bzw. der Client hat ein gewisses Zeitfenster um sich nun am RMI-Server anzumelden.

- Wo bindet man die Überprüfung am besten ein?

- Meine Idee ist, die Überprüfung in die accept()-Methode zu schreiben, doch was passiert hier, wenn diese Fehlschlägt? Socket schließen + Rückgabe oder null ?

- Kann ich beim Aufruf der Methoden eines Interfaces, in der Methode irgendwie feststellen, wer diese gerade aufgerufen hat?

```
public interface Hello extends Remote {
    public void hello();
}

class HelloImpl implements Hello {
   public void hello() {
        // kann ich nun hier irgendwie feststellen, wer diese Methode aufgerufen hat?
        // Gibt es irgendwelche interfaceses mit Parameterübergabe von der Serverseite aus?
        // z.B. in der Form:
       // public interface HelloAttr extends RemoteAttribute {
       //     public void hello(ServerEvent event);
       // }
       // ???
   }
}
```

- Gibt es nun eine Methode, mit der ich auslesen kann, wie lange der Client den Server genutzt hat? (z.B. In der Form eines Listeners -> connected(SessionEvent event) ... )

MfG,
  Thomas[/code]


----------

