reworked deferred authentication

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@155 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Greg Wilkins 2009-04-17 00:21:50 +00:00
parent 5ff3346774
commit ed2408538b
24 changed files with 859 additions and 745 deletions

View File

@ -3,7 +3,8 @@ jetty-7.0.0.M1-SNAPSHOT
+ Initial support for LoginService.logout
+ Removed HTTPConnection specifics from connection dispatching
+ JETTY-695 Handler dump
+ Reworked lazy authentication
+ Reworked authentication for deferred authentication
jetty-7.0.0.M0
+ JETTY-496 Support inetd/xinetd through use of System.inheritedChannel()

View File

@ -29,12 +29,14 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.security.Authentication;
import org.eclipse.jetty.security.Authenticator;
import org.eclipse.jetty.security.DefaultAuthentication;
import org.eclipse.jetty.security.LazyAuthentication;
import org.eclipse.jetty.security.UserAuthentication;
import org.eclipse.jetty.security.ServerAuthException;
import org.eclipse.jetty.security.authentication.FormAuthenticator;
import org.eclipse.jetty.security.authentication.DeferredAuthenticator;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.server.Authentication.User;
/**
* @version $Rev: 4793 $ $Date: 2009-03-19 00:00:01 +0100 (Thu, 19 Mar 2009) $
@ -79,7 +81,7 @@ public class JaspiAuthenticator implements Authenticator
public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException
{
if (_allowLazyAuthentication && !mandatory)
return new LazyAuthentication(this,request,response);
return new DeferredAuthenticator.DeferredAuthentication(this,request,response);
JaspiMessageInfo info = new JaspiMessageInfo((HttpServletRequest)request,(HttpServletResponse)response,mandatory);
request.setAttribute("org.eclipse.jetty.security.jaspi.info",info);
@ -87,7 +89,7 @@ public class JaspiAuthenticator implements Authenticator
}
// most likely validatedUser is not needed here.
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication validatedUser) throws ServerAuthException
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, User validatedUser) throws ServerAuthException
{
JaspiMessageInfo info = (JaspiMessageInfo)req.getAttribute("org.eclipse.jetty.security.jaspi.info");
if (info==null)
@ -113,16 +115,16 @@ public class JaspiAuthenticator implements Authenticator
if (authStatus == AuthStatus.SEND_CONTINUE)
return Authentication.CHALLENGE;
if (authStatus == AuthStatus.SEND_FAILURE)
return Authentication.FAILED;
return Authentication.FAILURE;
Set<UserIdentity> ids = clientSubject.getPrivateCredentials(UserIdentity.class);
if (ids.size()>0)
{
if (authStatus == AuthStatus.SEND_SUCCESS)
return new DefaultAuthentication.Send(this,ids.iterator().next());
return new DefaultAuthentication(this,ids.iterator().next());
return new FormAuthenticator.FormAuthentication(this,ids.iterator().next());
return new UserAuthentication(this,ids.iterator().next());
}
return Authentication.FAILED;
return Authentication.FAILURE;
}
catch (AuthException e)
{
@ -135,7 +137,7 @@ public class JaspiAuthenticator implements Authenticator
try
{
ServerAuthContext authContext = _authConfig.getAuthContext(_authContextId,_serviceSubject,_authProperties);
authContext.cleanSubject(messageInfo,validatedUser.getUserIdentity().getSubject());
// TODO authContext.cleanSubject(messageInfo,validatedUser.getUserIdentity().getSubject());
AuthStatus status = authContext.secureResponse(messageInfo,_serviceSubject);
return (AuthStatus.SUCCESS.equals(status));
}

View File

@ -1,120 +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;
import org.eclipse.jetty.server.UserIdentity;
/**
* Authentication state of a user.
*
* @version $Rev: 4701 $ $Date: 2009-03-03 13:01:26 +0100 (Tue, 03 Mar 2009) $
*/
public interface Authentication
{
String getAuthMethod();
UserIdentity getUserIdentity();
boolean isSuccess();
boolean isSend();
void logout();
public static final Authentication FAILED = new Authentication()
{
public String getAuthMethod()
{
return null;
}
public UserIdentity getUserIdentity()
{
return UserIdentity.UNAUTHENTICATED_IDENTITY;
}
public boolean isSuccess()
{
return false;
}
public boolean isSend()
{
return true;
}
public void logout()
{
}
};
public static final Authentication CHALLENGE = new Authentication()
{
public String getAuthMethod()
{
return null;
}
public UserIdentity getUserIdentity()
{
return UserIdentity.UNAUTHENTICATED_IDENTITY;
}
public boolean isSuccess()
{
return false;
}
public boolean isSend()
{
return true;
}
public void logout()
{
}
};
public static final Authentication NOT_CHECKED = new Authentication()
{
public String getAuthMethod()
{
return null;
}
public UserIdentity getUserIdentity()
{
return UserIdentity.UNAUTHENTICATED_IDENTITY;
}
public boolean isSuccess()
{
return false;
}
public boolean isSend()
{
return false;
}
public void logout()
{
}
};
}

View File

@ -19,22 +19,68 @@ import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.Authentication.User;
/**
* This is like the JASPI ServerAuthContext but is intended to be easier to use
* and allow lazy auth.
* Authenticator Interface
* <p>
* An Authenticator is responsible for checking requests and sending
* response challenges in order to authenticate a request.
* Various types of {@link Authentication} are returned in order to
* signal the next step in authentication.
*
* @version $Rev: 4793 $ $Date: 2009-03-19 00:00:01 +0100 (Thu, 19 Mar 2009) $
*/
public interface Authenticator
{
/* ------------------------------------------------------------ */
/**
* Configure the Authenticator
* @param configuration
*/
void setConfiguration(Configuration configuration);
/* ------------------------------------------------------------ */
/**
* @return The name of the authentication method
*/
String getAuthMethod();
/* ------------------------------------------------------------ */
/** Validate a response
* @param request The request
* @param response The response
* @param mandatory True if authentication is mandatory.
* @return An Authentication. If Authentication is successful, this will be a {@link Authentication.User}. If a response has
* been sent by the Authenticator (which can be done for both successful and unsuccessful authentications), then the result will
* implement {@link Authentication.ResponseSent}. If Authentication is not manditory, then a {@link Authentication.Deferred}
* may be returned.
*
* @throws ServerAuthException
*/
Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException;
boolean secureResponse(ServletRequest request, ServletResponse response, boolean mandatory, Authentication validatedUser) throws ServerAuthException;
/* ------------------------------------------------------------ */
/**
* @param request
* @param response
* @param mandatory
* @param validatedUser
* @return
* @throws ServerAuthException
*/
boolean secureResponse(ServletRequest request, ServletResponse response, boolean mandatory, User validatedUser) throws ServerAuthException;
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/**
* Authenticator Configuration
*/
interface Configuration
{
String getAuthMethod();
@ -46,6 +92,12 @@ public interface Authenticator
IdentityService getIdentityService();
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/**
* Authenticator Facotory
*/
interface Factory
{
Authenticator getAuthenticator(Server server, ServletContext context, Configuration configuration);

View File

@ -21,7 +21,7 @@ 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.LazyAuthenticator;
import org.eclipse.jetty.security.authentication.DeferredAuthenticator;
import org.eclipse.jetty.security.authentication.SessionCachingAuthenticator;
import org.eclipse.jetty.server.Server;
@ -34,7 +34,7 @@ import org.eclipse.jetty.server.Server;
* <li>{@link FormAuthenticator}</li>
* <li>{@link ClientCertAuthenticator}</li>
* </ul>
* If {@link Configuration#isLazy()} is true, the Authenticator is wrapped with a {@link LazyAuthenticator}
* If {@link Configuration#isLazy()} is true, the Authenticator is wrapped with a {@link DeferredAuthenticator}
* instance. The FormAuthenticator is always wrapped in a {@link SessionCachingAuthenticator}.
* <p>
* If a {@link LoginService} has not been set on this factory, then
@ -61,7 +61,7 @@ public class DefaultAuthenticatorFactory implements Authenticator.Factory
authenticator=new ClientCertAuthenticator();
if (configuration.isLazy() && authenticator!=null)
authenticator=new LazyAuthenticator(authenticator);
authenticator=new DeferredAuthenticator(authenticator);
return authenticator;
}

View File

@ -19,7 +19,6 @@ import java.util.Map;
import javax.security.auth.Subject;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.server.UserIdentity.Scope;
/* ------------------------------------------------------------ */
@ -43,15 +42,7 @@ public class DefaultIdentityService implements IdentityService
* If there are roles refs present in the scope, then wrap the UserIdentity
* with one that uses the role references in the {@link UserIdentity#isUserInRole(String)}
*/
public UserIdentity scope(UserIdentity user, Scope scope)
{
Map<String,String> roleRefMap=scope.getRoleRefMap();
if (roleRefMap!=null && roleRefMap.size()>0)
return new RoleRefUserIdentity(user,roleRefMap);
return user;
}
public void descope(UserIdentity scoped)
public void associate(UserIdentity user)
{
}
@ -79,36 +70,4 @@ public class DefaultIdentityService implements IdentityService
return new DefaultUserIdentity(subject,userPrincipal,roles);
}
/* ------------------------------------------------------------ */
/**
* Wrapper UserIdentity used to apply RoleRef map.
*
*/
public static class RoleRefUserIdentity implements UserIdentity
{
final private UserIdentity _delegate;
final private Map<String,String> _roleRefMap;
public RoleRefUserIdentity(final UserIdentity user, final Map<String, String> roleRefMap)
{
_delegate=user;
_roleRefMap=roleRefMap;
}
public Subject getSubject()
{
return _delegate.getSubject();
}
public Principal getUserPrincipal()
{
return _delegate.getUserPrincipal();
}
public boolean isUserInRole(String role)
{
String link=_roleRefMap.get(role);
return _delegate.isUserInRole(link==null?role:link);
}
}
}

View File

@ -28,36 +28,12 @@ public interface IdentityService
{
final static String[] NO_ROLES = new String[]{};
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/** A scoped UserIdentity.
*
* An interface used to ob
*
*/
interface Scoped
{
UserIdentity getScopedUserIdentity();
}
/* ------------------------------------------------------------ */
/**
* Scope the {@link UserIdentity} to a {@link UserIdentity.Scope}.
* @see IdentityService#descope(UserIdentity)
* @param user The current user.
* @param context The new scope.
* @return A scoped {@link UserIdentity}.
* @param user The current user or null for no user associated.
*/
UserIdentity scope(UserIdentity user, UserIdentity.Scope context);
/* ------------------------------------------------------------ */
/**
* Disassociate the current UserIdentity and reinstate the
* previousUser identity.
* @param scoped UserIdentity returned from previous associate call
*/
void descope(UserIdentity scoped);
void associate(UserIdentity user);
/* ------------------------------------------------------------ */
/**

View File

@ -1,259 +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;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Locale;
import javax.security.auth.Subject;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.Log;
/**
* @version $Rev: 4793 $ $Date: 2009-03-19 00:00:01 +0100 (Thu, 19 Mar 2009) $
*/
public class LazyAuthentication implements Authentication
{
protected final Authenticator _authenticator;
protected final ServletRequest _request;
protected final ServletResponse _response;
private Authentication _delegate;
public LazyAuthentication(Authenticator authenticator, ServletRequest request, ServletResponse response)
{
if (authenticator == null)
throw new NullPointerException("No Authenticator");
this._authenticator = authenticator;
this._request = request;
this._response = response;
}
private Authentication getDelegate()
{
if (_delegate == null)
{
try
{
_delegate = _authenticator.validateRequest(_request,__nullResponse,false);
if (_delegate.isSend())
_delegate=Authentication.NOT_CHECKED;
}
catch (ServerAuthException e)
{
Log.debug(e);
_delegate = Authentication.FAILED;
}
}
return _delegate;
}
public boolean isSuccess()
{
return getDelegate().isSuccess();
}
public boolean isSend()
{
return false;
}
public UserIdentity getUserIdentity()
{
return getDelegate().getUserIdentity();
}
public String getAuthMethod()
{
return getDelegate().getAuthMethod();
}
public void logout()
{
if (_delegate != null)
_delegate.logout();
}
public String toString()
{
return "{Lazy," + _delegate + "}";
}
private static HttpServletResponse __nullResponse = new HttpServletResponse()
{
public void addCookie(Cookie cookie)
{
}
public void addDateHeader(String name, long date)
{
}
public void addHeader(String name, String value)
{
}
public void addIntHeader(String name, int value)
{
}
public boolean containsHeader(String name)
{
return false;
}
public String encodeRedirectURL(String url)
{
return null;
}
public String encodeRedirectUrl(String url)
{
return null;
}
public String encodeURL(String url)
{
return null;
}
public String encodeUrl(String url)
{
return null;
}
public void sendError(int sc) throws IOException
{
}
public void sendError(int sc, String msg) throws IOException
{
}
public void sendRedirect(String location) throws IOException
{
}
public void setDateHeader(String name, long date)
{
}
public void setHeader(String name, String value)
{
}
public void setIntHeader(String name, int value)
{
}
public void setStatus(int sc)
{
}
public void setStatus(int sc, String sm)
{
}
public void flushBuffer() throws IOException
{
}
public int getBufferSize()
{
return 1024;
}
public String getCharacterEncoding()
{
return null;
}
public String getContentType()
{
return null;
}
public Locale getLocale()
{
return null;
}
public ServletOutputStream getOutputStream() throws IOException
{
return __nullOut;
}
public PrintWriter getWriter() throws IOException
{
return IO.getNullPrintWriter();
}
public boolean isCommitted()
{
return true;
}
public void reset()
{
}
public void resetBuffer()
{
}
public void setBufferSize(int size)
{
}
public void setCharacterEncoding(String charset)
{
}
public void setContentLength(int len)
{
}
public void setContentType(String type)
{
}
public void setLocale(Locale loc)
{
}
};
private static ServletOutputStream __nullOut = new ServletOutputStream()
{
public void write(int b) throws IOException
{
}
public void print(String s) throws IOException
{
}
public void println(String s) throws IOException
{
}
};
}

View File

@ -24,6 +24,8 @@ 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.server.Authentication;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.Request;
@ -407,32 +409,60 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
boolean isAuthMandatory = isAuthMandatory(base_request, base_response, constraintInfo);
// check authentication
UserIdentity old_user_identity=base_request.getUserIdentity();
try
{
final Authenticator authenticator = _authenticator;
Authentication authentication = authenticator.validateRequest(request, response, isAuthMandatory);
final Authentication authentication = authenticator.validateRequest(request, response, isAuthMandatory);
if (authentication!=null && !authentication.isSend())
if (authentication instanceof Authentication.ResponseSent)
{
final UserIdentity user_identity=authentication.getUserIdentity();
base_request.setAuthType(authentication.getAuthMethod());
base_request.setUserIdentity(user_identity);
base_request.setHandled(true);
}
else if (authentication instanceof Authentication.User)
{
Authentication.User userAuth = (Authentication.User)authentication;
base_request.setAuthentication(authentication);
_identityService.associate(userAuth.getUserIdentity());
if (isAuthMandatory && !checkWebResourcePermissions(pathInContext, base_request, base_response, constraintInfo, user_identity))
boolean authorized=checkWebResourcePermissions(pathInContext, base_request, base_response, constraintInfo, userAuth.getUserIdentity());
if (isAuthMandatory && !authorized)
{
response.sendError(Response.SC_FORBIDDEN, "User not in required role");
response.sendError(Response.SC_FORBIDDEN, "!role");
base_request.setHandled(true);
return;
}
handler.handle(pathInContext, request, response);
authenticator.secureResponse(request, response, isAuthMandatory, userAuth);
}
else if (authentication instanceof Authentication.Deferred)
{
DeferredAuthentication lazy= (DeferredAuthentication)authentication;
lazy.setIdentityService(_identityService);
base_request.setAuthentication(authentication);
authenticator.secureResponse(request, response, isAuthMandatory, authentication);
try
{
handler.handle(pathInContext, request, response);
}
finally
{
lazy.setIdentityService(null);
}
Authentication auth=base_request.getAuthentication();
if (auth instanceof Authentication.User)
{
Authentication.User userAuth = (Authentication.User)auth;
authenticator.secureResponse(request, response, isAuthMandatory, userAuth);
}
else
authenticator.secureResponse(request, response, isAuthMandatory, null);
}
else
{
base_request.setHandled(true);
base_request.setAuthentication(authentication);
handler.handle(pathInContext, request, response);
authenticator.secureResponse(request, response, isAuthMandatory, null);
}
}
catch (ServerAuthException e)
@ -443,7 +473,7 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
}
finally
{
base_request.setUserIdentity(old_user_identity);
_identityService.associate(null);
}
}
else

View File

@ -15,18 +15,20 @@ 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;
import org.eclipse.jetty.server.UserIdentity.Scope;
/**
* @version $Rev: 4793 $ $Date: 2009-03-19 00:00:01 +0100 (Thu, 19 Mar 2009) $
*/
public class DefaultAuthentication implements Authentication
public class UserAuthentication implements Authentication.User
{
private final Authenticator _authenticator;
private final UserIdentity _userIdentity;
public DefaultAuthentication(Authenticator authenticator, UserIdentity userIdentity)
public UserAuthentication(Authenticator authenticator, UserIdentity userIdentity)
{
_authenticator = authenticator;
_userIdentity=userIdentity;
@ -42,14 +44,12 @@ public class DefaultAuthentication implements Authentication
return _userIdentity;
}
public boolean isSuccess()
public boolean isUserInRole(Scope scope, String role)
{
return true;
}
if (scope!=null && scope.getRoleRefMap()!=null)
role=scope.getRoleRefMap().get(role);
public boolean isSend()
{
return false;
return _userIdentity.isUserInRole(role);
}
public void logout()
@ -75,17 +75,4 @@ public class DefaultAuthentication implements Authentication
{
return "{Auth,"+getAuthMethod()+","+_userIdentity+"}";
}
public static class Send extends DefaultAuthentication
{
public Send(Authenticator authenticator, UserIdentity userIdentity)
{
super(authenticator,userIdentity);
}
public boolean isSend()
{
return true;
}
}
}

View File

@ -23,11 +23,12 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.http.security.B64Code;
import org.eclipse.jetty.http.security.Constraint;
import org.eclipse.jetty.security.Authentication;
import org.eclipse.jetty.security.DefaultAuthentication;
import org.eclipse.jetty.security.UserAuthentication;
import org.eclipse.jetty.security.DefaultUserIdentity;
import org.eclipse.jetty.security.ServerAuthException;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.server.Authentication.User;
import org.eclipse.jetty.util.StringUtil;
/**
@ -74,15 +75,16 @@ public class BasicAuthenticator extends LoginAuthenticator
UserIdentity user = _loginService.login(username,password);
if (user!=null)
return new DefaultAuthentication(this,user);
return new UserAuthentication(this,user);
}
if (!mandatory)
return Authentication.NOT_CHECKED;
response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "basic realm=\"" + _loginService.getName() + '"');
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return Authentication.CHALLENGE;
if (mandatory)
{
response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "basic realm=\"" + _loginService.getName() + '"');
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return Authentication.CHALLENGE;
}
return credentials==null?Authentication.NOT_CHECKED:Authentication.UNAUTHENTICATED;
}
catch (IOException e)
{
@ -91,7 +93,7 @@ public class BasicAuthenticator extends LoginAuthenticator
}
// TODO most likely validatedUser is not needed here ??
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication validatedUser) throws ServerAuthException
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, User validatedUser) throws ServerAuthException
{
return true;
}

View File

@ -15,6 +15,7 @@ package org.eclipse.jetty.security.authentication;
import java.io.IOException;
import java.security.Principal;
import java.security.cert.X509Certificate;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
@ -23,10 +24,11 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.security.B64Code;
import org.eclipse.jetty.http.security.Constraint;
import org.eclipse.jetty.security.Authentication;
import org.eclipse.jetty.security.DefaultAuthentication;
import org.eclipse.jetty.security.UserAuthentication;
import org.eclipse.jetty.security.ServerAuthException;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.server.Authentication.User;
/**
* @version $Rev: 4793 $ $Date: 2009-03-19 00:00:01 +0100 (Thu, 19 Mar 2009) $
@ -55,32 +57,37 @@ public class ClientCertAuthenticator extends LoginAuthenticator
{
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
java.security.cert.X509Certificate[] certs = (java.security.cert.X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
try
{
// Need certificates.
if (certs == null || certs.length == 0 || certs[0] == null)
if (certs != null && certs.length > 0)
{
response.sendError(HttpServletResponse.SC_FORBIDDEN,"!certificate");
return Authentication.FAILED;
for (X509Certificate cert: certs)
{
if (cert==null)
continue;
Principal principal = cert.getSubjectDN();
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);
if (user!=null)
return new UserAuthentication(this,user);
}
}
Principal principal = certs[0].getSubjectDN();
if (principal == null) principal = certs[0].getIssuerDN();
final String username = principal == null ? "clientcert" : principal.getName();
if (mandatory)
{
response.sendError(HttpServletResponse.SC_FORBIDDEN);
return Authentication.FAILURE;
}
// TODO no idea if this is correct
final char[] credential = B64Code.encode(certs[0].getSignature());
UserIdentity user = _loginService.login(username,credential);
if (user!=null)
return new DefaultAuthentication(this,user);
if (!mandatory)
return Authentication.NOT_CHECKED;
response.sendError(HttpServletResponse.SC_FORBIDDEN);
return Authentication.FAILED;
return certs==null?Authentication.NOT_CHECKED:Authentication.UNAUTHENTICATED;
}
catch (IOException e)
{
@ -88,7 +95,7 @@ public class ClientCertAuthenticator extends LoginAuthenticator
}
}
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication validatedUser) throws ServerAuthException
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, User validatedUser) throws ServerAuthException
{
return true;
}

View File

@ -0,0 +1,325 @@
// ========================================================================
// 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 java.io.IOException;
import java.io.PrintWriter;
import java.util.Locale;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
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 DeferredAuthenticator(Authenticator delegate)
{
super(delegate);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.security.Authenticator#validateRequest(ServletRequest,
* ServletResponse, boolean)
*/
public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException
{
if (!mandatory)
{
return new DeferredAuthentication(_delegate,request,response);
}
return _delegate.validateRequest(request,response,mandatory);
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
public static class DeferredAuthentication implements Authentication.Deferred
{
protected final Authenticator _authenticator;
protected final ServletRequest _request;
protected final ServletResponse _response;
private Authentication _delegate;
private IdentityService _identityService;
public DeferredAuthentication(Authenticator authenticator, ServletRequest request, ServletResponse response)
{
if (authenticator == null)
throw new NullPointerException("No Authenticator");
this._authenticator = authenticator;
this._request = request;
this._response = response;
}
/* ------------------------------------------------------------ */
/** 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()
{
try
{
Authentication authentication = _authenticator.validateRequest(_request,__nullResponse,false);
if (authentication!=null && (authentication instanceof Authentication.User) && !(authentication instanceof Authentication.ResponseSent))
{
if (_identityService!=null)
_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)
_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
}
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
private static HttpServletResponse __nullResponse = new HttpServletResponse()
{
public void addCookie(Cookie cookie)
{
}
public void addDateHeader(String name, long date)
{
}
public void addHeader(String name, String value)
{
}
public void addIntHeader(String name, int value)
{
}
public boolean containsHeader(String name)
{
return false;
}
public String encodeRedirectURL(String url)
{
return null;
}
public String encodeRedirectUrl(String url)
{
return null;
}
public String encodeURL(String url)
{
return null;
}
public String encodeUrl(String url)
{
return null;
}
public void sendError(int sc) throws IOException
{
}
public void sendError(int sc, String msg) throws IOException
{
}
public void sendRedirect(String location) throws IOException
{
}
public void setDateHeader(String name, long date)
{
}
public void setHeader(String name, String value)
{
}
public void setIntHeader(String name, int value)
{
}
public void setStatus(int sc)
{
}
public void setStatus(int sc, String sm)
{
}
public void flushBuffer() throws IOException
{
}
public int getBufferSize()
{
return 1024;
}
public String getCharacterEncoding()
{
return null;
}
public String getContentType()
{
return null;
}
public Locale getLocale()
{
return null;
}
public ServletOutputStream getOutputStream() throws IOException
{
return __nullOut;
}
public PrintWriter getWriter() throws IOException
{
return IO.getNullPrintWriter();
}
public boolean isCommitted()
{
return true;
}
public void reset()
{
}
public void resetBuffer()
{
}
public void setBufferSize(int size)
{
}
public void setCharacterEncoding(String charset)
{
}
public void setContentLength(int len)
{
}
public void setContentType(String type)
{
}
public void setLocale(Locale loc)
{
}
};
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
private static ServletOutputStream __nullOut = new ServletOutputStream()
{
public void write(int b) throws IOException
{
}
public void print(String s) throws IOException
{
}
public void println(String s) throws IOException
{
}
};
}

View File

@ -16,9 +16,10 @@ package org.eclipse.jetty.security.authentication;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.eclipse.jetty.security.Authentication;
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
{
@ -49,7 +50,7 @@ public class DelegateAuthenticator implements Authenticator
return _delegate.validateRequest(request, response, manditory);
}
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication validatedUser) throws ServerAuthException
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, User validatedUser) throws ServerAuthException
{
return _delegate.secureResponse(req,res, mandatory, validatedUser);
}

View File

@ -25,12 +25,13 @@ import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.http.security.B64Code;
import org.eclipse.jetty.http.security.Constraint;
import org.eclipse.jetty.http.security.Credential;
import org.eclipse.jetty.security.Authentication;
import org.eclipse.jetty.security.DefaultAuthentication;
import org.eclipse.jetty.security.UserAuthentication;
import org.eclipse.jetty.security.DefaultUserIdentity;
import org.eclipse.jetty.security.ServerAuthException;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.server.Authentication.User;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil;
@ -55,7 +56,7 @@ public class DigestAuthenticator extends LoginAuthenticator
return Constraint.__DIGEST_AUTH;
}
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication validatedUser) throws ServerAuthException
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, User validatedUser) throws ServerAuthException
{
return true;
}
@ -123,30 +124,31 @@ public class DigestAuthenticator extends LoginAuthenticator
{
UserIdentity user = _loginService.login(digest.username,digest);
if (user!=null)
{
return new DefaultAuthentication(this,user);
}
return new UserAuthentication(this,user);
}
else if (n == 0) stale = true;
else if (n == 0)
stale = true;
}
if (!mandatory)
return Authentication.NOT_CHECKED;
if (mandatory)
{
String domain = request.getContextPath();
if (domain == null)
domain = "/";
response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "Digest realm=\"" + _loginService.getName()
+ "\", domain=\""
+ domain
+ "\", nonce=\""
+ newNonce((Request)request)
+ "\", algorithm=MD5, qop=\"auth\""
+ (_useStale ? (" stale=" + stale) : ""));
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
String domain = request.getContextPath();
if (domain == null)
domain = "/";
response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "Digest realm=\"" + _loginService.getName()
+ "\", domain=\""
+ domain
+ "\", nonce=\""
+ newNonce((Request)request)
+ "\", algorithm=MD5, qop=\"auth\""
+ (_useStale ? (" stale=" + stale) : ""));
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return Authentication.CHALLENGE;
}
return Authentication.CHALLENGE;
return credentials==null?Authentication.NOT_CHECKED:Authentication.UNAUTHENTICATED;
}
catch (IOException e)
{

View File

@ -32,10 +32,12 @@ import javax.servlet.http.HttpSession;
import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.http.security.Constraint;
import org.eclipse.jetty.security.Authentication;
import org.eclipse.jetty.security.DefaultAuthentication;
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;
import org.eclipse.jetty.server.Authentication.User;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log;
@ -187,7 +189,7 @@ public class FormAuthenticator extends LoginAuthenticator
}
response.setContentLength(0);
response.sendRedirect(response.encodeRedirectURL(nuri));
return new DefaultAuthentication.Send(this,user);
return new FormAuthentication(this,user);
}
// not authenticated
@ -210,41 +212,40 @@ public class FormAuthenticator extends LoginAuthenticator
response.sendRedirect(URIUtil.addPaths(request.getContextPath(),_formErrorPage));
}
return Authentication.FAILED;
return Authentication.FAILURE;
}
// Check if the session is already authenticated.
// Don't authenticate authform or errorpage
if (!mandatory)
return Authentication.NOT_CHECKED;
// redirect to login page
if (request.getQueryString() != null)
uri += "?" + request.getQueryString();
synchronized (session)
if (mandatory)
{
if (session.getAttribute(__J_URI)==null)
session.setAttribute(__J_URI, request.getScheme() + "://"
+ request.getServerName()
+ ":"
+ request.getServerPort()
+ URIUtil.addPaths(request.getContextPath(), uri));
// redirect to login page
if (request.getQueryString() != null)
uri += "?" + request.getQueryString();
synchronized (session)
{
if (session.getAttribute(__J_URI)==null)
session.setAttribute(__J_URI, request.getScheme() + "://"
+ request.getServerName()
+ ":"
+ request.getServerPort()
+ URIUtil.addPaths(request.getContextPath(), uri));
}
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.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.CHALLENGE;
return Authentication.UNAUTHENTICATED;
}
catch (IOException e)
{
@ -263,7 +264,7 @@ public class FormAuthenticator extends LoginAuthenticator
}
/* ------------------------------------------------------------ */
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication validatedUser) throws ServerAuthException
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, User validatedUser) throws ServerAuthException
{
return true;
}
@ -357,4 +358,17 @@ public class FormAuthenticator extends LoginAuthenticator
return true;
}
}
public static class FormAuthentication extends UserAuthentication implements Authentication.ResponseSent
{
public FormAuthentication(Authenticator authenticator, UserIdentity userIdentity)
{
super(authenticator,userIdentity);
}
public String toString()
{
return "Form"+super.toString();
}
}
}

View File

@ -1,45 +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.Authentication;
import org.eclipse.jetty.security.Authenticator;
import org.eclipse.jetty.security.LazyAuthentication;
import org.eclipse.jetty.security.ServerAuthException;
/**
* @version $Rev: 4793 $ $Date: 2009-03-19 00:00:01 +0100 (Thu, 19 Mar 2009) $
*/
public class LazyAuthenticator extends DelegateAuthenticator
{
public LazyAuthenticator(Authenticator delegate)
{
super(delegate);
}
/**
* @see org.eclipse.jetty.security.Authenticator#validateRequest(ServletRequest, ServletResponse, boolean)
*/
public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException
{
if (!mandatory)
{
return new LazyAuthentication(_delegate,request,response);
}
return _delegate.validateRequest(request, response, mandatory);
}
}

View File

@ -22,10 +22,10 @@ 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.UserAuthentication;
import org.eclipse.jetty.security.ServerAuthException;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.UserIdentity;
/**
@ -52,18 +52,18 @@ public class SessionCachingAuthenticator extends DelegateAuthenticator
return authentication;
authentication = _delegate.validateRequest(request, response, mandatory);
if (authentication!=null && authentication.isSuccess())
if (authentication instanceof Authentication.User)
{
Authentication cached=new FormAuthentication(_delegate,authentication.getUserIdentity());
Authentication cached=new SessionAuthentication(_delegate,((Authentication.User)authentication).getUserIdentity());
session.setAttribute(__J_AUTHENTICATED, cached);
}
return authentication;
}
protected class FormAuthentication extends DefaultAuthentication implements HttpSessionAttributeListener
protected class SessionAuthentication extends UserAuthentication implements HttpSessionAttributeListener
{
public FormAuthentication(Authenticator authenticator, UserIdentity userIdentity)
public SessionAuthentication(Authenticator authenticator, UserIdentity userIdentity)
{
super(authenticator,userIdentity);
}
@ -82,5 +82,10 @@ public class SessionCachingAuthenticator extends DelegateAuthenticator
logout();
}
public String toString()
{
return "Session"+super.toString();
}
}
}

View File

@ -18,10 +18,10 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.security.Authentication;
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

View File

@ -29,6 +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;
@ -218,7 +219,7 @@ public class ConstraintTest extends TestCase
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 403 "));
assertTrue(response.indexOf("User not in required role") > 0);
assertTrue(response.indexOf("!role") > 0);
_connector.reopen();
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
@ -226,7 +227,6 @@ public class ConstraintTest extends TestCase
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
_connector.reopen();
response = _connector.getResponses("GET /ctx/admin/relax/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
@ -293,7 +293,7 @@ public class ConstraintTest extends TestCase
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 403"));
assertTrue(response.indexOf("User not in required role") > 0);
assertTrue(response.indexOf("!role") > 0);
}
@ -355,7 +355,7 @@ public class ConstraintTest extends TestCase
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 403 "));
assertTrue(response.indexOf("User not in required role") > 0);
assertTrue(response.indexOf("!role") > 0);
_connector.reopen();
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
@ -424,14 +424,14 @@ public class ConstraintTest extends TestCase
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 403"));
assertTrue(response.indexOf("User not in required role") > 0);
assertTrue(response.indexOf("!role") > 0);
_connector.reopen();
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 403"));
assertTrue(response.indexOf("User not in required role") > 0);
assertTrue(response.indexOf("!role") > 0);
@ -465,7 +465,7 @@ public class ConstraintTest extends TestCase
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 403"));
assertTrue(response.indexOf("User not in required role") > 0);
assertTrue(response.indexOf("!role") > 0);
@ -537,6 +537,37 @@ public class ConstraintTest extends TestCase
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
}
public void testDeferredBasic()
throws Exception
{
_security.setAuthenticator(new DeferredAuthenticator(new BasicAuthenticator()));
_security.setStrict(false);
_server.start();
String response;
_connector.reopen();
response = _connector.getResponses("GET /ctx/noauth/info HTTP/1.0\r\n"+
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertTrue(response.indexOf("user=null") > 0);
_connector.reopen();
response = _connector.getResponses("GET /ctx/noauth/info HTTP/1.0\r\n"+
"Authorization: " + B64Code.encode("admin:wrong") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertTrue(response.indexOf("user=null") > 0);
_connector.reopen();
response = _connector.getResponses("GET /ctx/noauth/info HTTP/1.0\r\n"+
"Authorization: " + B64Code.encode("admin:password") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertTrue(response.indexOf("user=admin") > 0);
}
class RequestHandler extends AbstractHandler
{
public void handle(String target, HttpServletRequest request, HttpServletResponse response ) throws IOException, ServletException
@ -548,6 +579,8 @@ public class ConstraintTest extends TestCase
response.setStatus(200);
response.setContentType("text/plain; charset=UTF-8");
response.getWriter().println("URI="+request.getRequestURI());
String user = request.getRemoteUser();
response.getWriter().println("user="+user);
}
else
response.sendError(500);
@ -563,30 +596,29 @@ public class ConstraintTest extends TestCase
@Override
public void handle(String target, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
UserIdentity old = ((Request) request).getUserIdentity();
UserIdentity scoped = _security.getIdentityService().scope(old,
new UserIdentity.Scope()
{
UserIdentity.Scope old = ((Request) request).getUserIdentityScope();
public String getContextPath()
{
return "/";
}
UserIdentity.Scope scope = new UserIdentity.Scope()
{
public String getContextPath()
{
return "/";
}
public String getName()
{
return "someServlet";
}
public String getName()
{
return "someServlet";
}
public Map<String, String> getRoleRefMap()
{
Map<String, String> map = new HashMap<String, String>();
map.put("untranslated", "user");
return map;
}
public Map<String, String> getRoleRefMap()
{
Map<String, String> map = new HashMap<String, String>();
map.put("untranslated", "user");
return map;
}
};
});
((Request)request).setUserIdentity(scoped);
((Request)request).setUserIdentityScope(scope);
try
{
@ -594,8 +626,7 @@ public class ConstraintTest extends TestCase
}
finally
{
_security.getIdentityService().descope(scoped);
((Request)request).setUserIdentity(old);
((Request)request).setUserIdentityScope(old);
}
}
}

View File

@ -0,0 +1,118 @@
package org.eclipse.jetty.server;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/* ------------------------------------------------------------ */
/** The Authentication state of a request.
* <p>
* The Authentication state can be one of several sub-types that
* reflects where the request is in the many different authentication
* cycles. Authentication might not yet be checked or it might be checked
* and failed, checked and deferred or succeeded.
*
*/
public interface Authentication
{
/* ------------------------------------------------------------ */
/** A successful Authentication with User information.
*/
public interface User extends Authentication
{
String getAuthMethod();
UserIdentity getUserIdentity();
boolean isUserInRole(UserIdentity.Scope scope,String role);
void logout();
}
/* ------------------------------------------------------------ */
/** A deferred authentication with methods to progress
* the authentication process.
*/
public interface Deferred extends Authentication
{
/* ------------------------------------------------------------ */
/** Authenticate if possible without sending a challenge.
* This is used to check credentials that have been sent for
* non-manditory authentication.
* @return The new Authentication state.
*/
Authentication authenticate();
/* ------------------------------------------------------------ */
/** Authenticate and possibly send a challenge.
* This is used to initiate authentication for previously
* non-manditory authentication.
* @return The new Authentication state.
*/
Authentication authenticate(ServletRequest request,ServletResponse response);
/* ------------------------------------------------------------ */
/** Login with the LOGIN authenticator
* @param username
* @param password
* @return The new Authentication state
*/
Authentication login(String username,String password);
}
/* ------------------------------------------------------------ */
/** Authentication Response sent state.
* Responses are sent by authenticators either to issue an
* authentication challenge or on successful authentication in
* order to redirect the user to the original URL.
*/
public interface ResponseSent extends Authentication
{
}
/* ------------------------------------------------------------ */
/** An Authentication Challenge has been sent.
*/
public interface Challenge extends ResponseSent
{
}
/* ------------------------------------------------------------ */
/** An Authentication Failure has been sent.
*/
public interface Failure extends ResponseSent
{
}
/* ------------------------------------------------------------ */
/** Unauthenticated state.
* <p>
* This convenience instance is for non mandatory authentication where credentials
* have been presented and checked, but failed authentication.
*/
public final static Authentication UNAUTHENTICATED = new Authentication(){public String toString(){return "UNAUTHENTICATED";}};
/* ------------------------------------------------------------ */
/** Authentication not checked
* <p>
* This convenience instance us for non mandatory authentication when no
* credentials are present to be checked.
*/
public final static Authentication NOT_CHECKED = new Authentication(){public String toString(){return "NOT CHECKED";}};
/* ------------------------------------------------------------ */
/** Authentication challenge sent.
* <p>
* This convenience instance is for when an authentication challenge has been sent.
*/
public final static Authentication CHALLENGE = new Authentication.Challenge(){public String toString(){return "CHALLENGE";}};
/* ------------------------------------------------------------ */
/** Authentication failure sent.
* <p>
* This convenience instance is for when an authentication failure has been sent.
*/
public final static Authentication FAILURE = new Authentication.Failure(){public String toString(){return "FAILURE";}};
}

View File

@ -272,8 +272,12 @@ public class NCSARequestLog extends AbstractLifeCycle implements RequestLog
buf.append(addr);
buf.append(" - ");
String user = request.getRemoteUser();
buf.append((user == null)?" - ":user);
Authentication authentication=request.getAuthentication();
if (authentication instanceof Authentication.User)
buf.append(((Authentication.User)authentication).getUserIdentity().getUserPrincipal().getName());
else
buf.append(" - ");
buf.append(" [");
if (_logDateCache != null)
buf.append(_logDateCache.format(request.getTimeStamp()));

View File

@ -103,8 +103,6 @@ import org.eclipse.jetty.util.log.Log;
* to avoid reparsing headers and cookies that are likely to be the same for
* requests from the same connection.
*
*
*
*/
public class Request implements HttpServletRequest
{
@ -123,7 +121,7 @@ public class Request implements HttpServletRequest
protected final AsyncRequest _async = new AsyncRequest();
private boolean _asyncSupported=true;
private Attributes _attributes;
private String _authType;
private Authentication _authentication;
private MultiMap<String> _baseParameters;
private String _characterEncoding;
protected HttpConnection _connection;
@ -155,17 +153,16 @@ public class Request implements HttpServletRequest
private String _requestURI;
private Map<Object,HttpSession> _savedNewSessions;
private String _scheme=URIUtil.HTTP;
private UserIdentity.Scope _scope;
private String _serverName;
private String _servletName;
private String _servletPath;
private HttpSession _session;
private SessionManager _sessionManager;
private long _timeStamp;
private Buffer _timeStampBuffer;
private HttpURI _uri;
private UserIdentity _userIdentity = UserIdentity.UNAUTHENTICATED_IDENTITY;
/* ------------------------------------------------------------ */
public Request()
{
@ -347,13 +344,27 @@ public class Request implements HttpServletRequest
return _attributes;
}
/* ------------------------------------------------------------ */
/** Get the authentication.
* @return the authentication
*/
public Authentication getAuthentication()
{
return _authentication;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#getAuthType()
*/
public String getAuthType()
{
return _authType;
if (_authentication instanceof Authentication.Deferred)
_authentication = ((Authentication.Deferred)_authentication).authenticate();
if (_authentication instanceof Authentication.User)
return ((Authentication.User)_authentication).getAuthMethod();
return null;
}
/* ------------------------------------------------------------ */
@ -1062,7 +1073,9 @@ public class Request implements HttpServletRequest
*/
public String getServletName()
{
return _servletName;
if (_scope!=null)
return _scope.getName();
return null;
}
/* ------------------------------------------------------------ */
@ -1125,6 +1138,7 @@ public class Request implements HttpServletRequest
return _session;
}
/* ------------------------------------------------------------ */
/**
* @return Returns the sessionManager.
@ -1134,7 +1148,6 @@ public class Request implements HttpServletRequest
return _sessionManager;
}
/* ------------------------------------------------------------ */
/**
* Get Request TimeStamp
@ -1170,7 +1183,18 @@ public class Request implements HttpServletRequest
public UserIdentity getUserIdentity()
{
return _userIdentity;
if (_authentication instanceof Authentication.Deferred)
_authentication = ((Authentication.Deferred)_authentication).authenticate();
if (_authentication instanceof Authentication.User)
return ((Authentication.User)_authentication).getUserIdentity();
return null;
}
/* ------------------------------------------------------------ */
public UserIdentity.Scope getUserIdentityScope()
{
return _scope;
}
/* ------------------------------------------------------------ */
@ -1179,7 +1203,15 @@ public class Request implements HttpServletRequest
*/
public Principal getUserPrincipal()
{
return _userIdentity.getUserPrincipal();
if (_authentication instanceof Authentication.Deferred)
_authentication = ((Authentication.Deferred)_authentication).authenticate();
if (_authentication instanceof Authentication.User)
{
UserIdentity user = ((Authentication.User)_authentication).getUserIdentity();
return user.getUserPrincipal();
}
return null;
}
/* ------------------------------------------------------------ */
@ -1255,7 +1287,12 @@ public class Request implements HttpServletRequest
*/
public boolean isUserInRole(String role)
{
return _userIdentity!=null && _userIdentity.isUserInRole(role);
if (_authentication instanceof Authentication.Deferred)
_authentication = ((Authentication.Deferred)_authentication).authenticate();
if (_authentication instanceof Authentication.User)
return ((Authentication.User)_authentication).isUserInRole(_scope,role);
return false;
}
/* ------------------------------------------------------------ */
@ -1269,7 +1306,7 @@ public class Request implements HttpServletRequest
/* ------------------------------------------------------------ */
protected void recycle()
{
_authType=null;
_authentication=Authentication.NOT_CHECKED;
_async.recycle();
_asyncSupported=true;
_handled=false;
@ -1290,12 +1327,12 @@ public class Request implements HttpServletRequest
_requestedSessionIdFromCookie=false;
_session=null;
_requestURI=null;
_scope=null;
_scheme=URIUtil.HTTP;
_servletPath=null;
_timeStamp=0;
_timeStampBuffer=null;
_uri=null;
_userIdentity=UserIdentity.UNAUTHENTICATED_IDENTITY;
if (_baseParameters!=null)
_baseParameters.clear();
_parameters=null;
@ -1344,7 +1381,6 @@ public class Request implements HttpServletRequest
{
_requestAttributeListeners= LazyList.remove(_requestAttributeListeners, listener);
}
/* ------------------------------------------------------------ */
public void saveNewSession(Object key,HttpSession session)
{
@ -1352,17 +1388,18 @@ public class Request implements HttpServletRequest
_savedNewSessions=new HashMap<Object,HttpSession>();
_savedNewSessions.put(key,session);
}
/* ------------------------------------------------------------ */
public void setAsyncSupported(boolean supported)
{
_asyncSupported=supported;
}
/* ------------------------------------------------------------ */
public void setAsyncTimeout(long timeout)
{
_async.setAsyncTimeout(timeout);
}
/* ------------------------------------------------------------ */
/*
* Set a request attribute.
@ -1446,12 +1483,16 @@ public class Request implements HttpServletRequest
}
/* ------------------------------------------------------------ */
public void setAuthType(String authType)
{
_authType=authType;
}
/* ------------------------------------------------------------ */
/** Set the authentication.
* @param authentication the authentication to set
*/
public void setAuthentication(Authentication authentication)
{
_authentication = authentication;
}
/* ------------------------------------------------------------ */
/*
@ -1629,6 +1670,7 @@ public class Request implements HttpServletRequest
{
_requestedSessionId = requestedSessionId;
}
/* ------------------------------------------------------------ */
/**
* @param requestedSessionIdCookie The requestedSessionIdCookie to set.
@ -1637,7 +1679,6 @@ public class Request implements HttpServletRequest
{
_requestedSessionIdFromCookie = requestedSessionIdCookie;
}
/* ------------------------------------------------------------ */
/**
* @param requestListeners {@link LazyList} of {@link ServletRequestListener}s
@ -1683,15 +1724,6 @@ public class Request implements HttpServletRequest
_port = port;
}
/* ------------------------------------------------------------ */
/**
* @param name The servletName to set.
*/
public void setServletName(String name)
{
_servletName = name;
}
/* ------------------------------------------------------------ */
/**
* @param servletPath The servletPath to set.
@ -1734,11 +1766,10 @@ public class Request implements HttpServletRequest
_uri = uri;
}
public void setUserIdentity(UserIdentity userIdentity)
/* ------------------------------------------------------------ */
public void setUserIdentityScope(UserIdentity.Scope scope)
{
if (userIdentity == null)
throw new NullPointerException("No UserIdentity");
_userIdentity = userIdentity;
_scope=scope;
}
/* ------------------------------------------------------------ */

View File

@ -322,7 +322,7 @@ public class ServletHandler extends AbstractHandler
ServletRequestEvent request_event=null;
ServletHolder servlet_holder=null;
FilterChain chain=null;
UserIdentity old_identity=null;
UserIdentity.Scope old_scope=null;
// find the servlet
if (target.startsWith("/"))
@ -382,13 +382,8 @@ public class ServletHandler extends AbstractHandler
}
else
{
base_request.setServletName(servlet_holder.getName());
if (_identityService!=null)
{
old_identity=base_request.getUserIdentity();
scoped_identity=_identityService.scope(old_identity,servlet_holder);
base_request.setUserIdentity(scoped_identity);
}
old_scope=base_request.getUserIdentityScope();
base_request.setUserIdentityScope(servlet_holder);
// Handle context listeners
request_listeners = base_request.takeRequestListeners();
@ -517,12 +512,8 @@ public class ServletHandler extends AbstractHandler
}
}
if (scoped_identity!=null)
{
_identityService.descope(scoped_identity);
base_request.setUserIdentity(old_identity);
}
base_request.setServletName(old_servlet_name);
if (old_scope!=null)
base_request.setUserIdentityScope(old_scope);
if (!(DispatcherType.INCLUDE.equals(type)))
{