Revamping/cleanup of how we handle authentication usernames as well as chained
authenticators and chained session factories. We can share a lot more code this way and the implicit requirement that the default authenticator/factory had to be configured before anyone else configured a chanied author/factory is gone. The other big change is that Credentials doesn't require a username (UsernamePasswordCreds inherits that username so most derived classes don't notice any difference). Instead we require that a canonical authentication username be determined and configured in AuthingConnection during the authentication process. This canonical username is then used to resolve the client session and map everything in the client manager. This is pretty much exactly what was going on before except that we were doing it all in an ad hoc way by jamming a new name into Credentials during the authentication process and also doing jiggery pokery in PresentsSession.assignStartingUsername. That all goes away and/or becomes cleaner and more explicit. This is going to impact some Yohoho jiggery pokery, which I will shortly commit a patch for, but we're going to need to test it. Omelets, eggs, etc. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5828 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2009 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.presents.peer.data;
|
||||
|
||||
import com.threerings.util.Name;
|
||||
|
||||
/**
|
||||
* Represents an authenticated peer client.
|
||||
*/
|
||||
public class PeerAuthName extends Name
|
||||
{
|
||||
public PeerAuthName (String nodeName)
|
||||
{
|
||||
super(nodeName);
|
||||
}
|
||||
|
||||
// used when unserializing
|
||||
public PeerAuthName ()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -21,36 +21,16 @@
|
||||
|
||||
package com.threerings.presents.peer.net;
|
||||
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.net.UsernamePasswordCreds;
|
||||
import com.threerings.presents.net.ServiceCreds;
|
||||
|
||||
/**
|
||||
* Used by peer servers in a cluster installation to authenticate with one another.
|
||||
*/
|
||||
public class PeerCreds extends UsernamePasswordCreds
|
||||
public class PeerCreds extends ServiceCreds
|
||||
{
|
||||
/** A prefix prepended to the node name used as a peer's username to prevent the username from
|
||||
* colliding with a normal authenticating user's username. We assume that colons are not
|
||||
* allowed in a normal username. */
|
||||
public static final String PEER_PREFIX = "peer:";
|
||||
|
||||
/**
|
||||
* Creates a unique password for the specified node using the supplied shared secret.
|
||||
*/
|
||||
public static String createPassword (String nodeName, String sharedSecret)
|
||||
{
|
||||
return StringUtil.md5hex(nodeName + sharedSecret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates credentials for the specified peer.
|
||||
*/
|
||||
public PeerCreds (String nodeName, String sharedSecret)
|
||||
{
|
||||
super(new Name(PEER_PREFIX + nodeName), createPassword(nodeName, sharedSecret));
|
||||
super(nodeName, sharedSecret);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,13 +39,4 @@ public class PeerCreds extends UsernamePasswordCreds
|
||||
public PeerCreds ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the node name of this authenticating peer (which does not include the {@link
|
||||
* #PEER_PREFIX}.
|
||||
*/
|
||||
public String getNodeName ()
|
||||
{
|
||||
return getUsername().toString().substring(PEER_PREFIX.length());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.presents.peer.server;
|
||||
|
||||
import com.samskivert.io.PersistenceException;
|
||||
|
||||
import com.threerings.presents.data.AuthCodes;
|
||||
import com.threerings.presents.net.AuthRequest;
|
||||
import com.threerings.presents.net.AuthResponse;
|
||||
import com.threerings.presents.net.AuthResponseData;
|
||||
import com.threerings.presents.peer.net.PeerCreds;
|
||||
import com.threerings.presents.server.ChainedAuthenticator;
|
||||
import com.threerings.presents.server.net.AuthingConnection;
|
||||
|
||||
import static com.threerings.presents.Log.log;
|
||||
|
||||
/**
|
||||
* Handles authentication of peer servers and passes non-peer authentication requests through to a
|
||||
* normal authenticator.
|
||||
*/
|
||||
public class PeerAuthenticator extends ChainedAuthenticator
|
||||
{
|
||||
public PeerAuthenticator (PeerManager nodemgr)
|
||||
{
|
||||
_peermgr = nodemgr;
|
||||
}
|
||||
|
||||
@Override // from abstract ChainedAuthenticator
|
||||
protected boolean shouldHandleConnection (AuthingConnection conn)
|
||||
{
|
||||
return (conn.getAuthRequest().getCredentials() instanceof PeerCreds);
|
||||
}
|
||||
|
||||
@Override // 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;
|
||||
}
|
||||
@@ -69,11 +69,14 @@ import com.threerings.presents.server.InvocationManager;
|
||||
import com.threerings.presents.server.PresentsDObjectMgr;
|
||||
import com.threerings.presents.server.PresentsSession;
|
||||
import com.threerings.presents.server.ReportManager;
|
||||
import com.threerings.presents.server.ServiceAuthenticator;
|
||||
import com.threerings.presents.server.SessionFactory;
|
||||
import com.threerings.presents.server.net.ConnectionManager;
|
||||
|
||||
import com.threerings.presents.peer.client.PeerService;
|
||||
import com.threerings.presents.peer.data.ClientInfo;
|
||||
import com.threerings.presents.peer.data.NodeObject;
|
||||
import com.threerings.presents.peer.data.PeerAuthName;
|
||||
import com.threerings.presents.peer.net.PeerCreds;
|
||||
import com.threerings.presents.peer.server.persist.NodeRecord;
|
||||
import com.threerings.presents.peer.server.persist.NodeRepository;
|
||||
@@ -234,8 +237,15 @@ public abstract class PeerManager
|
||||
_sharedSecret = sharedSecret;
|
||||
|
||||
// wire ourselves into the server
|
||||
_conmgr.addChainedAuthenticator(new PeerAuthenticator(this));
|
||||
_clmgr.setSessionFactory(new PeerSessionFactory(_clmgr.getSessionFactory()));
|
||||
_conmgr.addChainedAuthenticator(
|
||||
new ServiceAuthenticator<PeerCreds>(PeerCreds.class, PeerAuthName.class) {
|
||||
protected boolean areValid (PeerCreds creds) {
|
||||
return creds.areValid(_sharedSecret);
|
||||
}
|
||||
});
|
||||
_clmgr.addSessionFactory(
|
||||
SessionFactory.newSessionFactory(PeerCreds.class, PeerSession.class,
|
||||
PeerAuthName.class, PeerClientResolver.class));
|
||||
|
||||
// create our node object
|
||||
_nodeobj = _omgr.registerObject(createNodeObject());
|
||||
@@ -269,8 +279,7 @@ public abstract class PeerManager
|
||||
*/
|
||||
public boolean isAuthenticPeer (PeerCreds creds)
|
||||
{
|
||||
return PeerCreds.createPassword(creds.getNodeName(), _sharedSecret).equals(
|
||||
creds.getPassword());
|
||||
return creds.areValid(_sharedSecret);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -855,7 +864,7 @@ public abstract class PeerManager
|
||||
// we scan through the list instead of relying on ClientInfo.getKey() because we want
|
||||
// derived classes to be able to override that for lookups that happen way more frequently
|
||||
// than logging off
|
||||
Name username = client.getCredentials().getUsername();
|
||||
Name username = client.getUsername();
|
||||
for (ClientInfo clinfo : _nodeobj.clients) {
|
||||
if (clinfo.username.equals(username)) {
|
||||
_nodeobj.startTransaction();
|
||||
@@ -1015,7 +1024,7 @@ public abstract class PeerManager
|
||||
*/
|
||||
protected void initClientInfo (PresentsSession client, ClientInfo info)
|
||||
{
|
||||
info.username = client.getCredentials().getUsername();
|
||||
info.username = client.getUsername();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1391,13 +1400,13 @@ public abstract class PeerManager
|
||||
protected Stats _stats = new Stats();
|
||||
|
||||
// our service dependencies
|
||||
@Inject protected ConnectionManager _conmgr;
|
||||
@Inject protected ClientManager _clmgr;
|
||||
@Inject protected ReportManager _repmgr;
|
||||
@Inject protected PresentsDObjectMgr _omgr;
|
||||
@Inject protected InvocationManager _invmgr;
|
||||
@Inject protected @MainInvoker Invoker _invoker;
|
||||
@Inject protected ClientManager _clmgr;
|
||||
@Inject protected ConnectionManager _conmgr;
|
||||
@Inject protected InvocationManager _invmgr;
|
||||
@Inject protected NodeRepository _noderepo;
|
||||
@Inject protected PresentsDObjectMgr _omgr;
|
||||
@Inject protected ReportManager _repmgr;
|
||||
|
||||
/** We wait this long for peer ratification to complete before acquiring/releasing the lock. */
|
||||
protected static final long LOCK_TIMEOUT = 5000L;
|
||||
|
||||
@@ -41,8 +41,7 @@ import static com.threerings.presents.Log.log;
|
||||
public class PeerSession extends PresentsSession
|
||||
{
|
||||
/**
|
||||
* Creates a peer session and provides it with a reference to the peer manager. This is only
|
||||
* done by the {@link PeerSessionFactory}.
|
||||
* Creates a peer session and provides it with a reference to the peer manager.
|
||||
*/
|
||||
@Inject public PeerSession (PeerManager peermgr)
|
||||
{
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.presents.peer.server;
|
||||
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.net.AuthRequest;
|
||||
import com.threerings.presents.peer.net.PeerCreds;
|
||||
import com.threerings.presents.server.SessionFactory;
|
||||
import com.threerings.presents.server.ClientResolver;
|
||||
import com.threerings.presents.server.PresentsSession;
|
||||
|
||||
/**
|
||||
* Handles resolution of peer servers and passes non-peer resolution requests through to a normal
|
||||
* factory.
|
||||
*/
|
||||
public class PeerSessionFactory implements SessionFactory
|
||||
{
|
||||
public PeerSessionFactory (SessionFactory delegate)
|
||||
{
|
||||
_delegate = delegate;
|
||||
}
|
||||
|
||||
// documentation inherited from interface SessionFactory
|
||||
public Class<? extends PresentsSession> getSessionClass (AuthRequest areq)
|
||||
{
|
||||
if (areq.getCredentials() instanceof PeerCreds) {
|
||||
return PeerSession.class;
|
||||
} else {
|
||||
return _delegate.getSessionClass(areq);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface SessionFactory
|
||||
public Class<? extends ClientResolver> getClientResolverClass (Name username)
|
||||
{
|
||||
if (username.toString().startsWith(PeerCreds.PEER_PREFIX)) {
|
||||
return PeerClientResolver.class;
|
||||
} else {
|
||||
return _delegate.getClientResolverClass(username);
|
||||
}
|
||||
}
|
||||
|
||||
protected SessionFactory _delegate;
|
||||
}
|
||||
Reference in New Issue
Block a user