diff --git a/jetty-jaspi/pom.xml b/jetty-jaspi/pom.xml index d446a891fdb..9cb18cfc744 100644 --- a/jetty-jaspi/pom.xml +++ b/jetty-jaspi/pom.xml @@ -23,6 +23,24 @@ org.eclipse.jetty.jaspi.* + + org.apache.felix + maven-bundle-plugin + true + + + + manifest + + + + osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)" + osgi.serviceloader;osgi.serviceloader=org.eclipse.jetty.security.Authenticator$Factory + + + + + diff --git a/jetty-jaspi/src/main/resources/META-INF/services/org.eclipse.jetty.security.Authenticator$Factory b/jetty-jaspi/src/main/resources/META-INF/services/org.eclipse.jetty.security.Authenticator$Factory new file mode 100644 index 00000000000..2e24fa8ca2a --- /dev/null +++ b/jetty-jaspi/src/main/resources/META-INF/services/org.eclipse.jetty.security.Authenticator$Factory @@ -0,0 +1 @@ +org.eclipse.jetty.security.jaspi.JaspiAuthenticatorFactory \ No newline at end of file diff --git a/jetty-openid/pom.xml b/jetty-openid/pom.xml index 1100f4dc10f..6c2943a636b 100644 --- a/jetty-openid/pom.xml +++ b/jetty-openid/pom.xml @@ -24,6 +24,24 @@ org.eclipse.jetty.security.openid.* + + org.apache.felix + maven-bundle-plugin + true + + + + manifest + + + + osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)" + osgi.serviceloader;osgi.serviceloader=org.eclipse.jetty.security.Authenticator$Factory + + + + + diff --git a/jetty-openid/src/main/java/org/eclipse/jetty/security/openid/OpenIdAuthenticatorFactory.java b/jetty-openid/src/main/java/org/eclipse/jetty/security/openid/OpenIdAuthenticatorFactory.java index 86eea6cdbde..20af7a7ed0e 100644 --- a/jetty-openid/src/main/java/org/eclipse/jetty/security/openid/OpenIdAuthenticatorFactory.java +++ b/jetty-openid/src/main/java/org/eclipse/jetty/security/openid/OpenIdAuthenticatorFactory.java @@ -21,13 +21,12 @@ package org.eclipse.jetty.security.openid; import javax.servlet.ServletContext; import org.eclipse.jetty.security.Authenticator; -import org.eclipse.jetty.security.DefaultAuthenticatorFactory; import org.eclipse.jetty.security.IdentityService; import org.eclipse.jetty.security.LoginService; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.util.security.Constraint; -public class OpenIdAuthenticatorFactory extends DefaultAuthenticatorFactory +public class OpenIdAuthenticatorFactory implements Authenticator.Factory { @Override public Authenticator getAuthenticator(Server server, ServletContext context, Authenticator.AuthConfiguration configuration, IdentityService identityService, LoginService loginService) @@ -35,6 +34,6 @@ public class OpenIdAuthenticatorFactory extends DefaultAuthenticatorFactory String auth = configuration.getAuthMethod(); if (Constraint.__OPENID_AUTH.equalsIgnoreCase(auth)) return new OpenIdAuthenticator(); - return super.getAuthenticator(server, context, configuration, identityService, loginService); + return null; } } \ No newline at end of file diff --git a/jetty-openid/src/main/resources/META-INF/services/org.eclipse.jetty.security.Authenticator$Factory b/jetty-openid/src/main/resources/META-INF/services/org.eclipse.jetty.security.Authenticator$Factory new file mode 100644 index 00000000000..cc53212a57b --- /dev/null +++ b/jetty-openid/src/main/resources/META-INF/services/org.eclipse.jetty.security.Authenticator$Factory @@ -0,0 +1 @@ +org.eclipse.jetty.security.openid.OpenIdAuthenticatorFactory \ No newline at end of file diff --git a/jetty-security/pom.xml b/jetty-security/pom.xml index 13008a7b235..b2fd3b06d53 100644 --- a/jetty-security/pom.xml +++ b/jetty-security/pom.xml @@ -21,6 +21,23 @@ org.eclipse.jetty.security.* + + org.apache.felix + maven-bundle-plugin + true + + + + manifest + + + + osgi.serviceloader; filter:="(osgi.serviceloader=org.eclipse.jetty.security.Authenticator$Factory)";resolution:=optional;cardinality:=multiple, osgi.extender; filter:="(osgi.extender=osgi.serviceloader.processor)";resolution:=optional + + + + + 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 62df3199fd7..d5b74b488f2 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 @@ -20,10 +20,13 @@ package org.eclipse.jetty.security; import java.io.IOException; import java.security.Principal; +import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.ServiceLoader; import java.util.Set; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -38,6 +41,7 @@ import org.eclipse.jetty.server.UserIdentity; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandler.Context; import org.eclipse.jetty.server.handler.HandlerWrapper; +import org.eclipse.jetty.util.component.DumpableCollection; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -58,20 +62,31 @@ import org.eclipse.jetty.util.log.Logger; public abstract class SecurityHandler extends HandlerWrapper implements Authenticator.AuthConfiguration { private static final Logger LOG = Log.getLogger(SecurityHandler.class); + private static final List __knownAuthenticatorFactories = new ArrayList<>(); private boolean _checkWelcomeFiles = false; private Authenticator _authenticator; - private Authenticator.Factory _authenticatorFactory = new DefaultAuthenticatorFactory(); + private Authenticator.Factory _authenticatorFactory; private String _realmName; private String _authMethod; - private final Map _initParameters = new HashMap(); + private final Map _initParameters = new HashMap<>(); private LoginService _loginService; private IdentityService _identityService; private boolean _renewSession = true; + static + { + for (Authenticator.Factory factory : ServiceLoader.load(Authenticator.Factory.class)) + { + __knownAuthenticatorFactories.add(factory); + } + + __knownAuthenticatorFactories.add(new DefaultAuthenticatorFactory()); + } + protected SecurityHandler() { - addBean(_authenticatorFactory); + addBean(new DumpableCollection("knownAuthenticatorFactories", __knownAuthenticatorFactories)); } /** @@ -163,6 +178,14 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti _authenticatorFactory = authenticatorFactory; } + /** + * @return the list of discovered authenticatorFactories + */ + public List getKnownAuthenticatorFactories() + { + return __knownAuthenticatorFactories; + } + /** * @return the realmName */ @@ -241,12 +264,12 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti * @param key the init key * @param value the init value * @return previous value - * @throws IllegalStateException if the SecurityHandler is running + * @throws IllegalStateException if the SecurityHandler is started */ public String setInitParameter(String key, String value) { - if (isRunning()) - throw new IllegalStateException("running"); + if (isStarted()) + throw new IllegalStateException("started"); return _initParameters.put(key, value); } @@ -336,9 +359,40 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti throw new IllegalStateException("LoginService has different IdentityService to " + this); } - Authenticator.Factory authenticatorFactory = getAuthenticatorFactory(); - if (_authenticator == null && authenticatorFactory != null && _identityService != null) - setAuthenticator(authenticatorFactory.getAuthenticator(getServer(), ContextHandler.getCurrentContext(), this, _identityService, _loginService)); + if (_authenticator == null && _identityService != null) + { + // If someone has set an authenticator factory only use that, otherwise try the list of discovered factories. + if (_authenticatorFactory != null) + { + Authenticator authenticator = _authenticatorFactory.getAuthenticator(getServer(), ContextHandler.getCurrentContext(), + this, _identityService, _loginService); + + if (authenticator != null) + { + if (LOG.isDebugEnabled()) + LOG.debug("Created authenticator {} with {}", authenticator, _authenticatorFactory); + + setAuthenticator(authenticator); + } + } + else + { + for (Authenticator.Factory factory : getKnownAuthenticatorFactories()) + { + Authenticator authenticator = factory.getAuthenticator(getServer(), ContextHandler.getCurrentContext(), + this, _identityService, _loginService); + + if (authenticator != null) + { + if (LOG.isDebugEnabled()) + LOG.debug("Created authenticator {} with {}", authenticator, factory); + + setAuthenticator(authenticator); + break; + } + } + } + } if (_authenticator != null) _authenticator.setConfiguration(this);