From 3a129bb90f6e025d1905aeaa79a8972282105690 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Wed, 15 Apr 2009 12:39:05 +0000 Subject: [PATCH] reworked the Authentication to better support lazyness and to move towards servlet 3.0 login and logout git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@151 7e9141cc-0065-0410-87d8-b60c137991c4 --- VERSION.txt | 2 + .../eclipse/jetty/embedded/ManyContexts.java | 1 + .../jetty/embedded/ManyServletContexts.java | 14 +- .../jetty/http/security/Credential.java | 6 +- .../eclipse/jetty/http/security/Password.java | 9 +- jetty-jaspi/pom.xml | 27 ++- .../security/jaspi/JaspiAuthenticator.java | 37 ++- .../jetty/security/Authentication.java | 106 ++++++--- .../eclipse/jetty/security/Authenticator.java | 2 +- .../security/ConstraintSecurityHandler.java | 10 +- .../jetty/security/DefaultAuthentication.java | 31 ++- .../security/DefaultIdentityService.java | 13 +- .../jetty/security/DefaultUserIdentity.java | 5 - .../jetty/security/HashLoginService.java | 2 +- .../jetty/security/IdentityService.java | 15 +- .../jetty/security/LazyAuthentication.java | 218 ++++++++++++++++-- .../jetty/security/MappedLoginService.java | 2 +- .../org/eclipse/jetty/security/RoleInfo.java | 26 ++- .../jetty/security/SecurityHandler.java | 2 +- .../authentication/BasicAuthenticator.java | 20 +- .../ClientCertAuthenticator.java | 19 +- .../authentication/DelegateAuthenticator.java | 2 +- .../authentication/DigestAuthenticator.java | 28 ++- .../authentication/FormAuthenticator.java | 61 ++--- .../authentication/LoginCallbackImpl.java | 3 +- .../SessionCachingAuthenticator.java | 14 +- .../jetty/security/ConstraintTest.java | 9 +- .../java/org/eclipse/jetty/server/Server.java | 2 +- .../eclipse/jetty/server/UserIdentity.java | 19 -- .../jetty/server/handler/AbstractHandler.java | 17 ++ .../handler/AbstractHandlerContainer.java | 43 ++-- .../jetty/server/handler/ContextHandler.java | 1 - .../jetty/server/HttpServerTestBase.java | 4 +- .../eclipse/jetty/servlet/DefaultServlet.java | 17 +- .../eclipse/jetty/servlet/FilterMapping.java | 6 +- .../eclipse/jetty/servlet/ServletHandler.java | 53 ++++- .../eclipse/jetty/servlet/ServletHolder.java | 12 +- .../eclipse/jetty/servlet/ServletMapping.java | 2 +- .../java/org/eclipse/jetty/DemoServer.java | 3 +- .../main/java/org/eclipse/jetty/util/IO.java | 12 +- pom.xml | 1 + 41 files changed, 591 insertions(+), 285 deletions(-) diff --git a/VERSION.txt b/VERSION.txt index c8b8a9f5623..e7999e0e9f9 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -2,6 +2,8 @@ jetty-7.0.0.M1-SNAPSHOT + 271258 FORM Authentication dispatch handling avoids caching + Initial support for LoginService.logout + Removed HTTPConnection specifics from connection dispatching + + JETTY-695 Handler dump + + Reworked lazy authentication jetty-7.0.0.M0 + JETTY-496 Support inetd/xinetd through use of System.inheritedChannel() diff --git a/jetty-embedded-examples/src/main/java/org/eclipse/jetty/embedded/ManyContexts.java b/jetty-embedded-examples/src/main/java/org/eclipse/jetty/embedded/ManyContexts.java index cbb926425a7..d408f185f3f 100644 --- a/jetty-embedded-examples/src/main/java/org/eclipse/jetty/embedded/ManyContexts.java +++ b/jetty-embedded-examples/src/main/java/org/eclipse/jetty/embedded/ManyContexts.java @@ -71,6 +71,7 @@ public class ManyContexts server.setHandler(contexts); server.start(); + System.err.println(server.dump()); server.join(); } diff --git a/jetty-embedded-examples/src/main/java/org/eclipse/jetty/embedded/ManyServletContexts.java b/jetty-embedded-examples/src/main/java/org/eclipse/jetty/embedded/ManyServletContexts.java index 4ee132d2380..621c027da20 100644 --- a/jetty-embedded-examples/src/main/java/org/eclipse/jetty/embedded/ManyServletContexts.java +++ b/jetty-embedded-examples/src/main/java/org/eclipse/jetty/embedded/ManyServletContexts.java @@ -26,6 +26,7 @@ import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.handler.StatisticsHandler; +import org.eclipse.jetty.servlet.DefaultServlet; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; @@ -40,17 +41,16 @@ public class ManyServletContexts server.setHandler(contexts); ServletContextHandler root = new ServletContextHandler(contexts,"/",ServletContextHandler.SESSIONS); - root.addServlet(new ServletHolder(new HelloServlet("Ciao")), "/*"); + root.addServlet(new ServletHolder(new HelloServlet("Hello")), "/"); + root.addServlet(new ServletHolder(new HelloServlet("Ciao")), "/it/*"); + root.addServlet(new ServletHolder(new HelloServlet("Bonjoir")), "/fr/*"); ServletContextHandler other = new ServletContextHandler(contexts,"/other",ServletContextHandler.SESSIONS); - other.addServlet("org.eclipse.jetty.server.example.ManyServletServletContextHandlers$HelloServlet", "/*"); - - StatisticsHandler stats = new StatisticsHandler(); - contexts.addHandler(stats); - ServletContextHandler yetanother =new ServletContextHandler(stats,"/yo",ServletContextHandler.SESSIONS); - yetanother.addServlet(new ServletHolder(new HelloServlet("YO!")), "/*"); + other.addServlet(DefaultServlet.class.getCanonicalName(), "/"); + other.addServlet(new ServletHolder(new HelloServlet("YO!")), "*.yo"); server.start(); + System.err.println(server.dump()); server.join(); } diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/security/Credential.java b/jetty-http/src/main/java/org/eclipse/jetty/http/security/Credential.java index e06664d7db5..a85b8b476ef 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/security/Credential.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/security/Credential.java @@ -13,6 +13,7 @@ package org.eclipse.jetty.http.security; +import java.lang.reflect.Array; import java.security.MessageDigest; import org.eclipse.jetty.util.StringUtil; @@ -82,7 +83,10 @@ public abstract class Credential public boolean check(Object credentials) { - if (!(credentials instanceof String) && !(credentials instanceof Password)) Log.warn("Can't check " + credentials.getClass() + " against CRYPT"); + if (credentials instanceof char[]) + credentials=new String((char[])credentials); + if (!(credentials instanceof String) && !(credentials instanceof Password)) + Log.warn("Can't check " + credentials.getClass() + " against CRYPT"); String passwd = credentials.toString(); return _cooked.equals(UnixCrypt.crypt(passwd, _cooked)); diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/security/Password.java b/jetty-http/src/main/java/org/eclipse/jetty/http/security/Password.java index f96fee71477..fa33b2116ab 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/security/Password.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/security/Password.java @@ -98,9 +98,11 @@ public class Password extends Credential /* ------------------------------------------------------------ */ public boolean equals(Object o) { - if (this == o) return true; + if (this == o) + return true; - if (null == o) return false; + if (null == o) + return false; if (o instanceof Password) { @@ -108,7 +110,8 @@ public class Password extends Credential return p._pw == _pw || (null != _pw && _pw.equals(p._pw)); } - if (o instanceof String) return o.equals(_pw); + if (o instanceof String) + return o.equals(_pw); return false; } diff --git a/jetty-jaspi/pom.xml b/jetty-jaspi/pom.xml index 4be822ba5f0..145f48cacdb 100644 --- a/jetty-jaspi/pom.xml +++ b/jetty-jaspi/pom.xml @@ -6,7 +6,7 @@ 4.0.0 jetty-jaspi - Jetty :: Security + Jetty :: JASPI Security Jetty security infrastructure @@ -50,21 +50,36 @@ + + + repository.apache.org + Apache Snapshot Repository + default + http://repository.apache.org/content/groups/snapshots/ + + true + + + false + + + + org.eclipse.jetty jetty-security ${project.version} - - org.apache.geronimo.specs - geronimo-jaspi_1.0_spec - 1.0-SNAPSHOT - junit junit test + + org.apache.geronimo.specs + geronimo-jaspi_1.0_spec + 1.0-SNAPSHOT + diff --git a/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/JaspiAuthenticator.java b/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/JaspiAuthenticator.java index a010b51f0c6..daade576835 100644 --- a/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/JaspiAuthenticator.java +++ b/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/JaspiAuthenticator.java @@ -87,10 +87,11 @@ public class JaspiAuthenticator implements Authenticator } // most likely validatedUser is not needed here. - public Authentication.Status secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication validatedUser) throws ServerAuthException + public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication validatedUser) throws ServerAuthException { JaspiMessageInfo info = (JaspiMessageInfo)req.getAttribute("org.eclipse.jetty.security.jaspi.info"); - if (info==null)info = new JaspiMessageInfo((HttpServletRequest)req,(HttpServletResponse)res,mandatory); + if (info==null) + info = new JaspiMessageInfo((HttpServletRequest)req,(HttpServletResponse)res,mandatory); return secureResponse(info,validatedUser); } @@ -108,10 +109,20 @@ public class JaspiAuthenticator implements Authenticator GroupPrincipalCallback groupPrincipalCallback = _callbackHandler.getThreadGroupPrincipalCallback(); String[] groups = groupPrincipalCallback == null?null:groupPrincipalCallback.getGroups(); + + if (authStatus == AuthStatus.SEND_CONTINUE) + return Authentication.CHALLENGE; + if (authStatus == AuthStatus.SEND_FAILURE) + return Authentication.FAILED; + Set ids = clientSubject.getPrivateCredentials(UserIdentity.class); if (ids.size()>0) - return new DefaultAuthentication(toServerAuthStatus(authStatus),authMethod,ids.iterator().next()); - return Authentication.SEND_FAILURE_RESULTS; + { + if (authStatus == AuthStatus.SEND_SUCCESS) + return new DefaultAuthentication.Send(this,ids.iterator().next()); + return new DefaultAuthentication(this,ids.iterator().next()); + } + return Authentication.FAILED; } catch (AuthException e) { @@ -119,31 +130,19 @@ public class JaspiAuthenticator implements Authenticator } } - public Authentication.Status secureResponse(JaspiMessageInfo messageInfo, Authentication validatedUser) throws ServerAuthException + public boolean secureResponse(JaspiMessageInfo messageInfo, Authentication validatedUser) throws ServerAuthException { try { ServerAuthContext authContext = _authConfig.getAuthContext(_authContextId,_serviceSubject,_authProperties); authContext.cleanSubject(messageInfo,validatedUser.getUserIdentity().getSubject()); - return toServerAuthStatus(authContext.secureResponse(messageInfo,_serviceSubject)); + AuthStatus status = authContext.secureResponse(messageInfo,_serviceSubject); + return (AuthStatus.SUCCESS.equals(status)); } catch (AuthException e) { throw new ServerAuthException(e); } } - - Authentication.Status toServerAuthStatus(AuthStatus authStatus) throws ServerAuthException - { - if (authStatus == AuthStatus.SEND_CONTINUE) - return Authentication.Status.SEND_CONTINUE; - if (authStatus == AuthStatus.SEND_FAILURE) - return Authentication.Status.SEND_FAILURE; - if (authStatus == AuthStatus.SEND_SUCCESS) - return Authentication.Status.SEND_SUCCESS; - if (authStatus == AuthStatus.SUCCESS) - return Authentication.Status.SUCCESS; - throw new ServerAuthException("Invalid server status: " + authStatus); - } } diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/Authentication.java b/jetty-security/src/main/java/org/eclipse/jetty/security/Authentication.java index 54938f5c541..fb6dc67f3cd 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/Authentication.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/Authentication.java @@ -22,49 +22,99 @@ import org.eclipse.jetty.server.UserIdentity; */ public interface Authentication { - public enum Status - { - SEND_FAILURE(false), SEND_SUCCESS(true), SEND_CONTINUE(false), SUCCESS(true); - boolean _success; - Status(boolean success) {_success=success; } - public boolean isSuccess(){ return _success;} - } - - Status getAuthStatus(); - String getAuthMethod(); UserIdentity getUserIdentity(); boolean isSuccess(); + boolean isSend(); + void logout(); + - public static final Authentication SUCCESS_UNAUTH_RESULTS = new Authentication() + public static final Authentication FAILED = new Authentication() { - public String getAuthMethod() {return null;} - public Status getAuthStatus() {return Authentication.Status.SUCCESS;} - public UserIdentity getUserIdentity() {return UserIdentity.UNAUTHENTICATED_IDENTITY;} - public boolean isSuccess() {return true;} - public void logout() {} + 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 SEND_CONTINUE_RESULTS = new Authentication() + public static final Authentication CHALLENGE = new Authentication() { - public String getAuthMethod() {return null;} - public Status getAuthStatus() {return Authentication.Status.SEND_CONTINUE;} - public UserIdentity getUserIdentity() {return UserIdentity.UNAUTHENTICATED_IDENTITY;} - public boolean isSuccess() {return false;} - public void logout() {} + 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 SEND_FAILURE_RESULTS = new Authentication() + public static final Authentication NOT_CHECKED = new Authentication() { - public String getAuthMethod() {return null;} - public Status getAuthStatus() {return Authentication.Status.SEND_FAILURE;} - public UserIdentity getUserIdentity() {return UserIdentity.UNAUTHENTICATED_IDENTITY;} - public boolean isSuccess() {return false;} - public void logout() {} + 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() + { + } + }; } diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/Authenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/Authenticator.java index f3e37aa6970..f32df2abbd1 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/Authenticator.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/Authenticator.java @@ -33,7 +33,7 @@ public interface Authenticator String getAuthMethod(); Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException; - Authentication.Status secureResponse(ServletRequest request, ServletResponse response, boolean mandatory, Authentication validatedUser) throws ServerAuthException; + boolean secureResponse(ServletRequest request, ServletResponse response, boolean mandatory, Authentication validatedUser) throws ServerAuthException; interface Configuration { diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintSecurityHandler.java b/jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintSecurityHandler.java index 4537d8c32db..209e5b8f586 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintSecurityHandler.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintSecurityHandler.java @@ -187,9 +187,9 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr UserDataConstraint userDataConstraint = UserDataConstraint.get(constraint.getDataConstraint()); roleInfo.setUserDataConstraint(userDataConstraint); - boolean unchecked = !constraint.getAuthenticate(); - roleInfo.setUnchecked(unchecked); - if (!roleInfo.isUnchecked()) + boolean checked = constraint.getAuthenticate(); + roleInfo.setChecked(checked); + if (roleInfo.isChecked()) { if (constraint.isAnyRole()) { @@ -312,7 +312,7 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr { return false; } - return !((RoleInfo)constraintInfo).isUnchecked(); + return ((RoleInfo)constraintInfo).isChecked(); } protected boolean checkWebResourcePermissions(String pathInContext, Request request, Response response, Object constraintInfo, UserIdentity userIdentity) @@ -324,7 +324,7 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr } RoleInfo roleInfo = (RoleInfo)constraintInfo; - if (roleInfo.isUnchecked()) + if (!roleInfo.isChecked()) { return true; } diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultAuthentication.java b/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultAuthentication.java index 344f171af1d..038fa160d8b 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultAuthentication.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultAuthentication.java @@ -23,13 +23,11 @@ import org.eclipse.jetty.server.UserIdentity; */ public class DefaultAuthentication implements Authentication { - private final Authentication.Status _authStatus; private final Authenticator _authenticator; private final UserIdentity _userIdentity; - public DefaultAuthentication(Authentication.Status authStatus, Authenticator authenticator, UserIdentity userIdentity) + public DefaultAuthentication(Authenticator authenticator, UserIdentity userIdentity) { - _authStatus = authStatus; _authenticator = authenticator; _userIdentity=userIdentity; } @@ -38,11 +36,6 @@ public class DefaultAuthentication implements Authentication { return _authenticator.getAuthMethod(); } - - public Authentication.Status getAuthStatus() - { - return _authStatus; - } public UserIdentity getUserIdentity() { @@ -51,7 +44,12 @@ public class DefaultAuthentication implements Authentication public boolean isSuccess() { - return _authStatus.isSuccess(); + return true; + } + + public boolean isSend() + { + return false; } public void logout() @@ -75,6 +73,19 @@ public class DefaultAuthentication implements Authentication public String toString() { - return "{Auth,"+getAuthMethod()+","+_authStatus+","+","+_userIdentity+"}"; + return "{Auth,"+getAuthMethod()+","+_userIdentity+"}"; + } + + public static class Send extends DefaultAuthentication + { + public Send(Authenticator authenticator, UserIdentity userIdentity) + { + super(authenticator,userIdentity); + } + + public boolean isSend() + { + return true; + } } } diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultIdentityService.java b/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultIdentityService.java index 6b1e8c1070e..6cb243d2e92 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultIdentityService.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultIdentityService.java @@ -43,7 +43,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 associate(UserIdentity user, Scope scope) + public UserIdentity scope(UserIdentity user, Scope scope) { Map roleRefMap=scope.getRoleRefMap(); if (roleRefMap!=null && roleRefMap.size()>0) @@ -51,16 +51,16 @@ public class DefaultIdentityService implements IdentityService return user; } - public void disassociate(UserIdentity scoped) + public void descope(UserIdentity scoped) { } - public Object associateRunAs(UserIdentity user, RunAsToken token) + public Object setRunAs(UserIdentity user, RunAsToken token) { return token; } - public void disassociateRunAs(Object lastToken) + public void unsetRunAs(Object lastToken) { } @@ -94,11 +94,6 @@ public class DefaultIdentityService implements IdentityService _delegate=user; _roleRefMap=roleRefMap; } - - public String[] getRoles() - { - return _delegate.getRoles(); - } public Subject getSubject() { diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultUserIdentity.java b/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultUserIdentity.java index aedff139dc0..2281c182882 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultUserIdentity.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultUserIdentity.java @@ -37,11 +37,6 @@ public class DefaultUserIdentity implements UserIdentity _roles=roles; } - public String[] getRoles() - { - return _roles; - } - public Subject getSubject() { return _subject; diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/HashLoginService.java b/jetty-security/src/main/java/org/eclipse/jetty/security/HashLoginService.java index f82590390b5..d9372bd456b 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/HashLoginService.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/HashLoginService.java @@ -160,7 +160,7 @@ public class HashLoginService extends MappedLoginService if (username != null && username.length() > 0 && credentials != null && credentials.length() > 0) { - String[] roleArray = UserIdentity.NO_ROLES; + String[] roleArray = IdentityService.NO_ROLES; if (roles != null && roles.length() > 0) roleArray = roles.split(","); known.add(username); diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/IdentityService.java b/jetty-security/src/main/java/org/eclipse/jetty/security/IdentityService.java index 7dfa3eb476f..acbbf7b615a 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/IdentityService.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/IdentityService.java @@ -26,7 +26,8 @@ import org.eclipse.jetty.server.UserIdentity; */ public interface IdentityService { - + final static String[] NO_ROLES = new String[]{}; + /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ @@ -42,13 +43,13 @@ public interface IdentityService /* ------------------------------------------------------------ */ /** - * Associate the {@link UserIdentity} and {@link UserIdentity.Scope} - * with the current thread. + * 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}. */ - UserIdentity associate(UserIdentity user, UserIdentity.Scope context); + UserIdentity scope(UserIdentity user, UserIdentity.Scope context); /* ------------------------------------------------------------ */ /** @@ -56,7 +57,7 @@ public interface IdentityService * previousUser identity. * @param scoped UserIdentity returned from previous associate call */ - void disassociate(UserIdentity scoped); + void descope(UserIdentity scoped); /* ------------------------------------------------------------ */ /** @@ -64,7 +65,7 @@ public interface IdentityService * @param token The runAsToken to associate. * @return The previous runAsToken or null. */ - Object associateRunAs(UserIdentity user, RunAsToken token); + Object setRunAs(UserIdentity user, RunAsToken token); /* ------------------------------------------------------------ */ /** @@ -72,7 +73,7 @@ public interface IdentityService * and reassociate the previous token. * @param token RUNAS returned from previous associateRunAs call */ - void disassociateRunAs(Object token); + void unsetRunAs(Object token); /* ------------------------------------------------------------ */ /** diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/LazyAuthentication.java b/jetty-security/src/main/java/org/eclipse/jetty/security/LazyAuthentication.java index caa3ecdbe27..df49bc6bad5 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/LazyAuthentication.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/LazyAuthentication.java @@ -13,32 +13,39 @@ 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 { - private static final Subject unauthenticatedSubject = new Subject(); - - private final Authenticator _serverAuthentication; - private final ServletRequest _request; - private final ServletResponse _response; + protected final Authenticator _authenticator; + protected final ServletRequest _request; + protected final ServletResponse _response; private Authentication _delegate; - public LazyAuthentication(Authenticator serverAuthentication, ServletRequest request, ServletResponse response) + public LazyAuthentication(Authenticator authenticator, ServletRequest request, ServletResponse response) { - if (serverAuthentication == null) throw new NullPointerException("No ServerAuthentication"); - this._serverAuthentication = serverAuthentication; - this._request=request; - this._response=response; + if (authenticator == null) + throw new NullPointerException("No Authenticator"); + this._authenticator = authenticator; + this._request = request; + this._response = response; } private Authentication getDelegate() @@ -47,36 +54,32 @@ public class LazyAuthentication implements Authentication { try { - _delegate = _serverAuthentication.validateRequest(_request, _response, false); + _delegate = _authenticator.validateRequest(_request,__nullResponse,false); + if (_delegate.isSend()) + _delegate=Authentication.NOT_CHECKED; } catch (ServerAuthException e) { - _delegate = DefaultAuthentication.SEND_FAILURE_RESULTS; + Log.debug(e); + _delegate = Authentication.FAILED; } } return _delegate; } - public Authentication.Status getAuthStatus() - { - return getDelegate().getAuthStatus(); - } - public boolean isSuccess() { return getDelegate().isSuccess(); } - public void logout() + public boolean isSend() { - if (_delegate!=null) - _delegate.logout(); + return false; } - - // for cleaning in secureResponse + public UserIdentity getUserIdentity() { - return _delegate == null ? UserIdentity.UNAUTHENTICATED_IDENTITY: _delegate.getUserIdentity(); + return getDelegate().getUserIdentity(); } public String getAuthMethod() @@ -84,8 +87,173 @@ public class LazyAuthentication implements Authentication return getDelegate().getAuthMethod(); } + public void logout() + { + if (_delegate != null) + _delegate.logout(); + } + public String toString() { - return "{Lazy,"+_delegate+"}"; + 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 + { + } + }; } diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/MappedLoginService.java b/jetty-security/src/main/java/org/eclipse/jetty/security/MappedLoginService.java index 76d459163e6..551a531151f 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/MappedLoginService.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/MappedLoginService.java @@ -150,7 +150,7 @@ public abstract class MappedLoginService extends AbstractLifeCycle implements Lo subject.getPrincipals().add(userPrincipal); subject.getPrivateCredentials().add(credential); subject.setReadOnly(); - identity=_identityService.newUserIdentity(subject,userPrincipal,UserIdentity.NO_ROLES); + identity=_identityService.newUserIdentity(subject,userPrincipal,IdentityService.NO_ROLES); } _users.put(userName,identity); diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/RoleInfo.java b/jetty-security/src/main/java/org/eclipse/jetty/security/RoleInfo.java index d4d687f51c6..b58558f70da 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/RoleInfo.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/RoleInfo.java @@ -29,21 +29,25 @@ public class RoleInfo { private final static String[] NO_ROLES={}; private boolean _isAnyRole; - private boolean _unchecked; + private boolean _checked; private boolean _forbidden; private UserDataConstraint _userDataConstraint; private String[] _roles = NO_ROLES; - public boolean isUnchecked() + public RoleInfo() + { + } + + public boolean isChecked() { - return _unchecked; + return _checked; } - public void setUnchecked(boolean unchecked) + public void setChecked(boolean checked) { - this._unchecked = unchecked; - if (unchecked) + this._checked = checked; + if (!checked) { _forbidden=false; _roles=NO_ROLES; @@ -61,7 +65,7 @@ public class RoleInfo this._forbidden = forbidden; if (forbidden) { - _unchecked = false; + _checked = true; _userDataConstraint = null; _isAnyRole=false; _roles=NO_ROLES; @@ -78,7 +82,7 @@ public class RoleInfo this._isAnyRole=anyRole; if (anyRole) { - _unchecked = false; + _checked = true; _roles=NO_ROLES; } } @@ -115,8 +119,8 @@ public class RoleInfo { if (other._forbidden) setForbidden(true); - else if (other._unchecked) - setUnchecked(true); + else if (!other._checked) // TODO is this the right way around??? + setChecked(true); else if (other._isAnyRole) setAnyRole(true); else if (!_isAnyRole) @@ -130,6 +134,6 @@ public class RoleInfo public String toString() { - return "{RoleInfo"+(_forbidden?",F":"")+(_unchecked?",U":"")+(_isAnyRole?",*":Arrays.asList(_roles).toString())+"}"; + return "{RoleInfo"+(_forbidden?",F":"")+(_checked?",C":"")+(_isAnyRole?",*":Arrays.asList(_roles).toString())+"}"; } } diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/SecurityHandler.java b/jetty-security/src/main/java/org/eclipse/jetty/security/SecurityHandler.java index ba0d5e002df..54076218b4e 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/SecurityHandler.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/SecurityHandler.java @@ -413,7 +413,7 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti final Authenticator authenticator = _authenticator; Authentication authentication = authenticator.validateRequest(request, response, isAuthMandatory); - if (authentication.getAuthStatus() == Authentication.Status.SUCCESS) + if (authentication!=null && !authentication.isSend()) { final UserIdentity user_identity=authentication.getUserIdentity(); base_request.setAuthType(authentication.getAuthMethod()); diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/BasicAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/BasicAuthenticator.java index 56a0ba3f097..faeb73fc084 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/BasicAuthenticator.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/BasicAuthenticator.java @@ -27,7 +27,6 @@ import org.eclipse.jetty.security.Authentication; import org.eclipse.jetty.security.DefaultAuthentication; import org.eclipse.jetty.security.DefaultUserIdentity; import org.eclipse.jetty.security.ServerAuthException; -import org.eclipse.jetty.security.Authentication.Status; import org.eclipse.jetty.server.UserIdentity; import org.eclipse.jetty.util.StringUtil; @@ -75,18 +74,15 @@ public class BasicAuthenticator extends LoginAuthenticator UserIdentity user = _loginService.login(username,password); if (user!=null) - { - return new DefaultAuthentication(Authentication.Status.SUCCESS,this,user); - } + return new DefaultAuthentication(this,user); } if (!mandatory) - { - return DefaultAuthentication.SUCCESS_UNAUTH_RESULTS; - } + return Authentication.NOT_CHECKED; + response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "basic realm=\"" + _loginService.getName() + '"'); response.sendError(HttpServletResponse.SC_UNAUTHORIZED); - return DefaultAuthentication.SEND_CONTINUE_RESULTS; + return Authentication.CHALLENGE; } catch (IOException e) { @@ -94,12 +90,10 @@ public class BasicAuthenticator extends LoginAuthenticator } } - // most likely validatedUser is not needed here. - - // corrct? - public Authentication.Status secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication validatedUser) throws ServerAuthException + // TODO most likely validatedUser is not needed here ?? + public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication validatedUser) throws ServerAuthException { - return Authentication.Status.SUCCESS; + return true; } } diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/ClientCertAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/ClientCertAuthenticator.java index cef53292381..875bda0d254 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/ClientCertAuthenticator.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/ClientCertAuthenticator.java @@ -62,9 +62,8 @@ public class ClientCertAuthenticator extends LoginAuthenticator // Need certificates. if (certs == null || certs.length == 0 || certs[0] == null) { - response.sendError(HttpServletResponse.SC_FORBIDDEN, - "A client certificate is required for accessing this web application but the server's listener is not configured for mutual authentication (or the client did not provide a certificate)."); - return DefaultAuthentication.SEND_FAILURE_RESULTS; + response.sendError(HttpServletResponse.SC_FORBIDDEN,"!certificate"); + return Authentication.FAILED; } Principal principal = certs[0].getSubjectDN(); @@ -76,14 +75,12 @@ public class ClientCertAuthenticator extends LoginAuthenticator UserIdentity user = _loginService.login(username,credential); if (user!=null) - return new DefaultAuthentication(Authentication.Status.SUCCESS,this,user); + return new DefaultAuthentication(this,user); if (!mandatory) - { - return DefaultAuthentication.SUCCESS_UNAUTH_RESULTS; - } - response.sendError(HttpServletResponse.SC_FORBIDDEN, "The provided client certificate does not correspond to a trusted user."); - return DefaultAuthentication.SEND_FAILURE_RESULTS; + return Authentication.NOT_CHECKED; + response.sendError(HttpServletResponse.SC_FORBIDDEN); + return Authentication.FAILED; } catch (IOException e) { @@ -91,8 +88,8 @@ public class ClientCertAuthenticator extends LoginAuthenticator } } - public Authentication.Status secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication validatedUser) throws ServerAuthException + public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication validatedUser) throws ServerAuthException { - return Authentication.Status.SUCCESS; + return true; } } diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DelegateAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DelegateAuthenticator.java index e7343cc7d2c..21a3cb2cab3 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DelegateAuthenticator.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DelegateAuthenticator.java @@ -49,7 +49,7 @@ public class DelegateAuthenticator implements Authenticator return _delegate.validateRequest(request, response, manditory); } - public Authentication.Status secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication validatedUser) throws ServerAuthException + public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication validatedUser) throws ServerAuthException { return _delegate.secureResponse(req,res, mandatory, validatedUser); } diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DigestAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DigestAuthenticator.java index 09c4d51ce78..c8e9daf15b2 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DigestAuthenticator.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DigestAuthenticator.java @@ -55,9 +55,9 @@ public class DigestAuthenticator extends LoginAuthenticator return Constraint.__DIGEST_AUTH; } - public Authentication.Status secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication validatedUser) throws ServerAuthException + public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication validatedUser) throws ServerAuthException { - return Authentication.Status.SUCCESS; + return true; } public Authentication validateRequest(ServletRequest req, ServletResponse res, boolean mandatory) throws ServerAuthException @@ -124,25 +124,29 @@ public class DigestAuthenticator extends LoginAuthenticator UserIdentity user = _loginService.login(digest.username,digest); if (user!=null) { - return new DefaultAuthentication(Authentication.Status.SUCCESS,this,user); + return new DefaultAuthentication(this,user); } } else if (n == 0) stale = true; } - if (!mandatory) { return DefaultAuthentication.SUCCESS_UNAUTH_RESULTS; } + if (!mandatory) + return Authentication.NOT_CHECKED; + String domain = request.getContextPath(); - if (domain == null) domain = "/"; + 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) : "")); + + "\", domain=\"" + + domain + + "\", nonce=\"" + + newNonce((Request)request) + + "\", algorithm=MD5, qop=\"auth\"" + + (_useStale ? (" stale=" + stale) : "")); response.sendError(HttpServletResponse.SC_UNAUTHORIZED); - return DefaultAuthentication.SEND_CONTINUE_RESULTS; + + return Authentication.CHALLENGE; } catch (IOException e) { diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/FormAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/FormAuthenticator.java index 7ef36047180..deb3d26b3e0 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/FormAuthenticator.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/FormAuthenticator.java @@ -150,41 +150,49 @@ public class FormAuthenticator extends LoginAuthenticator HttpServletResponse response = (HttpServletResponse)res; HttpSession session = request.getSession(mandatory); String uri = request.getPathInfo(); - // not mandatory and not authenticated + + // not mandatory or not authenticated if (session == null || isLoginOrErrorPage(uri)) { - return DefaultAuthentication.SUCCESS_UNAUTH_RESULTS; + return Authentication.NOT_CHECKED; } try { // Handle a request for authentication. - // TODO perhaps j_securitycheck can be uri suffix? - if (uri.endsWith(__J_SECURITY_CHECK)) + if (uri==null) + uri=URIUtil.SLASH; + else if (uri.endsWith(__J_SECURITY_CHECK)) { final String username = request.getParameter(__J_USERNAME); - final char[] password = request.getParameter(__J_PASSWORD).toCharArray(); + final String password = request.getParameter(__J_PASSWORD); UserIdentity user = _loginService.login(username,password); if (user!=null) { // Redirect to original request - String nuri = (String) session.getAttribute(__J_URI); + String nuri; + synchronized(session) + { + nuri = (String) session.getAttribute(__J_URI); + session.removeAttribute(__J_URI); + } + if (nuri == null || nuri.length() == 0) { nuri = request.getContextPath(); - if (nuri.length() == 0) nuri = URIUtil.SLASH; + if (nuri.length() == 0) + nuri = URIUtil.SLASH; } - // TODO shouldn't we forward to original URI instead? - session.removeAttribute(__J_URI); // Remove popped return URI. response.setContentLength(0); response.sendRedirect(response.encodeRedirectURL(nuri)); - return new DefaultAuthentication(Authentication.Status.SEND_SUCCESS,this,user); + return new DefaultAuthentication.Send(this,user); } // not authenticated - if (Log.isDebugEnabled()) Log.debug("Form authentication FAILED for " + StringUtil.printable(username)); + if (Log.isDebugEnabled()) + Log.debug("Form authentication FAILED for " + StringUtil.printable(username)); if (_formErrorPage == null) { if (response != null) @@ -202,27 +210,28 @@ public class FormAuthenticator extends LoginAuthenticator response.sendRedirect(URIUtil.addPaths(request.getContextPath(),_formErrorPage)); } - // TODO is this correct response if isMandatory false??? Can - // that occur? - return DefaultAuthentication.SEND_FAILURE_RESULTS; + return Authentication.FAILED; } // Check if the session is already authenticated. // Don't authenticate authform or errorpage - if (!mandatory) - // TODO verify this is correct action - return DefaultAuthentication.SUCCESS_UNAUTH_RESULTS; + if (!mandatory) + return Authentication.NOT_CHECKED; // redirect to login page if (request.getQueryString() != null) uri += "?" + request.getQueryString(); - //TODO is this safe if the client is sending several requests concurrently in the same session to secured resources? - session.setAttribute(__J_URI, request.getScheme() + "://" - + request.getServerName() - + ":" - + request.getServerPort() - + URIUtil.addPaths(request.getContextPath(), uri)); + 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); @@ -234,8 +243,8 @@ public class FormAuthenticator extends LoginAuthenticator { response.sendRedirect(URIUtil.addPaths(request.getContextPath(),_formLoginPage)); } + return Authentication.CHALLENGE; - return DefaultAuthentication.SEND_CONTINUE_RESULTS; } catch (IOException e) { @@ -254,9 +263,9 @@ public class FormAuthenticator extends LoginAuthenticator } /* ------------------------------------------------------------ */ - public Authentication.Status secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication validatedUser) throws ServerAuthException + public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication validatedUser) throws ServerAuthException { - return Authentication.Status.SUCCESS; + return true; } /* ------------------------------------------------------------ */ diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/LoginCallbackImpl.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/LoginCallbackImpl.java index bb1ee368982..578310d9484 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/LoginCallbackImpl.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/LoginCallbackImpl.java @@ -17,6 +17,7 @@ import java.security.Principal; import javax.security.auth.Subject; +import org.eclipse.jetty.security.IdentityService; import org.eclipse.jetty.server.UserIdentity; /** @@ -38,7 +39,7 @@ public class LoginCallbackImpl implements LoginCallback private Principal userPrincipal; - private String[] roles = UserIdentity.NO_ROLES; + private String[] roles = IdentityService.NO_ROLES; //TODO could use Credential instance instead of Object if Basic/Form create a Password object public LoginCallbackImpl (Subject subject, String userName, Object credential) diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SessionCachingAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SessionCachingAuthenticator.java index c2c7997ce93..29b825c19a8 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SessionCachingAuthenticator.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SessionCachingAuthenticator.java @@ -26,7 +26,6 @@ import org.eclipse.jetty.security.Authentication; import org.eclipse.jetty.security.Authenticator; import org.eclipse.jetty.security.DefaultAuthentication; import org.eclipse.jetty.security.ServerAuthException; -import org.eclipse.jetty.security.Authentication.Status; import org.eclipse.jetty.server.UserIdentity; /** @@ -46,26 +45,27 @@ public class SessionCachingAuthenticator extends DelegateAuthenticator HttpSession session = ((HttpServletRequest)request).getSession(mandatory); // not mandatory and not authenticated if (session == null) - return DefaultAuthentication.SUCCESS_UNAUTH_RESULTS; + return Authentication.NOT_CHECKED; Authentication authentication = (Authentication) session.getAttribute(__J_AUTHENTICATED); if (authentication != null) return authentication; authentication = _delegate.validateRequest(request, response, mandatory); - if (authentication != null && authentication.getUserIdentity().getSubject() != null) + if (authentication!=null && authentication.isSuccess()) { - Authentication next=new FormAuthentication(Authentication.Status.SUCCESS,_delegate,authentication.getUserIdentity()); - session.setAttribute(__J_AUTHENTICATED, next); + Authentication cached=new FormAuthentication(_delegate,authentication.getUserIdentity()); + session.setAttribute(__J_AUTHENTICATED, cached); } + return authentication; } protected class FormAuthentication extends DefaultAuthentication implements HttpSessionAttributeListener { - public FormAuthentication(Status authStatus, Authenticator authenticator, UserIdentity userIdentity) + public FormAuthentication(Authenticator authenticator, UserIdentity userIdentity) { - super(authStatus,authenticator,userIdentity); + super(authenticator,userIdentity); } public void attributeAdded(HttpSessionBindingEvent event) diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/ConstraintTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/ConstraintTest.java index b66d746c0ea..a5de2a8ef51 100644 --- a/jetty-security/src/test/java/org/eclipse/jetty/security/ConstraintTest.java +++ b/jetty-security/src/test/java/org/eclipse/jetty/security/ConstraintTest.java @@ -564,7 +564,7 @@ public class ConstraintTest extends TestCase public void handle(String target, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { UserIdentity old = ((Request) request).getUserIdentity(); - UserIdentity scoped = _security.getIdentityService().associate(old, + UserIdentity scoped = _security.getIdentityService().scope(old, new UserIdentity.Scope() { @@ -585,11 +585,6 @@ public class ConstraintTest extends TestCase return map; } - public String getRunAsRole() - { - return null; - } - }); ((Request)request).setUserIdentity(scoped); @@ -599,7 +594,7 @@ public class ConstraintTest extends TestCase } finally { - _security.getIdentityService().disassociate(scoped); + _security.getIdentityService().descope(scoped); ((Request)request).setUserIdentity(old); } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java index ac972f379b2..bc62ae51f05 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java @@ -57,7 +57,7 @@ public class Server extends HandlerWrapper implements Attributes private static ShutdownHookThread hookThread = new ShutdownHookThread(); private static String _version = (Server.class.getPackage()!=null && Server.class.getPackage().getImplementationVersion()!=null) ?Server.class.getPackage().getImplementationVersion() - :"7.0.x"; + :"7.0.0.M1-SNAPSHOT"; private ThreadPool _threadPool; private Connector[] _connectors; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/UserIdentity.java b/jetty-server/src/main/java/org/eclipse/jetty/server/UserIdentity.java index 94373bc5026..b0a158e332d 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/UserIdentity.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/UserIdentity.java @@ -29,8 +29,6 @@ import javax.servlet.ServletResponse; */ public interface UserIdentity { - final static String[] NO_ROLES = new String[]{}; - /* ------------------------------------------------------------ */ /** * @return The user subject @@ -43,12 +41,6 @@ public interface UserIdentity */ Principal getUserPrincipal(); - /* ------------------------------------------------------------ */ - /** - * @return The users roles - */ - String[] getRoles(); - /* ------------------------------------------------------------ */ /** Check if the user is in a role. * This call is used to satisfy authorization calls from @@ -83,12 +75,6 @@ public interface UserIdentity */ String getName(); - /* ------------------------------------------------------------ */ - /** - * @return The name of a runAs entity. Typically this is a runAs role applied to a servlet. - */ - String getRunAsRole(); - /* ------------------------------------------------------------ */ /** * @return A map of role reference names that converts from names used by application code @@ -119,11 +105,6 @@ public interface UserIdentity return null; } - public String[] getRoles() - { - return NO_ROLES; - } - public boolean isUserInRole(String role) { return false; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandler.java index 6cba3d819b7..8f0fed72cbf 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandler.java @@ -98,4 +98,21 @@ public abstract class AbstractHandler extends AbstractLifeCycle implements Handl _server.getContainer().removeBean(this); } + + /* ------------------------------------------------------------ */ + public String dump() + { + StringBuilder b = new StringBuilder(); + dump(b,""); + return b.toString(); + } + + /* ------------------------------------------------------------ */ + protected void dump(StringBuilder b,String indent) + { + b.append(toString()); + b.append(isStarted()?" started":" STOPPED"); + b.append('\n'); + } + } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandlerContainer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandlerContainer.java index d899b7458cd..44a306e5fc8 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandlerContainer.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandlerContainer.java @@ -22,8 +22,6 @@ import org.eclipse.jetty.util.LazyList; /* ------------------------------------------------------------ */ /** Abstract Handler Container. * This is the base class for handlers that may contain other handlers. - * - * * */ public abstract class AbstractHandlerContainer extends AbstractHandler implements HandlerContainer @@ -83,33 +81,28 @@ public abstract class AbstractHandlerContainer extends AbstractHandler implement return list; } - - /* ------------------------------------------------------------ */ - public String dump() - { - StringBuilder b = new StringBuilder(); - dump(b,this,0); - return b.toString(); - } - /* ------------------------------------------------------------ */ - protected void dump(StringBuilder b,Handler handler,int indent) + protected void dump(StringBuilder b,String indent) { - for (int i=0;i _managedAttributes; diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java index 35947ff9624..f2298d0e1e6 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java @@ -54,7 +54,7 @@ public class HttpServerTestBase extends TestCase private static final String REQUEST1=REQUEST1_HEADER+REQUEST1_CONTENT.getBytes().length+"\n\n"+REQUEST1_CONTENT; /** The expected response. */ - private static final String RESPONSE1="HTTP/1.1 200 OK\n"+"Connection: close\n"+"Server: Jetty(7.0.x)\n"+"\n"+"Hello world\n"; + private static final String RESPONSE1="HTTP/1.1 200 OK\n"+"Connection: close\n"+"Server: Jetty("+Server.getVersion()+")\n"+"\n"+"Hello world\n"; // Break the request up into three pieces, splitting the header. private static final String FRAGMENT1=REQUEST1.substring(0,16); @@ -95,7 +95,7 @@ public class HttpServerTestBase extends TestCase "HTTP/1.1 200 OK\n"+ "Content-Type: text/xml;charset=ISO-8859-1\n"+ "Content-Length: "+RESPONSE2_CONTENT.getBytes().length+"\n"+ - "Server: Jetty(7.0.x)\n"+ + "Server: Jetty("+Server.getVersion()+")\n"+ "\n"+ RESPONSE2_CONTENT; diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java index b8b655352d7..7cf01f0acca 100644 --- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java +++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java @@ -28,6 +28,7 @@ import javax.servlet.UnavailableException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; import org.eclipse.jetty.http.HttpContent; import org.eclipse.jetty.http.HttpFields; @@ -656,21 +657,23 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory } else { - // See if a short direct method can be used? + // See if a direct methods can be used? if (out instanceof HttpConnection.Output) { - if (_cacheControl!=null) + if (response instanceof Response) { - if (response instanceof Response) + if (_cacheControl!=null) ((Response)response).getHttpFields().put(HttpHeaders.CACHE_CONTROL_BUFFER,_cacheControl); - else - response.setHeader(HttpHeaders.CACHE_CONTROL,_cacheControl.toString()); + ((HttpConnection.Output)out).sendContent(content); + } + else + { + writeHeaders(response,content,content_length); + ((HttpConnection.Output)out).sendContent(content.getBuffer()); } - ((HttpConnection.Output)out).sendContent(content); } else { - // Write content normally writeHeaders(response,content,content_length); resource.writeTo(out,0,content_length); diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/FilterMapping.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/FilterMapping.java index 0467bb2d369..bac094ad81c 100644 --- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/FilterMapping.java +++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/FilterMapping.java @@ -274,7 +274,11 @@ public class FilterMapping /* ------------------------------------------------------------ */ public String toString() { - return "(F="+_filterName+","+(_pathSpecs==null?"[]":Arrays.asList(_pathSpecs).toString())+","+(_servletNames==null?"[]":Arrays.asList(_servletNames).toString())+","+_dispatches+")"; + return + (_pathSpecs==null?"[]":Arrays.asList(_pathSpecs).toString())+"/"+ + (_servletNames==null?"[]":Arrays.asList(_servletNames).toString())+"=="+ + _dispatches+"=>"+ + _filterName; } } diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java index 62c31de4a2b..a00ee9b8018 100644 --- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java +++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java @@ -17,6 +17,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -42,6 +43,8 @@ import org.eclipse.jetty.security.IdentityService; import org.eclipse.jetty.security.SecurityHandler; import org.eclipse.jetty.server.Dispatcher; import org.eclipse.jetty.server.DispatcherType; +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.HandlerContainer; import org.eclipse.jetty.server.HttpConnection; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.RetryRequest; @@ -383,7 +386,7 @@ public class ServletHandler extends AbstractHandler if (_identityService!=null) { old_identity=base_request.getUserIdentity(); - scoped_identity=_identityService.associate(old_identity,servlet_holder); + scoped_identity=_identityService.scope(old_identity,servlet_holder); base_request.setUserIdentity(scoped_identity); } @@ -516,7 +519,7 @@ public class ServletHandler extends AbstractHandler if (scoped_identity!=null) { - _identityService.disassociate(scoped_identity); + _identityService.descope(scoped_identity); base_request.setUserIdentity(old_identity); } base_request.setServletName(old_servlet_name); @@ -1367,4 +1370,50 @@ public class ServletHandler extends AbstractHandler { return filter; } + + + + /* ------------------------------------------------------------ */ + protected void dump(StringBuilder b,String indent) + { + super.dump(b,indent); + + if (getFilterMappings()!=null) + { + for (FilterMapping f : getFilterMappings()) + { + b.append(indent); + b.append(" +-"); + b.append(f); + b.append('\n'); + } + } + HashSet servlets = new HashSet(); + if (getServletMappings()!=null) + { + for (ServletMapping m : getServletMappings()) + { + servlets.add(m.getServletName()); + b.append(indent); + b.append(" +-"); + b.append(m); + b.append('\n'); + } + } + + if (getServlets()!=null) + { + for (ServletHolder h : getServlets()) + { + if (servlets.contains(h.getName())) + continue; + b.append(indent); + b.append(" +-[]==>"); + b.append(h.getName()); + b.append('\n'); + } + } + + } + } diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java index 42d632bebf3..5c8a88706f2 100644 --- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java +++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java @@ -263,7 +263,7 @@ public class ServletHolder extends Holder implements UserIdentity.Scope, Compara try { if (_identityService!=null && _runAsToken!=null) - old_run_as=_identityService.associateRunAs(_identityService.getSystemUserIdentity(),_runAsToken); + old_run_as=_identityService.setRunAs(_identityService.getSystemUserIdentity(),_runAsToken); destroyInstance(_servlet); } @@ -274,7 +274,7 @@ public class ServletHolder extends Holder implements UserIdentity.Scope, Compara finally { if (_identityService!=null && _runAsToken!=null) - _identityService.disassociateRunAs(old_run_as); + _identityService.unsetRunAs(old_run_as); } } @@ -405,7 +405,7 @@ public class ServletHolder extends Holder implements UserIdentity.Scope, Compara // Handle run as if (_identityService!=null && _runAsToken!=null) { - old_run_as=_identityService.associateRunAs(_identityService.getSystemUserIdentity(),_runAsToken); + old_run_as=_identityService.setRunAs(_identityService.getSystemUserIdentity(),_runAsToken); } _servlet.init(_config); @@ -435,7 +435,7 @@ public class ServletHolder extends Holder implements UserIdentity.Scope, Compara { // pop run-as role if (_identityService!=null && _runAsToken!=null) - _identityService.disassociateRunAs(old_run_as); + _identityService.unsetRunAs(old_run_as); } } @@ -512,7 +512,7 @@ public class ServletHolder extends Holder implements UserIdentity.Scope, Compara // Handle run as if (_identityService!=null && _runAsToken!=null) - old_run_as=_identityService.associateRunAs(baseRequest.getUserIdentity(),_runAsToken); + old_run_as=_identityService.setRunAs(baseRequest.getUserIdentity(),_runAsToken); if (!isAsyncSupported()) baseRequest.setAsyncSupported(false); @@ -531,7 +531,7 @@ public class ServletHolder extends Holder implements UserIdentity.Scope, Compara // pop run-as role if (_identityService!=null && _runAsToken!=null) - _identityService.disassociateRunAs(old_run_as); + _identityService.unsetRunAs(old_run_as); // Handle error params. if (servlet_error) diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletMapping.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletMapping.java index 88ecb0963a5..80e8d802c1a 100644 --- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletMapping.java +++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletMapping.java @@ -75,6 +75,6 @@ public class ServletMapping /* ------------------------------------------------------------ */ public String toString() { - return "(S="+_servletName+","+(_pathSpecs==null?"[]":Arrays.asList(_pathSpecs).toString())+")"; + return (_pathSpecs==null?"[]":Arrays.asList(_pathSpecs).toString())+"=>"+_servletName; } } diff --git a/jetty-test-webapp/src/test/java/org/eclipse/jetty/DemoServer.java b/jetty-test-webapp/src/test/java/org/eclipse/jetty/DemoServer.java index f1b435090f6..6c58fe1e655 100644 --- a/jetty-test-webapp/src/test/java/org/eclipse/jetty/DemoServer.java +++ b/jetty-test-webapp/src/test/java/org/eclipse/jetty/DemoServer.java @@ -3,6 +3,7 @@ package org.eclipse.jetty; import org.eclipse.jetty.http.security.Password; import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.webapp.WebAppContext; public class DemoServer @@ -13,7 +14,7 @@ public class DemoServer Server server = new Server(8080); WebAppContext context = new WebAppContext(); - context.setWar("./target/jetty-test-webapp-7.0.0.M1-SNAPSHOT"); // TODO YUCK! + context.setWar("./target/jetty-test-webapp-"+Server.getVersion()); // TODO YUCK! context.setDefaultsDescriptor("../jetty-webapp/src/main/config/etc/webdefault.xml"); server.setHandler(context); diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/IO.java b/jetty-util/src/main/java/org/eclipse/jetty/util/IO.java index ad503a7f756..d3ec54e279c 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/IO.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/IO.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; +import java.io.PrintWriter; import java.io.Reader; import java.io.StringWriter; import java.io.Writer; @@ -435,6 +436,15 @@ public class IO return __nullWriter; } + /* ------------------------------------------------------------ */ + /** + * @return An writer to nowhere + */ + public static PrintWriter getNullPrintWriter() + { + return __nullPrintWriter; + } + /* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */ private static class NullWrite extends Writer @@ -448,7 +458,7 @@ public class IO public void write(String s,int o,int l){} } private static NullWrite __nullWriter = new NullWrite(); - + private static PrintWriter __nullPrintWriter = new PrintWriter(__nullWriter); } diff --git a/pom.xml b/pom.xml index 144855a9780..f06db926031 100644 --- a/pom.xml +++ b/pom.xml @@ -109,6 +109,7 @@ jetty-client jetty-xml jetty-security + jetty-jaspi jetty-servlet jetty-webapp jetty-servlets