Moved some of the standard work done by Authenticators into the base class.

git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4291 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Ray Greenwell
2006-07-25 19:02:48 +00:00
parent 878129f75d
commit 426edf6ad7
4 changed files with 153 additions and 51 deletions
@@ -21,6 +21,10 @@
package com.threerings.presents.peer.server; package com.threerings.presents.peer.server;
import com.samskivert.io.PersistenceException;
import com.samskivert.util.Invoker;
import com.threerings.presents.data.AuthCodes; import com.threerings.presents.data.AuthCodes;
import com.threerings.presents.net.AuthRequest; import com.threerings.presents.net.AuthRequest;
@@ -49,22 +53,13 @@ public class PeerAuthenticator extends Authenticator
_delegate = delegate; _delegate = delegate;
} }
@Override // documentation inherited @Override
public void authenticateConnection (AuthingConnection conn) public void authenticateConnection (AuthingConnection conn)
{ {
// if this is a peer server, we check their credentials specially // if this is a peer server, we check their credentials specially
AuthRequest req = conn.getAuthRequest(); AuthRequest req = conn.getAuthRequest();
if (req.getCredentials() instanceof PeerCreds) { if (req.getCredentials() instanceof PeerCreds) {
AuthResponse rsp = new AuthResponse(new AuthResponseData()); super.authenticateConnection(conn);
PeerCreds pcreds = (PeerCreds)req.getCredentials();
if (_peermgr.isAuthenticPeer(pcreds)) {
rsp.getData().code = AuthResponseData.SUCCESS;
} else {
log.warning("Received invalid peer auth request? " +
"[creds=" + pcreds + "].");
rsp.getData().code = AuthCodes.SERVER_ERROR;
}
connectionWasAuthenticated(conn, rsp);
} else { } else {
// otherwise pass the request on to our delegate // otherwise pass the request on to our delegate
@@ -72,6 +67,34 @@ public class PeerAuthenticator extends Authenticator
} }
} }
@Override
protected Invoker getInvoker ()
{
// The processing of peer authentication happens inline,
// but other authentication will use the _delegate which will
// probably use an Invoker.
return null;
}
// from abstract Authenticator
protected void processAuthentication (
AuthingConnection conn, AuthResponse rsp)
throws PersistenceException
{
// here, we are ONLY authenticating peers
AuthRequest req = conn.getAuthRequest();
PeerCreds pcreds = (PeerCreds) req.getCredentials();
if (_peermgr.isAuthenticPeer(pcreds)) {
rsp.getData().code = AuthResponseData.SUCCESS;
} else {
log.warning("Received invalid peer auth request? " +
"[creds=" + pcreds + "].");
rsp.getData().code = AuthCodes.SERVER_ERROR;
}
}
protected PeerManager _peermgr; protected PeerManager _peermgr;
protected Authenticator _delegate; protected Authenticator _delegate;
} }
@@ -21,12 +21,23 @@
package com.threerings.presents.server; package com.threerings.presents.server;
import java.util.logging.Level;
import com.samskivert.io.PersistenceException;
import com.samskivert.util.Invoker;
import com.threerings.presents.data.AuthCodes;
import com.threerings.presents.net.AuthRequest;
import com.threerings.presents.net.AuthResponse; import com.threerings.presents.net.AuthResponse;
import com.threerings.presents.net.AuthResponseData; import com.threerings.presents.net.AuthResponseData;
import com.threerings.presents.server.net.AuthingConnection; import com.threerings.presents.server.net.AuthingConnection;
import com.threerings.presents.server.net.ConnectionManager; import com.threerings.presents.server.net.ConnectionManager;
import static com.threerings.presents.Log.log;
/** /**
* The authenticator is a pluggable component of the authentication * The authenticator is a pluggable component of the authentication
* framework. The base class handles the basic mechanics of authentication * framework. The base class handles the basic mechanics of authentication
@@ -47,28 +58,27 @@ public abstract class Authenticator
/** /**
* Called by the connection management code when an authenticating * Called by the connection management code when an authenticating
* connection has received its authentication request from the client. * connection has received its authentication request from the client.
* This method must return immediately as it is called on the
* connection manager thread. If it is possible to authenticate the
* connection immediately, it may do so, but more likely it will fire
* off a task on the {@link PresentsServer#invoker} to perform the
* authentication. When the authentication is complete, the
* authenticator implementation should call {@link
* #connectionWasAuthenticated}.
*/ */
public abstract void authenticateConnection (AuthingConnection conn); public void authenticateConnection (final AuthingConnection conn)
/**
* This is called by authenticator implementations when they have
* completed the authentication process. It will deliver the response
* to the user and let the connection manager know to report the
* authentication if it succeeded.
*/
protected void connectionWasAuthenticated (
final AuthingConnection conn, final AuthResponse rsp)
{ {
// make double plus extra sure we're on the omgr thread final AuthRequest req = conn.getAuthRequest();
PresentsServer.omgr.postRunnable(new Runnable() { final AuthResponseData rdata = createResponseData();
public void run () { final AuthResponse rsp = new AuthResponse(rdata);
Invoker.Unit unit = new Invoker.Unit("auth:" + req.getCredentials()) {
public boolean invoke() {
try {
processAuthentication(conn, rsp);
} catch (Exception e) { // Persistence or Runtime
log.log(Level.WARNING, "Error authenticating user " +
"[areq=" + req + "].", e);
rdata.code = AuthCodes.SERVER_ERROR;
}
return true;
}
public void handleResult () {
// stuff a reference to the auth response into the // stuff a reference to the auth response into the
// connection so that we have access to it later in the // connection so that we have access to it later in the
// authentication process // authentication process
@@ -79,13 +89,62 @@ public abstract class Authenticator
// if the authentication request was granted, let the // if the authentication request was granted, let the
// connection manager know that we just authed // connection manager know that we just authed
if (AuthResponseData.SUCCESS.equals(rsp.getData().code)) { if (AuthResponseData.SUCCESS.equals(rdata.code)) {
_conmgr.connectionDidAuthenticate(conn); _conmgr.connectionDidAuthenticate(conn);
} }
} }
}); };
Invoker invoker = getInvoker();
if (invoker != null) {
invoker.postUnit(unit);
} else {
// just process it here
try {
unit.invoke();
unit.handleResult();
} catch (Exception e) {
log.log(Level.WARNING, "Error authenticating user " +
"[areq=" + req + "].", e);
}
}
} }
/**
* Return the invoker on which to process the authentication, or null
* if the authentication should occur on the calling thread. The default
* implementation returns PresentsServer.invoker.
*/
protected Invoker getInvoker ()
{
return PresentsServer.invoker;
}
/**
* Create a new AuthResponseData instance to use for authenticating
* a connection.
*/
protected AuthResponseData createResponseData ()
{
return new AuthResponseData();
}
/**
* Process the authentication for the specified connection.
* This method may do database operations if and only if getInvoker()
* returns non-null. The method may return after it has stuffed a valid
* response code in rsp.getData().code.
*
* @param conn The client connection.
* @param rsp The response to the client, which will already contain
* an AuthResponseData created by createResponseDatA().
*/
protected abstract void processAuthentication (
AuthingConnection conn, AuthResponse rsp)
throws PersistenceException;
/** The connection manager with which we're working. */ /** The connection manager with which we're working. */
protected ConnectionManager _conmgr; protected ConnectionManager _conmgr;
} }
@@ -21,25 +21,34 @@
package com.threerings.presents.server; package com.threerings.presents.server;
import com.threerings.presents.Log; import com.samskivert.io.PersistenceException;
import com.samskivert.util.Invoker;
import com.threerings.presents.net.AuthResponse; import com.threerings.presents.net.AuthResponse;
import com.threerings.presents.net.AuthResponseData; import com.threerings.presents.net.AuthResponseData;
import com.threerings.presents.server.net.AuthingConnection; import com.threerings.presents.server.net.AuthingConnection;
import static com.threerings.presents.Log.log;
/** /**
* A simple authenticator implementation that simply accepts all * A simple authenticator implementation that simply accepts all
* authentication requests. * authentication requests.
*/ */
public class DummyAuthenticator extends Authenticator public class DummyAuthenticator extends Authenticator
{ {
/** @Override
* Accept all authentication requests. protected Invoker getInvoker ()
*/
public void authenticateConnection (AuthingConnection conn)
{ {
Log.info("Accepting request: " + conn.getAuthRequest()); return null; // not needed
AuthResponseData rdata = new AuthResponseData(); }
rdata.code = AuthResponseData.SUCCESS;
connectionWasAuthenticated(conn, new AuthResponse(rdata)); // from abstract Authenticator
protected void processAuthentication (
AuthingConnection conn, AuthResponse rsp)
throws PersistenceException
{
log.info("Accepting request: " + conn.getAuthRequest());
rsp.getData().code = AuthResponseData.SUCCESS;
} }
} }
@@ -3,14 +3,20 @@
package com.threerings.presents.server; package com.threerings.presents.server;
import java.util.logging.Level;
import com.samskivert.io.PersistenceException;
import com.samskivert.util.Invoker;
import com.samskivert.util.StringUtil; import com.samskivert.util.StringUtil;
import com.threerings.util.MessageBundle; import com.threerings.util.MessageBundle;
import com.threerings.presents.Log;
import com.threerings.presents.net.AuthResponse; import com.threerings.presents.net.AuthResponse;
import com.threerings.presents.net.AuthResponseData; import com.threerings.presents.net.AuthResponseData;
import com.threerings.presents.server.net.AuthingConnection; import com.threerings.presents.server.net.AuthingConnection;
import static com.threerings.presents.Log.log;
/** /**
* A simple server that does nothing more than spit out a canned error * A simple server that does nothing more than spit out a canned error
* response to everyone who logs in. * response to everyone who logs in.
@@ -51,8 +57,7 @@ public class Rejector extends PresentsServer
server.init(); server.init();
server.run(); server.run();
} catch (Exception e) { } catch (Exception e) {
Log.warning("Unable to initialize server."); log.log(Level.WARNING, "Unable to initialize server.", e);
Log.logStackTrace(e);
} }
} }
@@ -62,13 +67,19 @@ public class Rejector extends PresentsServer
*/ */
protected class RejectingAuthenticator extends Authenticator protected class RejectingAuthenticator extends Authenticator
{ {
/** Reject all authentication requests. */ @Override
public void authenticateConnection (AuthingConnection conn) protected Invoker getInvoker ()
{ {
Log.info("Rejecting request: " + conn.getAuthRequest()); return null;
AuthResponseData rdata = new AuthResponseData(); }
rdata.code = _errmsg;
connectionWasAuthenticated(conn, new AuthResponse(rdata)); // from abstract Authenticator
protected void processAuthentication (
AuthingConnection conn, AuthResponse rsp)
throws PersistenceException
{
log.info("Rejecting request: " + conn.getAuthRequest());
rsp.getData().code = _errmsg;
} }
} }