make the dispatch feature work for core securityHandler
Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
parent
db5209e97a
commit
9208629e95
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.security;
|
||||
|
||||
import org.eclipse.jetty.server.Request;
|
||||
|
||||
public interface ServeAs
|
||||
{
|
||||
Request serveAs(Request request, String path);
|
||||
}
|
|
@ -40,6 +40,10 @@ import org.slf4j.LoggerFactory;
|
|||
/**
|
||||
* FORM Authenticator.
|
||||
*
|
||||
* <p>This authenticator implements form authentication will use dispatchers to
|
||||
* the login page if the {@link #__FORM_DISPATCH} init parameter is set to true.
|
||||
* Otherwise it will redirect.</p>
|
||||
*
|
||||
* <p>The form authenticator redirects unauthenticated requests to a log page
|
||||
* which should use a form to gather username/password from the user and send them
|
||||
* to the /j_security_check URI within the context. FormAuthentication uses
|
||||
|
@ -52,6 +56,8 @@ public class FormAuthenticator extends LoginAuthenticator
|
|||
|
||||
public static final String __FORM_LOGIN_PAGE = "org.eclipse.jetty.security.form_login_page";
|
||||
public static final String __FORM_ERROR_PAGE = "org.eclipse.jetty.security.form_error_page";
|
||||
public static final String __FORM_DISPATCH = "org.eclipse.jetty.security.dispatch";
|
||||
|
||||
public static final String __J_URI = "org.eclipse.jetty.security.form_URI";
|
||||
public static final String __J_POST = "org.eclipse.jetty.security.form_POST";
|
||||
public static final String __J_METHOD = "org.eclipse.jetty.security.form_METHOD";
|
||||
|
@ -64,24 +70,19 @@ public class FormAuthenticator extends LoginAuthenticator
|
|||
private String _formLoginPage;
|
||||
private String _formLoginPath;
|
||||
private boolean _alwaysSaveUri;
|
||||
private boolean _dispatch;
|
||||
|
||||
public FormAuthenticator()
|
||||
{
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public FormAuthenticator(String login, String error, boolean dispatch)
|
||||
{
|
||||
this(login, error);
|
||||
}
|
||||
|
||||
public FormAuthenticator(String login, String error)
|
||||
{
|
||||
this();
|
||||
if (login != null)
|
||||
setLoginPage(login);
|
||||
if (error != null)
|
||||
setErrorPage(error);
|
||||
_dispatch = dispatch;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -112,6 +113,9 @@ public class FormAuthenticator extends LoginAuthenticator
|
|||
String error = configuration.getParameter(FormAuthenticator.__FORM_ERROR_PAGE);
|
||||
if (error != null)
|
||||
setErrorPage(error);
|
||||
|
||||
String dispatch = configuration.getParameter(FormAuthenticator.__FORM_DISPATCH);
|
||||
_dispatch = dispatch == null ? _dispatch : Boolean.parseBoolean(dispatch);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -361,20 +365,53 @@ public class FormAuthenticator extends LoginAuthenticator
|
|||
return sendChallenge(request, response, callback);
|
||||
}
|
||||
|
||||
protected AuthenticationState dispatch(String path, Request request, Response response, Callback callback)
|
||||
{
|
||||
try
|
||||
{
|
||||
HttpURI.Mutable newUri = HttpURI.build(request.getHttpURI()).path(path);
|
||||
return new AuthenticationState.ServeAs(newUri)
|
||||
{
|
||||
@Override
|
||||
public Request wrap(Request request)
|
||||
{
|
||||
org.eclipse.jetty.security.ServeAs serveAs = Request.as(request, org.eclipse.jetty.security.ServeAs.class);
|
||||
if (serveAs != null)
|
||||
return serveAs.serveAs(request, path);
|
||||
return super.wrap(request);
|
||||
}
|
||||
};
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
Response.writeError(request, response, callback, t);
|
||||
return AuthenticationState.SEND_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
protected AuthenticationState sendError(Request request, Response response, Callback callback)
|
||||
{
|
||||
if (_formErrorPage == null)
|
||||
Response.writeError(request, response, callback, HttpStatus.FORBIDDEN_403);
|
||||
else if (_dispatch && getErrorPage() != null)
|
||||
return dispatch(_formErrorPage, request, response, callback);
|
||||
else
|
||||
Response.sendRedirect(request, response, callback, encodeURL(URIUtil.addPaths(request.getContext().getContextPath(), _formErrorPage), request), true);
|
||||
return AuthenticationState.SEND_FAILURE;
|
||||
}
|
||||
|
||||
protected AuthenticationState sendChallenge(Request request, Response response, Callback callback)
|
||||
{
|
||||
if (_dispatch)
|
||||
{
|
||||
return dispatch(_formLoginPage, request, response, callback);
|
||||
}
|
||||
else
|
||||
{
|
||||
Response.sendRedirect(request, response, callback, encodeURL(URIUtil.addPaths(request.getContext().getContextPath(), _formLoginPage), request), true);
|
||||
return AuthenticationState.SEND_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isJSecurityCheck(String uri)
|
||||
{
|
||||
|
|
|
@ -768,7 +768,7 @@ public interface Request extends Attributes, Content.Source
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T extends Request.Wrapper> T as(Request request, Class<T> type)
|
||||
static <T> T as(Request request, Class<T> type)
|
||||
{
|
||||
while (request instanceof Request.Wrapper wrapper)
|
||||
{
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.eclipse.jetty.http.HttpMethod;
|
|||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.http.UriCompliance;
|
||||
import org.eclipse.jetty.http.pathmap.MatchedResource;
|
||||
import org.eclipse.jetty.security.ServeAs;
|
||||
import org.eclipse.jetty.server.FormFields;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.Response;
|
||||
|
@ -53,7 +54,7 @@ import org.eclipse.jetty.util.Fields;
|
|||
* This class is single use only.
|
||||
* </p>
|
||||
*/
|
||||
public class ServletContextRequest extends ContextRequest implements ServletContextHandler.ServletRequestInfo
|
||||
public class ServletContextRequest extends ContextRequest implements ServletContextHandler.ServletRequestInfo, ServeAs
|
||||
{
|
||||
public static final String MULTIPART_CONFIG_ELEMENT = "org.eclipse.jetty.multipartConfig";
|
||||
static final int INPUT_NONE = 0;
|
||||
|
@ -117,6 +118,7 @@ public class ServletContextRequest extends ContextRequest implements ServletCont
|
|||
addIdleTimeoutListener(_servletChannel.getServletRequestState()::onIdleTimeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request serveAs(Request request, String path)
|
||||
{
|
||||
MatchedResource<ServletHandler.MappedServlet> matchedResource = getServletContextHandler().getServletHandler().getMatchedServlet(path);
|
||||
|
|
|
@ -13,41 +13,8 @@
|
|||
|
||||
package org.eclipse.jetty.ee10.servlet.security;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Locale;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpServletResponseWrapper;
|
||||
import org.eclipse.jetty.ee10.servlet.ServletContextRequest;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.security.AuthenticationState;
|
||||
import org.eclipse.jetty.security.authentication.SessionAuthentication;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.Response;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
|
||||
/**
|
||||
* FORM Authenticator.
|
||||
*
|
||||
* <p>This authenticator implements form authentication will use dispatchers to
|
||||
* the login page if the {@link #__FORM_DISPATCH} init parameter is set to true.
|
||||
* Otherwise it will redirect.</p>
|
||||
*
|
||||
* <p>The form authenticator redirects unauthenticated requests to a log page
|
||||
* which should use a form to gather username/password from the user and send them
|
||||
* to the /j_security_check URI within the context. FormAuthentication uses
|
||||
* {@link SessionAuthentication} to wrap Authentication results so that they
|
||||
* are associated with the session.</p>
|
||||
*/
|
||||
public class FormAuthenticator extends org.eclipse.jetty.security.authentication.FormAuthenticator
|
||||
{
|
||||
public static final String __FORM_DISPATCH = "org.eclipse.jetty.security.dispatch";
|
||||
|
||||
private boolean _dispatch;
|
||||
|
||||
public FormAuthenticator()
|
||||
{
|
||||
}
|
||||
|
@ -55,144 +22,5 @@ public class FormAuthenticator extends org.eclipse.jetty.security.authentication
|
|||
public FormAuthenticator(String login, String error, boolean dispatch)
|
||||
{
|
||||
super(login, error, dispatch);
|
||||
_dispatch = dispatch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConfiguration(Configuration configuration)
|
||||
{
|
||||
super.setConfiguration(configuration);
|
||||
|
||||
String dispatch = configuration.getParameter(FormAuthenticator.__FORM_DISPATCH);
|
||||
_dispatch = dispatch == null ? _dispatch : Boolean.parseBoolean(dispatch);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthenticationState sendError(Request request, Response response, Callback callback)
|
||||
{
|
||||
if (_dispatch && getErrorPage() != null)
|
||||
return dispatch(getErrorPage(), request, response, callback);
|
||||
else
|
||||
return super.sendError(request, response, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthenticationState sendChallenge(Request request, Response response, Callback callback)
|
||||
{
|
||||
if (_dispatch)
|
||||
return dispatch(getLoginPage(), request, response, callback);
|
||||
else
|
||||
return super.sendChallenge(request, response, callback);
|
||||
}
|
||||
|
||||
private AuthenticationState dispatch(String path, Request request, Response response, Callback callback)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Currently we do not attempt to wrap the request
|
||||
return new AuthenticationState.ServeAs(request.getHttpURI())
|
||||
{
|
||||
@Override
|
||||
public Request wrap(Request request)
|
||||
{
|
||||
ServletContextRequest servletContextRequest = Request.as(request, ServletContextRequest.class);
|
||||
if (servletContextRequest == null)
|
||||
return super.wrap(request);
|
||||
|
||||
return servletContextRequest.serveAs(request, path);
|
||||
}
|
||||
};
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
Response.writeError(request, response, callback, t);
|
||||
return AuthenticationState.SEND_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
protected static class FormRequest extends HttpServletRequestWrapper
|
||||
{
|
||||
public FormRequest(HttpServletRequest request)
|
||||
{
|
||||
super(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDateHeader(String name)
|
||||
{
|
||||
if (name.toLowerCase(Locale.ENGLISH).startsWith("if-"))
|
||||
return -1;
|
||||
return super.getDateHeader(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHeader(String name)
|
||||
{
|
||||
if (name.toLowerCase(Locale.ENGLISH).startsWith("if-"))
|
||||
return null;
|
||||
return super.getHeader(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getHeaderNames()
|
||||
{
|
||||
return Collections.enumeration(Collections.list(super.getHeaderNames()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getHeaders(String name)
|
||||
{
|
||||
if (name.toLowerCase(Locale.ENGLISH).startsWith("if-"))
|
||||
return Collections.<String>enumeration(Collections.<String>emptyList());
|
||||
return super.getHeaders(name);
|
||||
}
|
||||
}
|
||||
|
||||
protected static class FormResponse extends HttpServletResponseWrapper
|
||||
{
|
||||
public FormResponse(HttpServletResponse response)
|
||||
{
|
||||
super(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDateHeader(String name, long date)
|
||||
{
|
||||
if (notIgnored(name))
|
||||
super.addDateHeader(name, date);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addHeader(String name, String value)
|
||||
{
|
||||
if (notIgnored(name))
|
||||
super.addHeader(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDateHeader(String name, long date)
|
||||
{
|
||||
if (notIgnored(name))
|
||||
super.setDateHeader(name, date);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeader(String name, String value)
|
||||
{
|
||||
if (notIgnored(name))
|
||||
super.setHeader(name, value);
|
||||
}
|
||||
|
||||
private boolean notIgnored(String name)
|
||||
{
|
||||
if (HttpHeader.CACHE_CONTROL.is(name) ||
|
||||
HttpHeader.PRAGMA.is(name) ||
|
||||
HttpHeader.ETAG.is(name) ||
|
||||
HttpHeader.EXPIRES.is(name) ||
|
||||
HttpHeader.LAST_MODIFIED.is(name) ||
|
||||
HttpHeader.AGE.is(name))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue