improved deferred authentication handling and fixed test harnesses

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@623 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Greg Wilkins 2009-08-03 08:54:41 +00:00
parent ff0450e1b8
commit 6e4f53cc3d
24 changed files with 317 additions and 504 deletions

View File

@ -31,8 +31,7 @@ import org.eclipse.jetty.security.Authenticator;
import org.eclipse.jetty.security.UserAuthentication;
import org.eclipse.jetty.security.ServerAuthException;
import org.eclipse.jetty.security.IdentityService;
import org.eclipse.jetty.security.authentication.DeferredAuthenticator;
import org.eclipse.jetty.security.authentication.DeferredAuthenticator.DeferredAuthentication;
import org.eclipse.jetty.security.authentication.DeferredAuthentication;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.server.Authentication.User;
@ -175,10 +174,4 @@ public class JaspiAuthenticator implements Authenticator
}
}
public boolean isMandatory(ServletRequest request)
{
return false;
}
}

View File

@ -108,8 +108,7 @@ public class JaspiAuthenticatorFactory extends DefaultAuthenticatorFactory
for (String key : configuration.getInitParameterNames())
map.put(key,configuration.getInitParameter(key));
authenticator= new JaspiAuthenticator(serverAuthConfig,map,servletCallbackHandler,
serviceSubject,
configuration.isLazy(), identityService);
serviceSubject,true, identityService);
}
}
}

View File

@ -102,8 +102,6 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
_realmName = name;
}
/* ------------------------------------------------------------ */
/** Get the identityService.
* @return the identityService
@ -113,7 +111,6 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
return _identityService;
}
/* ------------------------------------------------------------ */
/** Set the identityService.
* @param identityService the identityService to set
@ -123,7 +120,6 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
_identityService = identityService;
}
/* ------------------------------------------------------------ */
/**
* Set the name to use to index into the config
@ -136,7 +132,6 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
_loginModuleName = name;
}
/* ------------------------------------------------------------ */
public void setCallbackHandlerClass (String classname)
{
@ -228,6 +223,13 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
return null;
}
/* ------------------------------------------------------------ */
public boolean validate(UserIdentity user)
{
// TODO optionally check user is still valid
return true;
}
/* ------------------------------------------------------------ */
private String getUserName(CallbackHandler callbackHandler) throws IOException, UnsupportedCallbackException
{

View File

@ -62,16 +62,6 @@ public interface Authenticator
*/
Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException;
/* ------------------------------------------------------------ */
/** Ask Authenticator if authentication is mandatory for a specific request.
* This allows authenticators like FORM authentication to be called for specific requests like j_security_check,
* even if there is not constraint.
*
* @param request
* @return
*/
boolean isMandatory(ServletRequest request);
/* ------------------------------------------------------------ */
/**
* @param request
@ -94,7 +84,6 @@ public interface Authenticator
{
String getAuthMethod();
String getRealmName();
boolean isLazy();
String getInitParameter(String key);
Set<String> getInitParameterNames();
LoginService getLoginService();

View File

@ -250,14 +250,13 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
protected boolean checkUserDataPermissions(String pathInContext, Request request, Response response, Object constraintInfo) throws IOException
{
if (constraintInfo == null)
{
return true;
}
RoleInfo roleInfo = (RoleInfo)constraintInfo;
if (roleInfo.isForbidden())
{
return false;
}
UserDataConstraint dataConstraint = roleInfo.getUserDataConstraint();
if (dataConstraint == null || dataConstraint == UserDataConstraint.None)
{
@ -277,8 +276,11 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
url += "?" + request.getQueryString();
response.setContentLength(0);
response.sendRedirect(url);
request.setHandled(true);
}
else
response.sendError(Response.SC_FORBIDDEN,"!Integral");
request.setHandled(true);
return false;
}
else if (dataConstraint == UserDataConstraint.Confidential)
@ -295,8 +297,11 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
response.setContentLength(0);
response.sendRedirect(url);
request.setHandled(true);
}
else
response.sendError(Response.SC_FORBIDDEN,"!Confidential");
request.setHandled(true);
return false;
}
else

View File

@ -21,8 +21,6 @@ import org.eclipse.jetty.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.security.authentication.ClientCertAuthenticator;
import org.eclipse.jetty.security.authentication.DigestAuthenticator;
import org.eclipse.jetty.security.authentication.FormAuthenticator;
import org.eclipse.jetty.security.authentication.DeferredAuthenticator;
import org.eclipse.jetty.security.authentication.SessionCachingAuthenticator;
import org.eclipse.jetty.server.Server;
/* ------------------------------------------------------------ */
@ -56,13 +54,10 @@ public class DefaultAuthenticatorFactory implements Authenticator.Factory
else if (Constraint.__DIGEST_AUTH.equalsIgnoreCase(auth))
authenticator=new DigestAuthenticator();
else if (Constraint.__FORM_AUTH.equalsIgnoreCase(auth))
authenticator=new SessionCachingAuthenticator(new FormAuthenticator());
authenticator=new FormAuthenticator();
if (Constraint.__CERT_AUTH.equalsIgnoreCase(auth)||Constraint.__CERT_AUTH2.equalsIgnoreCase(auth))
authenticator=new ClientCertAuthenticator();
if (configuration.isLazy() && authenticator!=null)
authenticator=new DeferredAuthenticator(authenticator);
return authenticator;
}

View File

@ -129,7 +129,6 @@ public class HashLoginService extends MappedLoginService
@Override
protected UserIdentity loadUser(String username)
{
// TODO Auto-generated method stub
return null;
}

View File

@ -213,7 +213,6 @@ public class JDBCLoginService extends MappedLoginService
return super.login(username,credentials);
}
/* ------------------------------------------------------------ */
@Override
protected void loadUsers()

View File

@ -26,10 +26,39 @@ import org.eclipse.jetty.server.UserIdentity;
*/
public interface LoginService
{
String getName();
UserIdentity login(String username,Object credentials);
void logout(UserIdentity user);
/* ------------------------------------------------------------ */
/**
* @return Get the name of the login service (aka Realm name)
*/
String getName();
/* ------------------------------------------------------------ */
/** Login a user.
* @param username The user name
* @param credentials The users credentials
* @return A UserIdentity if the credentials matched, otherwise null
*/
UserIdentity login(String username,Object credentials);
/* ------------------------------------------------------------ */
/** Validate a user identity.
* Validate that a UserIdentity previously created by a call
* to {@link #login(String, Object)} is still valid.
* @param user The user to validate
* @return true if authentication has not been revoked for the user.
*/
boolean validate(UserIdentity user);
/* ------------------------------------------------------------ */
/** Get the IdentityService associated with this Login Service.
* @return the IdentityService associated with this Login Service.
*/
IdentityService getIdentityService();
/* ------------------------------------------------------------ */
/** Set the IdentityService associated with this Login Service.
* @param service the IdentityService associated with this Login Service.
*/
void setIdentityService(IdentityService service);
}

View File

@ -181,6 +181,12 @@ public abstract class MappedLoginService extends AbstractLifeCycle implements Lo
return identity;
}
/* ------------------------------------------------------------ */
public void removeUser(String username)
{
_users.remove(username);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.security.LoginService#login(java.lang.String, java.lang.Object)
@ -202,9 +208,15 @@ public abstract class MappedLoginService extends AbstractLifeCycle implements Lo
}
/* ------------------------------------------------------------ */
public void logout(UserIdentity user)
public boolean validate(UserIdentity user)
{
// TODO maybe clear cache?
if (_users.containsKey(user.getUserPrincipal().getName()))
return true;
if (loadUser(user.getUserPrincipal().getName())!=null)
return true;
return false;
}
/* ------------------------------------------------------------ */

View File

@ -25,7 +25,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.security.authentication.DeferredAuthenticator.DeferredAuthentication;
import org.eclipse.jetty.security.authentication.DeferredAuthentication;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConnection;
@ -57,7 +57,6 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
private boolean _checkWelcomeFiles = false;
private Authenticator _authenticator;
private Authenticator.Factory _authenticatorFactory=new DefaultAuthenticatorFactory();
private boolean _isLazy=true;
private String _realmName;
private String _authMethod;
private final Map<String,String> _initParameters=new HashMap<String,String>();
@ -151,27 +150,6 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
_authenticatorFactory = authenticatorFactory;
}
/* ------------------------------------------------------------ */
/**
* @return the isLazy
*/
public boolean isLazy()
{
return _isLazy;
}
/* ------------------------------------------------------------ */
/**
* @param isLazy the isLazy to set
* @throws IllegalStateException if the SecurityHandler is running
*/
public void setLazy(boolean isLazy)
{
if (isRunning())
throw new IllegalStateException("running");
_isLazy = isLazy;
}
/* ------------------------------------------------------------ */
/**
* @return the realmName
@ -421,7 +399,7 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
{
if (!baseRequest.isHandled())
{
response.sendError(Response.SC_FORBIDDEN,"!data constraint");
response.sendError(Response.SC_FORBIDDEN);
baseRequest.setHandled(true);
}
return;
@ -429,8 +407,7 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
// is Auth mandatory?
boolean isAuthMandatory =
isAuthMandatory(baseRequest, base_response, constraintInfo) ||
authenticator.isMandatory(request);
isAuthMandatory(baseRequest, base_response, constraintInfo);
// check authentication
Object previousIdentity = null;
@ -472,8 +449,8 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
}
else if (authentication instanceof Authentication.Deferred)
{
DeferredAuthentication lazy= (DeferredAuthentication)authentication;
lazy.setIdentityService(_identityService);
DeferredAuthentication deferred= (DeferredAuthentication)authentication;
deferred.setIdentityService(_identityService);
baseRequest.setAuthentication(authentication);
try
@ -482,9 +459,10 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
}
finally
{
previousIdentity = lazy.getPreviousAssociation();
lazy.setIdentityService(null);
previousIdentity = deferred.getPreviousAssociation();
deferred.setIdentityService(null);
}
Authentication auth=baseRequest.getAuthentication();
if (auth instanceof Authentication.User)
{

View File

@ -13,7 +13,6 @@
package org.eclipse.jetty.security;
import org.eclipse.jetty.security.authentication.DelegateAuthenticator;
import org.eclipse.jetty.security.authentication.LoginAuthenticator;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.UserIdentity;
@ -51,23 +50,16 @@ public class UserAuthentication implements Authentication.User
public void logout()
{
Authenticator authenticator = _authenticator;
while (true)
final Authenticator authenticator = _authenticator;
if (authenticator instanceof LoginAuthenticator)
{
if (authenticator instanceof LoginAuthenticator)
{
((LoginAuthenticator)authenticator).getLoginService().logout(this.getUserIdentity());
break;
}
else if (authenticator instanceof DelegateAuthenticator)
{
authenticator=((DelegateAuthenticator)authenticator).getDelegate();
}
else
break;
IdentityService id_service=((LoginAuthenticator)authenticator).getLoginService().getIdentityService();
if (id_service!=null)
id_service.disassociate(null); // TODO provide the previous value
}
}
@Override
public String toString()
{
return "{Auth,"+getAuthMethod()+","+_userIdentity+"}";

View File

@ -64,6 +64,9 @@ public class BasicAuthenticator extends LoginAuthenticator
try
{
if (!mandatory)
return _deferred;
if (credentials != null)
{
credentials = credentials.substring(credentials.indexOf(' ')+1);
@ -77,13 +80,12 @@ public class BasicAuthenticator extends LoginAuthenticator
return new UserAuthentication(this,user);
}
if (mandatory)
{
response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "basic realm=\"" + _loginService.getName() + '"');
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return Authentication.SEND_CONTINUE;
}
return credentials==null?Authentication.NOT_CHECKED:Authentication.UNAUTHENTICATED;
if (_deferred.isDeferred(response))
return Authentication.UNAUTHENTICATED;
response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "basic realm=\"" + _loginService.getName() + '"');
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return Authentication.SEND_CONTINUE;
}
catch (IOException e)
{
@ -91,7 +93,6 @@ public class BasicAuthenticator extends LoginAuthenticator
}
}
// TODO most likely validatedUser is not needed here ??
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, User validatedUser) throws ServerAuthException
{
return true;

View File

@ -46,15 +46,14 @@ public class ClientCertAuthenticator extends LoginAuthenticator
}
/**
* TODO what should happen if an insecure page is accessed without a client
* cert? Current code requires a client cert always but allows access to
* insecure pages if it is not recognized.
*
* @return
* @throws ServerAuthException
*/
public Authentication validateRequest(ServletRequest req, ServletResponse res, boolean mandatory) throws ServerAuthException
{
if (!mandatory)
return _deferred;
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
@ -72,7 +71,6 @@ public class ClientCertAuthenticator extends LoginAuthenticator
if (principal == null) principal = cert.getIssuerDN();
final String username = principal == null ? "clientcert" : principal.getName();
// TODO no idea if this is correct
final char[] credential = B64Code.encode(cert.getSignature());
UserIdentity user = _loginService.login(username,credential);
@ -81,13 +79,13 @@ public class ClientCertAuthenticator extends LoginAuthenticator
}
}
if (mandatory)
if (!_deferred.isDeferred(response))
{
response.sendError(HttpServletResponse.SC_FORBIDDEN);
return Authentication.SEND_FAILURE;
}
return certs==null?Authentication.NOT_CHECKED:Authentication.UNAUTHENTICATED;
return Authentication.UNAUTHENTICATED;
}
catch (IOException e)
{

View File

@ -1,5 +1,5 @@
// ========================================================================
// Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd.
// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
@ -11,6 +11,7 @@
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.security.authentication;
import java.io.IOException;
@ -27,145 +28,114 @@ import org.eclipse.jetty.security.Authenticator;
import org.eclipse.jetty.security.IdentityService;
import org.eclipse.jetty.security.ServerAuthException;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.Log;
/**
* Deferred Authentictor
* <p>
* Authenticator that defers non manditory authentication by
* returning a {@link Authentication.Deferred} instance that
* defers authentication until a call
* to {@link Authentication.Deferred#authenticate()} or
* {@link Authentication.Deferred#authenticate(ServletRequest, ServletResponse)}.
*
* @version $Rev: 4793 $ $Date: 2009-03-19 00:00:01 +0100 (Thu, 19 Mar 2009) $
*/
public class DeferredAuthenticator extends DelegateAuthenticator
public class DeferredAuthentication implements Authentication.Deferred
{
private final DeferredAuthentication _deferred;
protected final Authenticator _authenticator;
private IdentityService _identityService;
private Object _previousAssociation;
public DeferredAuthentication(Authenticator authenticator)
{
if (authenticator == null)
throw new NullPointerException("No Authenticator");
this._authenticator = authenticator;
}
/* ------------------------------------------------------------ */
public DeferredAuthenticator(Authenticator delegate)
/** Get the identityService.
* @return the identityService
*/
public IdentityService getIdentityService()
{
super(delegate);
_deferred=new DeferredAuthentication(delegate);
return _identityService;
}
/* ------------------------------------------------------------ */
/** Set the identityService.
* @param identityService the identityService to set
*/
public void setIdentityService(IdentityService identityService)
{
_identityService = identityService;
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.security.Authenticator#validateRequest(ServletRequest,
* ServletResponse, boolean)
* @see org.eclipse.jetty.server.Authentication.Deferred#authenticate()
*/
public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException
public Authentication authenticate(ServletRequest request)
{
if (!mandatory)
return _deferred;
return _delegate.validateRequest(request,response,mandatory);
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
public static class DeferredAuthentication implements Authentication.Deferred
{
protected final Authenticator _authenticator;
private IdentityService _identityService;
private Object _previousAssociation;
public DeferredAuthentication(Authenticator authenticator)
try
{
if (authenticator == null)
throw new NullPointerException("No Authenticator");
this._authenticator = authenticator;
}
Authentication authentication = _authenticator.validateRequest(request,__deferredResponse,true);
/* ------------------------------------------------------------ */
/** Get the identityService.
* @return the identityService
*/
public IdentityService getIdentityService()
{
return _identityService;
}
/* ------------------------------------------------------------ */
/** Set the identityService.
* @param identityService the identityService to set
*/
public void setIdentityService(IdentityService identityService)
{
_identityService = identityService;
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.Authentication.Deferred#authenticate()
*/
public Authentication authenticate(ServletRequest request)
{
try
if (authentication!=null && (authentication instanceof Authentication.User) && !(authentication instanceof Authentication.ResponseSent))
{
Authentication authentication = _authenticator.validateRequest(request,__nullResponse,false);
if (authentication!=null && (authentication instanceof Authentication.User) && !(authentication instanceof Authentication.ResponseSent))
{
if (_identityService!=null)
_previousAssociation=_identityService.associate(((Authentication.User)authentication).getUserIdentity());
return authentication;
}
}
catch (ServerAuthException e)
{
Log.debug(e);
}
return Authentication.UNAUTHENTICATED;
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.Authentication.Deferred#authenticate(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
*/
public Authentication authenticate(ServletRequest request, ServletResponse response)
{
try
{
Authentication authentication = _authenticator.validateRequest(request,response,true);
if (authentication instanceof Authentication.User && _identityService!=null)
if (_identityService!=null)
_previousAssociation=_identityService.associate(((Authentication.User)authentication).getUserIdentity());
return authentication;
}
catch (ServerAuthException e)
{
Log.debug(e);
}
return Authentication.UNAUTHENTICATED;
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.Authentication.Deferred#login(java.lang.String, java.lang.String)
*/
public Authentication login(String username, String password)
catch (ServerAuthException e)
{
return null; // TODO implement
}
/* ------------------------------------------------------------ */
public Object getPreviousAssociation()
{
return _previousAssociation;
Log.debug(e);
}
return Authentication.UNAUTHENTICATED;
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.Authentication.Deferred#authenticate(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
*/
public Authentication authenticate(ServletRequest request, ServletResponse response)
{
try
{
Authentication authentication = _authenticator.validateRequest(request,response,true);
if (authentication instanceof Authentication.User && _identityService!=null)
_previousAssociation=_identityService.associate(((Authentication.User)authentication).getUserIdentity());
return authentication;
}
catch (ServerAuthException e)
{
Log.debug(e);
}
return Authentication.UNAUTHENTICATED;
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.Authentication.Deferred#login(java.lang.String, java.lang.String)
*/
public Authentication login(String username, String password)
{
return null; // TODO implement
}
/* ------------------------------------------------------------ */
public Object getPreviousAssociation()
{
return _previousAssociation;
}
/* ------------------------------------------------------------ */
/**
* @param response
* @return true if this response is from a deferred call to {@link #authenticate(ServletRequest)}
*/
public boolean isDeferred(HttpServletResponse response)
{
return response==__deferredResponse;
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
private static HttpServletResponse __nullResponse = new HttpServletResponse()
static HttpServletResponse __deferredResponse = new HttpServletResponse()
{
public void addCookie(Cookie cookie)
{
@ -327,4 +297,5 @@ public class DeferredAuthenticator extends DelegateAuthenticator
}
};
}

View File

@ -1,62 +0,0 @@
// ========================================================================
// Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.security.authentication;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.eclipse.jetty.security.Authenticator;
import org.eclipse.jetty.security.ServerAuthException;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.Authentication.User;
public class DelegateAuthenticator implements Authenticator
{
protected final Authenticator _delegate;
public void setConfiguration(Configuration configuration)
{
_delegate.setConfiguration(configuration);
}
public String getAuthMethod()
{
return _delegate.getAuthMethod();
}
public DelegateAuthenticator(Authenticator delegate)
{
_delegate=delegate;
}
public Authenticator getDelegate()
{
return _delegate;
}
public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean manditory) throws ServerAuthException
{
return _delegate.validateRequest(request, response, manditory);
}
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, User validatedUser) throws ServerAuthException
{
return _delegate.secureResponse(req,res, mandatory, validatedUser);
}
public boolean isMandatory(ServletRequest request)
{
return _delegate.isMandatory(request);
}
}

View File

@ -62,6 +62,9 @@ public class DigestAuthenticator extends LoginAuthenticator
public Authentication validateRequest(ServletRequest req, ServletResponse res, boolean mandatory) throws ServerAuthException
{
if (mandatory)
return _deferred;
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
String credentials = request.getHeader(HttpHeaders.AUTHORIZATION);
@ -130,7 +133,7 @@ public class DigestAuthenticator extends LoginAuthenticator
}
if (mandatory)
if (!_deferred.isDeferred(response))
{
String domain = request.getContextPath();
if (domain == null)
@ -147,7 +150,7 @@ public class DigestAuthenticator extends LoginAuthenticator
return Authentication.SEND_CONTINUE;
}
return credentials==null?Authentication.NOT_CHECKED:Authentication.UNAUTHENTICATED;
return Authentication.UNAUTHENTICATED;
}
catch (IOException e)
{

View File

@ -59,11 +59,11 @@ public class FormAuthenticator extends LoginAuthenticator
public final static String __FORM_LOGIN_PAGE="org.eclipse.jetty.security.form_login_page";
public final static String __FORM_ERROR_PAGE="org.eclipse.jetty.security.form_error_page";
public final static String __FORM_DISPATCH="org.eclipse.jetty.security.dispatch";
public final static String __J_URI = "org.eclipse.jetty.util.URI";
public final static String __J_AUTHENTICATED = "org.eclipse.jetty.server.Auth";
public final static String __J_URI = "org.eclipse.jetty.security.form_URI";
public final static String __J_SECURITY_CHECK = "/j_security_check";
public final static String __J_USERNAME = "j_username";
public final static String __J_PASSWORD = "j_password";
private String _formErrorPage;
private String _formErrorPath;
private String _formLoginPage;
@ -151,22 +151,23 @@ public class FormAuthenticator extends LoginAuthenticator
{
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
HttpSession session = request.getSession(mandatory);
String uri = request.getRequestURI();
if (uri==null)
uri=URIUtil.SLASH;
// not mandatory or not authenticated
if (session == null || isLoginOrErrorPage(uri))
{
mandatory|=uri.endsWith(__J_SECURITY_CHECK);
if (!mandatory)
return _deferred;
if (isLoginOrErrorPage(uri))
return Authentication.NOT_CHECKED;
}
HttpSession session = request.getSession(true);
try
{
// Handle a request for authentication.
if (uri==null)
uri=URIUtil.SLASH;
else if (uri.endsWith(__J_SECURITY_CHECK))
if (uri.endsWith(__J_SECURITY_CHECK))
{
final String username = request.getParameter(__J_USERNAME);
final String password = request.getParameter(__J_PASSWORD);
@ -190,6 +191,9 @@ public class FormAuthenticator extends LoginAuthenticator
}
response.setContentLength(0);
response.sendRedirect(response.encodeRedirectURL(nuri));
Authentication cached=new SessionAuthentication(session,this,user);
session.setAttribute(SessionAuthentication.__J_AUTHENTICATED, cached);
return new FormAuthentication(this,user);
}
@ -216,35 +220,52 @@ public class FormAuthenticator extends LoginAuthenticator
return Authentication.SEND_FAILURE;
}
if (mandatory)
// Look for cached authentication
Authentication authentication = (Authentication) session.getAttribute(SessionAuthentication.__J_AUTHENTICATED);
if (authentication != null)
{
// redirect to login page
synchronized (session)
{
if (session.getAttribute(__J_URI)==null)
{
StringBuffer buf = request.getRequestURL();
if (request.getQueryString() != null)
buf.append("?").append(request.getQueryString());
session.setAttribute(__J_URI, buf.toString());
}
}
// Has authentication been revoked?
if (authentication instanceof Authentication.User &&
_loginService!=null &&
!_loginService.validate(((Authentication.User)authentication).getUserIdentity()))
if (_dispatch)
{
RequestDispatcher dispatcher = request.getRequestDispatcher(_formLoginPage);
response.setHeader(HttpHeaders.CACHE_CONTROL,"No-cache");
response.setDateHeader(HttpHeaders.EXPIRES,1);
dispatcher.forward(new FormRequest(request), new FormResponse(response));
}
session.removeAttribute(SessionAuthentication.__J_AUTHENTICATED);
else
{
response.sendRedirect(URIUtil.addPaths(request.getContextPath(),_formLoginPage));
}
return Authentication.SEND_CONTINUE;
return authentication;
}
return Authentication.UNAUTHENTICATED;
// remember the current URI
synchronized (session)
{
// TODO is this right?
if (session.getAttribute(__J_URI)==null)
{
StringBuffer buf = request.getRequestURL();
if (request.getQueryString() != null)
buf.append("?").append(request.getQueryString());
session.setAttribute(__J_URI, buf.toString());
}
}
// if we can't send challenge
if (_deferred.isDeferred(response))
return Authentication.UNAUTHENTICATED;
// send the the challenge
if (_dispatch)
{
RequestDispatcher dispatcher = request.getRequestDispatcher(_formLoginPage);
response.setHeader(HttpHeaders.CACHE_CONTROL,"No-cache");
response.setDateHeader(HttpHeaders.EXPIRES,1);
dispatcher.forward(new FormRequest(request), new FormResponse(response));
}
else
{
response.sendRedirect(URIUtil.addPaths(request.getContextPath(),_formLoginPage));
}
return Authentication.SEND_CONTINUE;
}
catch (IOException e)
{
@ -262,12 +283,6 @@ public class FormAuthenticator extends LoginAuthenticator
return pathInContext != null && (pathInContext.equals(_formErrorPath) || pathInContext.equals(_formLoginPath));
}
/* ------------------------------------------------------------ */
public boolean isMandatory(ServletRequest request)
{
return ((HttpServletRequest)request).getRequestURI().endsWith(__J_SECURITY_CHECK);
}
/* ------------------------------------------------------------ */
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, User validatedUser) throws ServerAuthException
{

View File

@ -13,14 +13,13 @@
package org.eclipse.jetty.security.authentication;
import javax.servlet.ServletRequest;
import org.eclipse.jetty.security.Authenticator;
import org.eclipse.jetty.security.IdentityService;
import org.eclipse.jetty.security.LoginService;
public abstract class LoginAuthenticator implements Authenticator
{
protected final DeferredAuthentication _deferred=new DeferredAuthentication(this);
protected LoginService _loginService;
protected IdentityService _identityService;
@ -42,9 +41,4 @@ public abstract class LoginAuthenticator implements Authenticator
{
return _loginService;
}
public boolean isMandatory(ServletRequest request)
{
return false;
}
}

View File

@ -0,0 +1,62 @@
// ========================================================================
// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.security.authentication;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import org.eclipse.jetty.security.Authenticator;
import org.eclipse.jetty.security.UserAuthentication;
import org.eclipse.jetty.server.UserIdentity;
class SessionAuthentication extends UserAuthentication implements HttpSessionAttributeListener
{
public final static String __J_AUTHENTICATED="org.eclipse.jetty.security.UserIdentity";
HttpSession _session;
public SessionAuthentication(HttpSession session,Authenticator authenticator, UserIdentity userIdentity)
{
super(authenticator,userIdentity);
_session=session;
}
public void attributeAdded(HttpSessionBindingEvent event)
{
}
public void attributeRemoved(HttpSessionBindingEvent event)
{
super.logout();
}
public void attributeReplaced(HttpSessionBindingEvent event)
{
if (event.getValue()==null)
super.logout();
}
public void logout()
{
_session.removeAttribute(SessionAuthentication.__J_AUTHENTICATED);
}
public String toString()
{
return "Session"+super.toString();
}
}

View File

@ -1,91 +0,0 @@
// ========================================================================
// Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.security.authentication;
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.Authenticator;
import org.eclipse.jetty.security.UserAuthentication;
import org.eclipse.jetty.security.ServerAuthException;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.UserIdentity;
/**
* @version $Rev: 4793 $ $Date: 2009-03-19 00:00:01 +0100 (Thu, 19 Mar 2009) $
*/
public class SessionCachingAuthenticator extends DelegateAuthenticator
{
public final static String __J_AUTHENTICATED = "org.eclipse.jetty.server.Auth";
public SessionCachingAuthenticator(Authenticator delegate)
{
super(delegate);
}
public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException
{
HttpSession session = ((HttpServletRequest)request).getSession(mandatory);
// not mandatory and not authenticated
if (session == null)
return Authentication.NOT_CHECKED;
Authentication authentication = (Authentication) session.getAttribute(__J_AUTHENTICATED);
if (authentication != null)
return authentication;
authentication = _delegate.validateRequest(request, response, mandatory);
if (authentication instanceof Authentication.User)
{
Authentication cached=new SessionAuthentication(_delegate,((Authentication.User)authentication).getUserIdentity());
session.setAttribute(__J_AUTHENTICATED, cached);
}
return authentication;
}
protected class SessionAuthentication extends UserAuthentication implements HttpSessionAttributeListener
{
public SessionAuthentication(Authenticator authenticator, UserIdentity userIdentity)
{
super(authenticator,userIdentity);
}
public void attributeAdded(HttpSessionBindingEvent event)
{
}
public void attributeRemoved(HttpSessionBindingEvent event)
{
logout();
}
public void attributeReplaced(HttpSessionBindingEvent arg0)
{
logout();
}
public String toString()
{
return "Session"+super.toString();
}
}
}

View File

@ -1,57 +0,0 @@
// ========================================================================
// Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.security.authentication;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.security.Authenticator;
import org.eclipse.jetty.security.CrossContextPsuedoSession;
import org.eclipse.jetty.security.ServerAuthException;
import org.eclipse.jetty.server.Authentication;
/**
* Cross-context psuedo-session caching ServerAuthentication
*
* @version $Rev: 4793 $ $Date: 2009-03-19 00:00:01 +0100 (Thu, 19 Mar 2009) $
*/
public class XCPSCachingAuthenticator extends DelegateAuthenticator
{
public final static String __J_AUTHENTICATED = "org.eclipse.jetty.server.Auth";
private final CrossContextPsuedoSession<Authentication> _xcps;
public XCPSCachingAuthenticator(Authenticator delegate, CrossContextPsuedoSession<Authentication> xcps)
{
super(delegate);
this._xcps = xcps;
}
public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean manditory) throws ServerAuthException
{
Authentication serverAuthResult = _xcps.fetch((HttpServletRequest)request);
if (serverAuthResult != null)
return serverAuthResult;
serverAuthResult = _delegate.validateRequest(request, response, manditory);
if (serverAuthResult != null)
_xcps.store(serverAuthResult, (HttpServletResponse)response);
return serverAuthResult;
}
}

View File

@ -29,9 +29,7 @@ import org.eclipse.jetty.http.security.B64Code;
import org.eclipse.jetty.http.security.Constraint;
import org.eclipse.jetty.http.security.Password;
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.security.authentication.DeferredAuthenticator;
import org.eclipse.jetty.security.authentication.FormAuthenticator;
import org.eclipse.jetty.security.authentication.SessionCachingAuthenticator;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.LocalConnector;
@ -117,8 +115,7 @@ public class Constrain2tTest extends TestCase
throws Exception
{
_context.setContextPath("/");
_security.setAuthenticator(new SessionCachingAuthenticator(
new FormAuthenticator("/testLoginPage","/testErrorPage",true)));
_security.setAuthenticator(new FormAuthenticator("/testLoginPage","/testErrorPage",true));
_security.setStrict(false);
_server.start();
@ -170,8 +167,7 @@ public class Constrain2tTest extends TestCase
throws Exception
{
_context.setContextPath("/");
_security.setAuthenticator(new SessionCachingAuthenticator(
new FormAuthenticator("/testLoginPage","/testErrorPage",false)));
_security.setAuthenticator(new FormAuthenticator("/testLoginPage","/testErrorPage",false));
_security.setStrict(false);
_server.start();

View File

@ -29,9 +29,7 @@ import org.eclipse.jetty.http.security.B64Code;
import org.eclipse.jetty.http.security.Constraint;
import org.eclipse.jetty.http.security.Password;
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.security.authentication.DeferredAuthenticator;
import org.eclipse.jetty.security.authentication.FormAuthenticator;
import org.eclipse.jetty.security.authentication.SessionCachingAuthenticator;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.LocalConnector;
@ -234,8 +232,7 @@ public class ConstraintTest extends TestCase
public void testFormdispatch()
throws Exception
{
_security.setAuthenticator(new SessionCachingAuthenticator(
new FormAuthenticator("/testLoginPage","/testErrorPage",true)));
_security.setAuthenticator(new FormAuthenticator("/testLoginPage","/testErrorPage",true));
_security.setStrict(false);
_server.start();
@ -251,8 +248,6 @@ public class ConstraintTest extends TestCase
_connector.reopen();
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n\r\n");
// assertTrue(response.indexOf(" 302 Found") > 0);
// assertTrue(response.indexOf("/ctx/testLoginPage") > 0);
assertTrue(response.indexOf("Cache-Control: no-cache") > 0);
assertTrue(response.indexOf("Expires") > 0);
assertTrue(response.indexOf("URI=/ctx/testLoginPage") > 0);
@ -266,7 +261,6 @@ public class ConstraintTest extends TestCase
"Content-Length: 31\r\n" +
"\r\n" +
"j_username=user&j_password=wrong\r\n");
//assertTrue(response.indexOf("Location") > 0);
assertTrue(response.indexOf("testErrorPage") > 0);
@ -299,8 +293,7 @@ public class ConstraintTest extends TestCase
public void testFormRedirect()
throws Exception
{
_security.setAuthenticator(new SessionCachingAuthenticator(
new FormAuthenticator("/testLoginPage","/testErrorPage",false)));
_security.setAuthenticator(new FormAuthenticator("/testLoginPage","/testErrorPage",false));
_security.setStrict(false);
_server.start();
@ -431,8 +424,7 @@ public class ConstraintTest extends TestCase
public void testStrictFormDispatch()
throws Exception
{
_security.setAuthenticator(new SessionCachingAuthenticator(
new FormAuthenticator("/testLoginPage","/testErrorPage",true)));
_security.setAuthenticator(new FormAuthenticator("/testLoginPage","/testErrorPage",true));
_server.start();
@ -565,8 +557,7 @@ public class ConstraintTest extends TestCase
public void testStrictFormRedirect()
throws Exception
{
_security.setAuthenticator(new SessionCachingAuthenticator(
new FormAuthenticator("/testLoginPage","/testErrorPage",false)));
_security.setAuthenticator(new FormAuthenticator("/testLoginPage","/testErrorPage",false));
_server.start();
@ -730,7 +721,7 @@ public class ConstraintTest extends TestCase
public void testDeferredBasic()
throws Exception
{
_security.setAuthenticator(new DeferredAuthenticator(new BasicAuthenticator()));
_security.setAuthenticator(new BasicAuthenticator());
_security.setStrict(false);
_server.start();