Reputation: 387
I am developing a secured Banking service in RMI with a GUI both for Server and Client.
The Server must be able to log every operations (new User, deleted User, Withdrawal, Lodgement...) The Client will do these operations. As everything is secured, the Client must at first, create an account with a name and a password in the GUI. After that, the GUI adds the User in the Bank UserList(arrayList) as a new Customer and the User can do several operations. It seems straightforward at first but I think my conception is not correct.
Is it correct to send the whole Bank by RMI ? Because at first I thought Bank would be the server but I cannot find another way to do that. Currently, the Client GUI asks for a login and a password, and receives the Bank by RMI. A User is characterized by a name and a hash of the password.
private String name;
private byte[] passwordDigest;
In fact the GUI is doing every security checking and I don't know if it's relevant. When you type login//password, it will search the login in the Bank and compare the hash of the password. In fact I have the impression that the Client knows too much information because when you have the Bank you have everything..
Does it seem correct or do I need to change my implementation ?
Upvotes: 0
Views: 4068
Reputation: 310875
You need two remote object classes.
The first one is obtained via Naming.lookup()
; it is a singleton; and it contains a login()
method.
This method returns the second remote object, which is not a singleton, not registered in the Registry, and is created anew for every return value. This object contains all the banking methods and also a logout()
method, which unexports it; it probably also implements the Unreferenced
interface so it can detect a dead client, and unexport itself. Because it exists once per client, it can hold client state, and because it can only be obtained by a successful login step it solves your security problem.
public interface Login extends Remote
{
Session login(String username, char[] password /* or whatever */)
throws LoginException, RemoteException;
}
public interface Session extends Remote
{
void logout() throws RemoteException;
void deposit(...) throws RemoteException;
void withdraw(...) throws RemoteException;
}
public class LoginImpl extends UnicastRemoteObject implements Login
{
public Session login(String username, char[] password)
throws LoginException, RemoteException
{
// username/password check; if it fails throw a LoginException
return new SessionImpl(username); // or whatever
}
}
public class SessionImpl extends UnicastRemoteObject implements Session, Unreferenced
{
public void logout() throws RemoteException
{
unexportObject(this, true);
}
public void unreferenced()
{
unexportObject(this, true); // needs to be in a try/catch block of course
}
// etc
}
I described this as the Remote Session pattern in my book in 2001.
Of course you also need transport layer security: see javax.rmi.ssl.
Upvotes: 2
Reputation: 53694
You are misunderstanding how Remote interfaces work. the client does not have the Bank, it only has a reference to a remote instance of a Bank. all the method calls made by the client on the Bank interface are actually turned into remote calls against the remote instance of the Bank (running in the server).
presumably, the security checking is done inside the Bank methods on every method call.
Upvotes: 1