diff --git a/README.md b/README.md index 2d529b0275a..969435deb35 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Documentation Project documentation is available on the Jetty Eclipse website. -- [http://www.eclipse.org/jetty/documentation](http://www.eclipse.org/jetty/documentation) +- [https://www.eclipse.org/jetty/documentation](https://www.eclipse.org/jetty/documentation) Building ======== @@ -45,4 +45,4 @@ It is possible to bypass tests by building with `mvn clean install -DskipTests`. Professional Services --------------------- -Expert advice and production support are available through [Webtide.com](http://webtide.com). +Expert advice and production support are available through [Webtide.com](https://webtide.com). diff --git a/VERSION.txt b/VERSION.txt index b5c40ca2bc7..471fef74d52 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -460,6 +460,11 @@ jetty-9.4.15.v20190215 - 15 February 2019 + 3350 Do not expect to be able to connect to https URLs with the HttpClient created from a parameterless constructor +jetty-9.3.28.v20191105 - 05 November 2019 + + 3989 Inform custom ManagedSelector of dead selector via optional + onFailedSelect() + + 4217 SslConnection.DecryptedEnpoint.flush eternal busy loop + jetty-9.3.27.v20190418 - 18 April 2019 + 3549 Directory Listing on Windows reveals Resource Base path + 3555 DefaultHandler Reveals Base Resource Path of each Context @@ -472,6 +477,9 @@ jetty-9.3.26.v20190403 - 03 April 2019 ForwardedRequestCustomizer + 3319 Allow reverse sort for directory listed files +jetty-9.2.29.v20191105 - 05 November 2019 + + 4217 SslConnection.DecryptedEnpoint.flush eternal busy loop + jetty-9.2.28.v20190418 - 18 April 2019 + 3549 Directory Listing on Windows reveals Resource Base path + 3555 DefaultHandler Reveals Base Resource Path of each Context diff --git a/jetty-jaspi/pom.xml b/jetty-jaspi/pom.xml index d4691812295..0d16ccb6974 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 48dcc6adaf1..928a51b0ca8 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 90569d68b0f..ed204799803 100644 --- a/jetty-security/pom.xml +++ b/jetty-security/pom.xml @@ -24,6 +24,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); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java index 541db3eb23b..88a23363b7d 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java @@ -27,11 +27,9 @@ import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.stream.Collectors; - import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -106,15 +104,23 @@ public class ErrorHandler extends AbstractHandler { if (errorDispatcher != null) { - errorDispatcher.error(request, response); - } - else - { - String message = (String)request.getAttribute(Dispatcher.ERROR_MESSAGE); - if (message == null) - message = baseRequest.getResponse().getReason(); - generateAcceptableResponse(baseRequest, request, response, response.getStatus(), message); + try + { + errorDispatcher.error(request, response); + return; + } + catch (ServletException e) + { + LOG.debug(e); + if (response.isCommitted()) + return; + } } + + String message = (String)request.getAttribute(Dispatcher.ERROR_MESSAGE); + if (message == null) + message = baseRequest.getResponse().getReason(); + generateAcceptableResponse(baseRequest, request, response, response.getStatus(), message); } finally {