updated login service for logout.

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@141 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Greg Wilkins 2009-04-13 23:55:40 +00:00
parent d4a4e0ea68
commit 74de0dbec6
21 changed files with 176 additions and 80 deletions

View File

@ -38,6 +38,7 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector,
private final HttpClient _httpClient;
private SSLContext _sslContext;
private Buffers _sslBuffers;
private boolean _blockingConnect;
SelectorManager _selectorManager=new Manager();
@ -49,28 +50,50 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector,
_httpClient = httpClient;
}
/* ------------------------------------------------------------ */
/** Get the blockingConnect.
* @return the blockingConnect
*/
public boolean isBlockingConnect()
{
return _blockingConnect;
}
/* ------------------------------------------------------------ */
/** Set the blockingConnect.
* @param blockingConnect If true, connections are made in blocking mode.
*/
public void setBlockingConnect(boolean blockingConnect)
{
_blockingConnect = blockingConnect;
}
/* ------------------------------------------------------------ */
protected void doStart() throws Exception
{
_selectorManager.start();
_httpClient._threadPool.dispatch(this);
}
/* ------------------------------------------------------------ */
protected void doStop() throws Exception
{
_selectorManager.stop();
}
/* ------------------------------------------------------------ */
public void startConnection( HttpDestination destination )
throws IOException
{
SocketChannel channel = SocketChannel.open();
Address address = destination.isProxied() ? destination.getProxy() : destination.getAddress();
channel.connect(address.toSocketAddress());
channel.configureBlocking( false );
channel.connect(address.toSocketAddress());
channel.socket().setSoTimeout( _httpClient._soTimeout );
_selectorManager.register( channel, destination );
}
/* ------------------------------------------------------------ */
public void run()
{
while (_httpClient.isRunning())
@ -86,6 +109,7 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector,
}
}
/* ------------------------------------------------------------ */
class Manager extends SelectorManager
{
protected SocketChannel acceptChannel(SelectionKey key) throws IOException
@ -192,7 +216,5 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector,
else
Log.warn(ex);
}
}
}

View File

@ -282,19 +282,13 @@ public abstract class SelectorManager extends AbstractLifeCycle
synchronized (_changes)
{
_changes[_change].add(point);
if (point instanceof SocketChannel)
_changes[_change].add(null);
}
}
/* ------------------------------------------------------------ */
public void addChange(SocketChannel channel, Object att)
{
synchronized (_changes)
{
_changes[_change].add(channel);
_changes[_change].add(att);
}
addChange(new AttachedSocketChannel(channel,att));
}
/* ------------------------------------------------------------ */
@ -325,7 +319,8 @@ public abstract class SelectorManager extends AbstractLifeCycle
// Make any key changes required
for (int i = 0; i < changes.size(); i++)
final int size=changes.size();
for (int i = 0; i < size; i++)
{
try
{
@ -340,11 +335,12 @@ public abstract class SelectorManager extends AbstractLifeCycle
{
dispatch((Runnable)o);
}
else if (o instanceof SocketChannel)
else if (o instanceof AttachedSocketChannel)
{
// finish accepting/connecting this connection
SocketChannel channel=(SocketChannel)o;
Object att = changes.get(++i);
final AttachedSocketChannel asc = (AttachedSocketChannel)o;
final SocketChannel channel=asc._channel;
final Object att = asc._attachment;
if (channel.isConnected())
{
@ -436,8 +432,10 @@ public abstract class SelectorManager extends AbstractLifeCycle
final Object attachment = key.attachment();
key.cancel();
addChange(channel,attachment);
if (attachment==null)
addChange(channel);
else
addChange(attachment);
}
_selector.close();
_selector=new_selector;
@ -678,4 +676,20 @@ public abstract class SelectorManager extends AbstractLifeCycle
}
}
}
/* ------------------------------------------------------------ */
private static class AttachedSocketChannel
{
final SocketChannel _channel;
final Object _attachment;
public AttachedSocketChannel(SocketChannel channel, Object attachment)
{
super();
_channel = channel;
_attachment = attachment;
}
}
}

View File

@ -125,6 +125,7 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
}
/* ------------------------------------------------------------ */
/**
* Set the name to use to index into the config
* file of LoginModules.
@ -137,11 +138,13 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
}
/* ------------------------------------------------------------ */
public void setCallbackHandlerClass (String classname)
{
_callbackHandlerClass = classname;
}
/* ------------------------------------------------------------ */
public void setRoleClassNames (String[] classnames)
{
ArrayList<String> tmp = new ArrayList<String>();
@ -154,6 +157,7 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
_roleClassNames = tmp.toArray(new String[tmp.size()]);
}
/* ------------------------------------------------------------ */
public String[] getRoleClassNames()
{
return _roleClassNames;
@ -225,6 +229,7 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
return null;
}
/* ------------------------------------------------------------ */
private String getUserName(CallbackHandler callbackHandler) throws IOException, UnsupportedCallbackException
{
NameCallback nameCallback = new NameCallback("foo");
@ -232,14 +237,10 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
return nameCallback.getName();
}
public void logout(Subject subject) throws ServerAuthException
/* ------------------------------------------------------------ */
public void logout(UserIdentity user)
{
// loginCallback.clearPassword();
Set<JAASUserPrincipal> userPrincipals = subject.getPrincipals(JAASUserPrincipal.class);
if (userPrincipals.size() != 1)
{
throw new ServerAuthException("logout implausible, wrong number of user principals: " + userPrincipals);
}
Set<JAASUserPrincipal> userPrincipals = user.getSubject().getPrincipals(JAASUserPrincipal.class);
LoginContext loginContext = userPrincipals.iterator().next().getLoginContext();
try
{
@ -247,11 +248,12 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
}
catch (LoginException e)
{
throw new ServerAuthException("Failed to log out: "+e.getMessage());
Log.warn(e);
}
}
/* ------------------------------------------------------------ */
private String[] getGroups (Subject subject)
{
//get all the roles of the various types

View File

@ -38,6 +38,7 @@ public interface Authentication
boolean isSuccess();
void logout();
public static final Authentication SUCCESS_UNAUTH_RESULTS = new Authentication()
{
@ -45,6 +46,7 @@ public interface Authentication
public Status getAuthStatus() {return Authentication.Status.SUCCESS;}
public UserIdentity getUserIdentity() {return UserIdentity.UNAUTHENTICATED_IDENTITY;}
public boolean isSuccess() {return true;}
public void logout() {}
};
public static final Authentication SEND_CONTINUE_RESULTS = new Authentication()
@ -53,6 +55,7 @@ public interface Authentication
public Status getAuthStatus() {return Authentication.Status.SEND_CONTINUE;}
public UserIdentity getUserIdentity() {return UserIdentity.UNAUTHENTICATED_IDENTITY;}
public boolean isSuccess() {return false;}
public void logout() {}
};
public static final Authentication SEND_FAILURE_RESULTS = new Authentication()
@ -61,6 +64,7 @@ public interface Authentication
public Status getAuthStatus() {return Authentication.Status.SEND_FAILURE;}
public UserIdentity getUserIdentity() {return UserIdentity.UNAUTHENTICATED_IDENTITY;}
public boolean isSuccess() {return false;}
public void logout() {}
};
}

View File

@ -13,6 +13,8 @@
package org.eclipse.jetty.security;
import org.eclipse.jetty.security.authentication.DelegateAuthenticator;
import org.eclipse.jetty.security.authentication.LoginAuthenticator;
import org.eclipse.jetty.server.UserIdentity;
@ -22,19 +24,19 @@ import org.eclipse.jetty.server.UserIdentity;
public class DefaultAuthentication implements Authentication
{
private final Authentication.Status _authStatus;
private final String _authMethod;
private final Authenticator _authenticator;
private final UserIdentity _userIdentity;
public DefaultAuthentication(Authentication.Status authStatus, String authMethod, UserIdentity userIdentity)
public DefaultAuthentication(Authentication.Status authStatus, Authenticator authenticator, UserIdentity userIdentity)
{
_authStatus = authStatus;
_authMethod = authMethod;
_authenticator = authenticator;
_userIdentity=userIdentity;
}
public String getAuthMethod()
{
return _authMethod;
return _authenticator.getAuthMethod();
}
public Authentication.Status getAuthStatus()
@ -52,8 +54,27 @@ public class DefaultAuthentication implements Authentication
return _authStatus.isSuccess();
}
public void logout()
{
Authenticator authenticator = _authenticator;
while (true)
{
if (authenticator instanceof LoginAuthenticator)
{
((LoginAuthenticator)authenticator).getLoginService().logout(this.getUserIdentity());
break;
}
else if (authenticator instanceof DelegateAuthenticator)
{
authenticator=((DelegateAuthenticator)authenticator).getDelegate();
}
else
break;
}
}
public String toString()
{
return "{Auth,"+_authMethod+","+_authStatus+","+","+_userIdentity+"}";
return "{Auth,"+getAuthMethod()+","+_authStatus+","+","+_userIdentity+"}";
}
}

View File

@ -32,7 +32,7 @@ import org.eclipse.jetty.server.UserIdentity.Scope;
* implementation. All other operations are effectively noops.
*
*/
public class DefaultIdentityService implements IdentityService<UserIdentity, RoleRunAsToken>
public class DefaultIdentityService implements IdentityService
{
public DefaultIdentityService()
{
@ -55,12 +55,12 @@ public class DefaultIdentityService implements IdentityService<UserIdentity, Rol
{
}
public RoleRunAsToken associateRunAs(RunAsToken token)
public Object associateRunAs(UserIdentity user, RunAsToken token)
{
return null;
return token;
}
public void disassociateRunAs(RoleRunAsToken lastToken)
public void disassociateRunAs(Object lastToken)
{
}
@ -69,7 +69,7 @@ public class DefaultIdentityService implements IdentityService<UserIdentity, Rol
return new RoleRunAsToken(runAsName);
}
public UserIdentity newSystemUserIdentity()
public UserIdentity getSystemUserIdentity()
{
return null;
}

View File

@ -16,9 +16,6 @@ package org.eclipse.jetty.security;
import java.security.Principal;
import javax.security.auth.Subject;
import org.eclipse.jetty.http.security.Constraint;
import org.eclipse.jetty.security.Authentication.Status;
import org.eclipse.jetty.server.UserIdentity;
@ -29,10 +26,6 @@ import org.eclipse.jetty.server.UserIdentity;
*/
public class DefaultUserIdentity implements UserIdentity
{
/* Cache successful authentications for BASIC and DIGEST to avoid creation on every request */
public final Authentication SUCCESSFUL_BASIC = new DefaultAuthentication(Status.SUCCESS,Constraint.__BASIC_AUTH,this);
public final Authentication SUCCESSFUL_DIGEST = new DefaultAuthentication(Status.SUCCESS,Constraint.__BASIC_AUTH,this);
private final Subject _subject;
private final Principal _userPrincipal;
private final String[] _roles;

View File

@ -24,7 +24,7 @@ import org.eclipse.jetty.server.UserIdentity;
* Associates UserIdentities from with threads and UserIdentity.Contexts.
*
*/
public interface IdentityService <SCOPED extends UserIdentity, RUNAS>
public interface IdentityService
{
/* ------------------------------------------------------------ */
@ -48,24 +48,23 @@ public interface IdentityService <SCOPED extends UserIdentity, RUNAS>
* @param context The new scope.
* @return A scoped {@link UserIdentity}.
*/
SCOPED associate(UserIdentity user, UserIdentity.Scope context);
UserIdentity associate(UserIdentity user, UserIdentity.Scope context);
/* ------------------------------------------------------------ */
/**
* Disassociate the current UserIdentity and reinstate the
* previousUser identity.
* TODO this might not be necessary. Both existing implementations are no-ops
* @param scoped SCOPED returned from previous associate call
* @param scoped UserIdentity returned from previous associate call
*/
void disassociate(SCOPED scoped);
void disassociate(UserIdentity scoped);
/* ------------------------------------------------------------ */
/**
* Associate a runas Token with the current thread.
* Associate a runas Token with the current user and thread.
* @param token The runAsToken to associate.
* @return The previous runAsToken or null.
*/
RUNAS associateRunAs(RunAsToken token);
Object associateRunAs(UserIdentity user, RunAsToken token);
/* ------------------------------------------------------------ */
/**
@ -73,7 +72,7 @@ public interface IdentityService <SCOPED extends UserIdentity, RUNAS>
* and reassociate the previous token.
* @param token RUNAS returned from previous associateRunAs call
*/
void disassociateRunAs(RUNAS token);
void disassociateRunAs(Object token);
/* ------------------------------------------------------------ */
/**
@ -95,5 +94,6 @@ public interface IdentityService <SCOPED extends UserIdentity, RUNAS>
*/
RunAsToken newRunAsToken(String runAsName);
UserIdentity newSystemUserIdentity();
/* ------------------------------------------------------------ */
UserIdentity getSystemUserIdentity();
}

View File

@ -66,6 +66,12 @@ public class LazyAuthentication implements Authentication
{
return getDelegate().isSuccess();
}
public void logout()
{
if (_delegate!=null)
_delegate.logout();
}
// for cleaning in secureResponse
public UserIdentity getUserIdentity()

View File

@ -28,7 +28,8 @@ public interface LoginService
{
String getName();
UserIdentity login(String username,Object credentials);
void logout(UserIdentity user);
IdentityService<UserIdentity,?> getIdentityService();
void setIdentityService(IdentityService<UserIdentity,?> service);
IdentityService getIdentityService();
void setIdentityService(IdentityService service);
}

View File

@ -201,6 +201,12 @@ public abstract class MappedLoginService extends AbstractLifeCycle implements Lo
return null;
}
/* ------------------------------------------------------------ */
public void logout(UserIdentity user)
{
// TODO maybe clear cache?
}
/* ------------------------------------------------------------ */
protected abstract UserIdentity loadUser(String username);

View File

@ -54,7 +54,7 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
private final Map<String,String> _initParameters=new HashMap<String,String>();
private LoginService _loginService;
private boolean _loginServiceShared;
private IdentityService<UserIdentity,?> _identityService;
private IdentityService _identityService;
/* ------------------------------------------------------------ */
protected SecurityHandler()
@ -65,7 +65,7 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
/** Get the identityService.
* @return the identityService
*/
public IdentityService<UserIdentity,?> getIdentityService()
public IdentityService getIdentityService()
{
return _identityService;
}
@ -74,7 +74,7 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
/** Set the identityService.
* @param identityService the identityService to set
*/
public void setIdentityService(IdentityService<UserIdentity,?> identityService)
public void setIdentityService(IdentityService identityService)
{
if (isStarted())
throw new IllegalStateException("Started");
@ -268,7 +268,7 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
}
/* ------------------------------------------------------------ */
protected IdentityService<UserIdentity,?> findIdentityService()
protected IdentityService findIdentityService()
{
List<IdentityService> services = getServer().getBeans(IdentityService.class);
if (services!=null && services.size()>0)

View File

@ -27,6 +27,7 @@ import org.eclipse.jetty.security.Authentication;
import org.eclipse.jetty.security.DefaultAuthentication;
import org.eclipse.jetty.security.DefaultUserIdentity;
import org.eclipse.jetty.security.ServerAuthException;
import org.eclipse.jetty.security.Authentication.Status;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.StringUtil;
@ -34,7 +35,7 @@ import org.eclipse.jetty.util.StringUtil;
* @version $Rev: 4793 $ $Date: 2009-03-19 00:00:01 +0100 (Thu, 19 Mar 2009) $
*/
public class BasicAuthenticator extends LoginAuthenticator
{
{
/* ------------------------------------------------------------ */
/**
* @param loginService
@ -75,9 +76,7 @@ public class BasicAuthenticator extends LoginAuthenticator
UserIdentity user = _loginService.login(username,password);
if (user!=null)
{
if (user instanceof DefaultUserIdentity)
return ((DefaultUserIdentity)user).SUCCESSFUL_BASIC;
return new DefaultAuthentication(Authentication.Status.SUCCESS,Constraint.__BASIC_AUTH,user);
return new DefaultAuthentication(Authentication.Status.SUCCESS,this,user);
}
}

View File

@ -76,7 +76,7 @@ public class ClientCertAuthenticator extends LoginAuthenticator
UserIdentity user = _loginService.login(username,credential);
if (user!=null)
return new DefaultAuthentication(Authentication.Status.SUCCESS,Constraint.__CERT_AUTH2,user);
return new DefaultAuthentication(Authentication.Status.SUCCESS,this,user);
if (!mandatory)
{

View File

@ -124,9 +124,7 @@ public class DigestAuthenticator extends LoginAuthenticator
UserIdentity user = _loginService.login(digest.username,digest);
if (user!=null)
{
if (user instanceof DefaultUserIdentity)
return ((DefaultUserIdentity)user).SUCCESSFUL_BASIC;
return new DefaultAuthentication(Authentication.Status.SUCCESS,Constraint.__DIGEST_AUTH,user);
return new DefaultAuthentication(Authentication.Status.SUCCESS,this,user);
}
}
else if (n == 0) stale = true;

View File

@ -180,7 +180,7 @@ public class FormAuthenticator extends LoginAuthenticator
session.removeAttribute(__J_URI); // Remove popped return URI.
response.setContentLength(0);
response.sendRedirect(response.encodeRedirectURL(nuri));
return new DefaultAuthentication(Authentication.Status.SEND_SUCCESS,Constraint.__FORM_AUTH,user);
return new DefaultAuthentication(Authentication.Status.SEND_SUCCESS,this,user);
}
// not authenticated

View File

@ -17,11 +17,17 @@ import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import org.eclipse.jetty.security.Authentication;
import org.eclipse.jetty.security.Authenticator;
import org.eclipse.jetty.security.DefaultAuthentication;
import org.eclipse.jetty.security.ServerAuthException;
import org.eclipse.jetty.security.Authentication.Status;
import org.eclipse.jetty.server.UserIdentity;
/**
* @version $Rev: 4793 $ $Date: 2009-03-19 00:00:01 +0100 (Thu, 19 Mar 2009) $
@ -30,7 +36,6 @@ public class SessionCachingAuthenticator extends DelegateAuthenticator
{
public final static String __J_AUTHENTICATED = "org.eclipse.jetty.server.Auth";
public SessionCachingAuthenticator(Authenticator delegate)
{
super(delegate);
@ -50,10 +55,32 @@ public class SessionCachingAuthenticator extends DelegateAuthenticator
authentication = _delegate.validateRequest(request, response, mandatory);
if (authentication != null && authentication.getUserIdentity().getSubject() != null)
{
Authentication next=new DefaultAuthentication(Authentication.Status.SUCCESS,authentication.getAuthMethod(),authentication.getUserIdentity());
Authentication next=new FormAuthentication(Authentication.Status.SUCCESS,_delegate,authentication.getUserIdentity());
session.setAttribute(__J_AUTHENTICATED, next);
}
return authentication;
}
protected class FormAuthentication extends DefaultAuthentication implements HttpSessionAttributeListener
{
public FormAuthentication(Status authStatus, Authenticator authenticator, UserIdentity userIdentity)
{
super(authStatus,authenticator,userIdentity);
}
public void attributeAdded(HttpSessionBindingEvent event)
{
}
public void attributeRemoved(HttpSessionBindingEvent event)
{
logout();
}
public void attributeReplaced(HttpSessionBindingEvent arg0)
{
logout();
}
}
}

View File

@ -44,10 +44,12 @@ public class XCPSCachingAuthenticator extends DelegateAuthenticator
{
Authentication serverAuthResult = _xcps.fetch((HttpServletRequest)request);
if (serverAuthResult != null) return serverAuthResult;
if (serverAuthResult != null)
return serverAuthResult;
serverAuthResult = _delegate.validateRequest(request, response, manditory);
if (serverAuthResult != null) _xcps.store(serverAuthResult, (HttpServletResponse)response);
if (serverAuthResult != null)
_xcps.store(serverAuthResult, (HttpServletResponse)response);
return serverAuthResult;
}

View File

@ -100,13 +100,14 @@ public interface UserIdentity
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
public interface UnauthticatedUserIdentity extends UserIdentity
public interface UnauthenticatedUserIdentity extends UserIdentity
{
UserIdentity login(ServletRequest request, ServletResponse response);
UserIdentity login(String username, String password);
};
public static final UserIdentity UNAUTHENTICATED_IDENTITY = new UserIdentity()
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
public static final UserIdentity UNAUTHENTICATED_IDENTITY = new UnauthenticatedUserIdentity()
{
public Subject getSubject()
{

View File

@ -84,7 +84,7 @@ public class ServletHandler extends AbstractHandler
private boolean _filterChainsCached=true;
private int _maxFilterChainsCacheSize=1000;
private boolean _startWithUnavailable=true;
private IdentityService<UserIdentity,?> _identityService;
private IdentityService _identityService;
private ServletHolder[] _servlets;
private ServletMapping[] _servletMappings;
@ -140,7 +140,7 @@ public class ServletHandler extends AbstractHandler
{
SecurityHandler security_handler = (SecurityHandler)_contextHandler.getChildHandlerByClass(SecurityHandler.class);
if (security_handler!=null)
_identityService=(IdentityService<UserIdentity,?>)security_handler.getIdentityService();
_identityService=security_handler.getIdentityService();
}
updateNameMappings();

View File

@ -263,7 +263,7 @@ public class ServletHolder extends Holder implements UserIdentity.Scope, Compara
try
{
if (_identityService!=null && _runAsToken!=null)
old_run_as=_identityService.associateRunAs(_runAsToken);
old_run_as=_identityService.associateRunAs(_identityService.getSystemUserIdentity(),_runAsToken);
destroyInstance(_servlet);
}
@ -405,7 +405,7 @@ public class ServletHolder extends Holder implements UserIdentity.Scope, Compara
// Handle run as
if (_identityService!=null && _runAsToken!=null)
{
old_run_as=_identityService.associateRunAs(_runAsToken);
old_run_as=_identityService.associateRunAs(_identityService.getSystemUserIdentity(),_runAsToken);
}
_servlet.init(_config);
@ -512,7 +512,7 @@ public class ServletHolder extends Holder implements UserIdentity.Scope, Compara
// Handle run as
if (_identityService!=null && _runAsToken!=null)
old_run_as=_identityService.associateRunAs(_runAsToken);
old_run_as=_identityService.associateRunAs(baseRequest.getUserIdentity(),_runAsToken);
if (!isAsyncSupported())
baseRequest.setAsyncSupported(false);