Reformat code using spring-javaformat
Run `./gradlew format` to reformat all java files. Issue gh-8945
This commit is contained in:
@@ -31,6 +31,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public interface AuthenticationEntryPoint {
|
||||
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
@@ -44,12 +45,12 @@ public interface AuthenticationEntryPoint {
|
||||
* <p>
|
||||
* Implementations should modify the headers on the <code>ServletResponse</code> as
|
||||
* necessary to commence the authentication process.
|
||||
*
|
||||
* @param request that resulted in an <code>AuthenticationException</code>
|
||||
* @param response so that the user agent can begin authentication
|
||||
* @param authException that caused the invocation
|
||||
*
|
||||
*/
|
||||
void commence(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException authException) throws IOException, ServletException;
|
||||
void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
|
||||
throws IOException, ServletException;
|
||||
|
||||
}
|
||||
|
||||
@@ -45,8 +45,7 @@ public class DefaultRedirectStrategy implements RedirectStrategy {
|
||||
* information (HTTP or HTTPS), so will cause problems if a redirect is being
|
||||
* performed to change to HTTPS, for example.
|
||||
*/
|
||||
public void sendRedirect(HttpServletRequest request, HttpServletResponse response,
|
||||
String url) throws IOException {
|
||||
public void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url) throws IOException {
|
||||
String redirectUrl = calculateRedirectUrl(request.getContextPath(), url);
|
||||
redirectUrl = response.encodeRedirectURL(redirectUrl);
|
||||
|
||||
@@ -98,10 +97,11 @@ public class DefaultRedirectStrategy implements RedirectStrategy {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt>, if the redirection URL should be calculated
|
||||
* minus the protocol and context path (defaults to <tt>false</tt>).
|
||||
* Returns <tt>true</tt>, if the redirection URL should be calculated minus the
|
||||
* protocol and context path (defaults to <tt>false</tt>).
|
||||
*/
|
||||
protected boolean isContextRelative() {
|
||||
return contextRelative;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,12 +27,14 @@ import java.util.*;
|
||||
* Standard implementation of {@code SecurityFilterChain}.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public final class DefaultSecurityFilterChain implements SecurityFilterChain {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(DefaultSecurityFilterChain.class);
|
||||
|
||||
private final RequestMatcher requestMatcher;
|
||||
|
||||
private final List<Filter> filters;
|
||||
|
||||
public DefaultSecurityFilterChain(RequestMatcher requestMatcher, Filter... filters) {
|
||||
@@ -61,4 +63,5 @@ public final class DefaultSecurityFilterChain implements SecurityFilterChain {
|
||||
public String toString() {
|
||||
return "[ " + requestMatcher + ", " + filters + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -59,9 +59,9 @@ import java.util.*;
|
||||
* and a list of filters which should be applied to matching requests. Most applications
|
||||
* will only contain a single filter chain, and if you are using the namespace, you don't
|
||||
* have to set the chains explicitly. If you require finer-grained control, you can make
|
||||
* use of the {@code <filter-chain>} namespace element. This defines a URI pattern
|
||||
* and the list of filters (as comma-separated bean names) which should be applied to
|
||||
* requests which match the pattern. An example configuration might look like this:
|
||||
* use of the {@code <filter-chain>} namespace element. This defines a URI pattern and the
|
||||
* list of filters (as comma-separated bean names) which should be applied to requests
|
||||
* which match the pattern. An example configuration might look like this:
|
||||
*
|
||||
* <pre>
|
||||
* <bean id="myfilterChainProxy" class="org.springframework.security.web.FilterChainProxy">
|
||||
@@ -136,6 +136,7 @@ import java.util.*;
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class FilterChainProxy extends GenericFilterBean {
|
||||
|
||||
// ~ Static fields/initializers
|
||||
// =====================================================================================
|
||||
|
||||
@@ -144,8 +145,7 @@ public class FilterChainProxy extends GenericFilterBean {
|
||||
// ~ Instance fields
|
||||
// ================================================================================================
|
||||
|
||||
private final static String FILTER_APPLIED = FilterChainProxy.class.getName().concat(
|
||||
".APPLIED");
|
||||
private final static String FILTER_APPLIED = FilterChainProxy.class.getName().concat(".APPLIED");
|
||||
|
||||
private List<SecurityFilterChain> filterChains;
|
||||
|
||||
@@ -175,14 +175,15 @@ public class FilterChainProxy extends GenericFilterBean {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
boolean clearContext = request.getAttribute(FILTER_APPLIED) == null;
|
||||
if (clearContext) {
|
||||
try {
|
||||
request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
|
||||
doFilterInternal(request, response, chain);
|
||||
} catch (RequestRejectedException e) {
|
||||
}
|
||||
catch (RequestRejectedException e) {
|
||||
this.requestRejectedHandler.handle((HttpServletRequest) request, (HttpServletResponse) response, e);
|
||||
}
|
||||
finally {
|
||||
@@ -195,21 +196,18 @@ public class FilterChainProxy extends GenericFilterBean {
|
||||
}
|
||||
}
|
||||
|
||||
private void doFilterInternal(ServletRequest request, ServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
private void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
|
||||
FirewalledRequest fwRequest = firewall
|
||||
.getFirewalledRequest((HttpServletRequest) request);
|
||||
HttpServletResponse fwResponse = firewall
|
||||
.getFirewalledResponse((HttpServletResponse) response);
|
||||
FirewalledRequest fwRequest = firewall.getFirewalledRequest((HttpServletRequest) request);
|
||||
HttpServletResponse fwResponse = firewall.getFirewalledResponse((HttpServletResponse) response);
|
||||
|
||||
List<Filter> filters = getFilters(fwRequest);
|
||||
|
||||
if (filters == null || filters.size() == 0) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(UrlUtils.buildRequestUrl(fwRequest)
|
||||
+ (filters == null ? " has no matching filters"
|
||||
: " has an empty filter list"));
|
||||
+ (filters == null ? " has no matching filters" : " has an empty filter list"));
|
||||
}
|
||||
|
||||
fwRequest.reset();
|
||||
@@ -225,7 +223,6 @@ public class FilterChainProxy extends GenericFilterBean {
|
||||
|
||||
/**
|
||||
* Returns the first filter chain matching the supplied URL.
|
||||
*
|
||||
* @param request the request to match
|
||||
* @return an ordered array of Filters defining the filter chain
|
||||
*/
|
||||
@@ -241,13 +238,11 @@ public class FilterChainProxy extends GenericFilterBean {
|
||||
|
||||
/**
|
||||
* Convenience method, mainly for testing.
|
||||
*
|
||||
* @param url the URL
|
||||
* @return matching filter list
|
||||
*/
|
||||
public List<Filter> getFilters(String url) {
|
||||
return getFilters(firewall.getFirewalledRequest((new FilterInvocation(url, "GET")
|
||||
.getRequest())));
|
||||
return getFilters(firewall.getFirewalledRequest((new FilterInvocation(url, "GET").getRequest())));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -261,7 +256,6 @@ public class FilterChainProxy extends GenericFilterBean {
|
||||
/**
|
||||
* Used (internally) to specify a validation strategy for the filters in each
|
||||
* configured chain.
|
||||
*
|
||||
* @param filterChainValidator the validator instance which will be invoked on during
|
||||
* initialization to check the {@code FilterChainProxy} instance.
|
||||
*/
|
||||
@@ -273,7 +267,6 @@ public class FilterChainProxy extends GenericFilterBean {
|
||||
* Sets the "firewall" implementation which will be used to validate and wrap (or
|
||||
* potentially reject) the incoming requests. The default implementation should be
|
||||
* satisfactory for most requirements.
|
||||
*
|
||||
* @param firewall
|
||||
*/
|
||||
public void setFirewall(HttpFirewall firewall) {
|
||||
@@ -281,7 +274,8 @@ public class FilterChainProxy extends GenericFilterBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link RequestRejectedHandler} to be used for requests rejected by the firewall.
|
||||
* Sets the {@link RequestRejectedHandler} to be used for requests rejected by the
|
||||
* firewall.
|
||||
*
|
||||
* @since 5.2
|
||||
* @param requestRejectedHandler the {@link RequestRejectedHandler}
|
||||
@@ -310,14 +304,19 @@ public class FilterChainProxy extends GenericFilterBean {
|
||||
* the additional internal list of filters which match the request.
|
||||
*/
|
||||
private static class VirtualFilterChain implements FilterChain {
|
||||
|
||||
private final FilterChain originalChain;
|
||||
|
||||
private final List<Filter> additionalFilters;
|
||||
|
||||
private final FirewalledRequest firewalledRequest;
|
||||
|
||||
private final int size;
|
||||
|
||||
private int currentPosition = 0;
|
||||
|
||||
private VirtualFilterChain(FirewalledRequest firewalledRequest,
|
||||
FilterChain chain, List<Filter> additionalFilters) {
|
||||
private VirtualFilterChain(FirewalledRequest firewalledRequest, FilterChain chain,
|
||||
List<Filter> additionalFilters) {
|
||||
this.originalChain = chain;
|
||||
this.additionalFilters = additionalFilters;
|
||||
this.size = additionalFilters.size();
|
||||
@@ -325,8 +324,7 @@ public class FilterChainProxy extends GenericFilterBean {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response)
|
||||
throws IOException, ServletException {
|
||||
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
|
||||
if (currentPosition == size) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(UrlUtils.buildRequestUrl(firewalledRequest)
|
||||
@@ -344,25 +342,29 @@ public class FilterChainProxy extends GenericFilterBean {
|
||||
Filter nextFilter = additionalFilters.get(currentPosition - 1);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(UrlUtils.buildRequestUrl(firewalledRequest)
|
||||
+ " at position " + currentPosition + " of " + size
|
||||
+ " in additional filter chain; firing Filter: '"
|
||||
logger.debug(UrlUtils.buildRequestUrl(firewalledRequest) + " at position " + currentPosition
|
||||
+ " of " + size + " in additional filter chain; firing Filter: '"
|
||||
+ nextFilter.getClass().getSimpleName() + "'");
|
||||
}
|
||||
|
||||
nextFilter.doFilter(request, response, this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public interface FilterChainValidator {
|
||||
|
||||
void validate(FilterChainProxy filterChainProxy);
|
||||
|
||||
}
|
||||
|
||||
private static class NullFilterChainValidator implements FilterChainValidator {
|
||||
|
||||
@Override
|
||||
public void validate(FilterChainProxy filterChainProxy) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ import org.springframework.security.web.util.UrlUtils;
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class FilterInvocation {
|
||||
|
||||
// ~ Static fields
|
||||
// ==================================================================================================
|
||||
static final FilterChain DUMMY_CHAIN = (req, res) -> {
|
||||
@@ -63,14 +64,15 @@ public class FilterInvocation {
|
||||
// ================================================================================================
|
||||
|
||||
private FilterChain chain;
|
||||
|
||||
private HttpServletRequest request;
|
||||
|
||||
private HttpServletResponse response;
|
||||
|
||||
// ~ Constructors
|
||||
// ===================================================================================================
|
||||
|
||||
public FilterInvocation(ServletRequest request, ServletResponse response,
|
||||
FilterChain chain) {
|
||||
public FilterInvocation(ServletRequest request, ServletResponse response, FilterChain chain) {
|
||||
if ((request == null) || (response == null) || (chain == null)) {
|
||||
throw new IllegalArgumentException("Cannot pass null values to constructor");
|
||||
}
|
||||
@@ -88,16 +90,14 @@ public class FilterInvocation {
|
||||
this(contextPath, servletPath, null, null, method);
|
||||
}
|
||||
|
||||
public FilterInvocation(String contextPath, String servletPath, String pathInfo,
|
||||
String query, String method) {
|
||||
public FilterInvocation(String contextPath, String servletPath, String pathInfo, String query, String method) {
|
||||
DummyRequest request = new DummyRequest();
|
||||
if (contextPath == null) {
|
||||
contextPath = "/cp";
|
||||
}
|
||||
request.setContextPath(contextPath);
|
||||
request.setServletPath(servletPath);
|
||||
request.setRequestURI(
|
||||
contextPath + servletPath + (pathInfo == null ? "" : pathInfo));
|
||||
request.setRequestURI(contextPath + servletPath + (pathInfo == null ? "" : pathInfo));
|
||||
request.setPathInfo(pathInfo);
|
||||
request.setQueryString(query);
|
||||
request.setMethod(method);
|
||||
@@ -116,7 +116,6 @@ public class FilterInvocation {
|
||||
* <p>
|
||||
* The returned URL does <b>not</b> reflect the port number determined from a
|
||||
* {@link org.springframework.security.web.PortResolver}.
|
||||
*
|
||||
* @return the full URL of this request
|
||||
*/
|
||||
public String getFullRequestUrl() {
|
||||
@@ -133,7 +132,6 @@ public class FilterInvocation {
|
||||
|
||||
/**
|
||||
* Obtains the web application-specific fragment of the URL.
|
||||
*
|
||||
* @return the URL, excluding any server name, context path or servlet path
|
||||
*/
|
||||
public String getRequestUrl() {
|
||||
@@ -152,21 +150,29 @@ public class FilterInvocation {
|
||||
public String toString() {
|
||||
return "FilterInvocation: URL: " + getRequestUrl();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class DummyRequest extends HttpServletRequestWrapper {
|
||||
private static final HttpServletRequest UNSUPPORTED_REQUEST = (HttpServletRequest) Proxy
|
||||
.newProxyInstance(DummyRequest.class.getClassLoader(),
|
||||
new Class[] { HttpServletRequest.class },
|
||||
new UnsupportedOperationExceptionInvocationHandler());
|
||||
|
||||
private static final HttpServletRequest UNSUPPORTED_REQUEST = (HttpServletRequest) Proxy.newProxyInstance(
|
||||
DummyRequest.class.getClassLoader(), new Class[] { HttpServletRequest.class },
|
||||
new UnsupportedOperationExceptionInvocationHandler());
|
||||
|
||||
private String requestURI;
|
||||
|
||||
private String contextPath = "";
|
||||
|
||||
private String servletPath;
|
||||
|
||||
private String pathInfo;
|
||||
|
||||
private String queryString;
|
||||
|
||||
private String method;
|
||||
|
||||
private final HttpHeaders headers = new HttpHeaders();
|
||||
|
||||
private final Map<String, String[]> parameters = new LinkedHashMap<>();
|
||||
|
||||
DummyRequest() {
|
||||
@@ -258,7 +264,7 @@ class DummyRequest extends HttpServletRequestWrapper {
|
||||
@Override
|
||||
public int getIntHeader(String name) {
|
||||
String value = this.headers.getFirst(name);
|
||||
if (value == null ) {
|
||||
if (value == null) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
@@ -294,9 +300,11 @@ class DummyRequest extends HttpServletRequestWrapper {
|
||||
public void setParameter(String name, String... values) {
|
||||
this.parameters.put(name, values);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
final class UnsupportedOperationExceptionInvocationHandler implements InvocationHandler {
|
||||
|
||||
private static final float JAVA_VERSION = Float.parseFloat(System.getProperty("java.class.version", "52"));
|
||||
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
@@ -311,14 +319,9 @@ final class UnsupportedOperationExceptionInvocationHandler implements Invocation
|
||||
return invokeDefaultMethodForJdk8(proxy, method, args);
|
||||
}
|
||||
return MethodHandles.lookup()
|
||||
.findSpecial(
|
||||
method.getDeclaringClass(),
|
||||
method.getName(),
|
||||
MethodType.methodType(method.getReturnType(), new Class[0]),
|
||||
method.getDeclaringClass()
|
||||
)
|
||||
.bindTo(proxy)
|
||||
.invokeWithArguments(args);
|
||||
.findSpecial(method.getDeclaringClass(), method.getName(),
|
||||
MethodType.methodType(method.getReturnType(), new Class[0]), method.getDeclaringClass())
|
||||
.bindTo(proxy).invokeWithArguments(args);
|
||||
}
|
||||
|
||||
private Object invokeDefaultMethodForJdk8(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
@@ -326,14 +329,12 @@ final class UnsupportedOperationExceptionInvocationHandler implements Invocation
|
||||
constructor.setAccessible(true);
|
||||
|
||||
Class<?> clazz = method.getDeclaringClass();
|
||||
return constructor.newInstance(clazz)
|
||||
.in(clazz)
|
||||
.unreflectSpecial(method, clazz)
|
||||
.bindTo(proxy)
|
||||
return constructor.newInstance(clazz).in(clazz).unreflectSpecial(method, clazz).bindTo(proxy)
|
||||
.invokeWithArguments(args);
|
||||
}
|
||||
|
||||
private boolean isJdk8OrEarlier() {
|
||||
return JAVA_VERSION <= 52;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ package org.springframework.security.web;
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public interface PortMapper {
|
||||
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
@@ -31,9 +32,7 @@ public interface PortMapper {
|
||||
* <P>
|
||||
* Returns <code>null</code> if unknown.
|
||||
* </p>
|
||||
*
|
||||
* @param httpsPort
|
||||
*
|
||||
* @return the HTTP port or <code>null</code> if unknown
|
||||
*/
|
||||
Integer lookupHttpPort(Integer httpsPort);
|
||||
@@ -43,10 +42,9 @@ public interface PortMapper {
|
||||
* <P>
|
||||
* Returns <code>null</code> if unknown.
|
||||
* </p>
|
||||
*
|
||||
* @param httpPort
|
||||
*
|
||||
* @return the HTTPS port or <code>null</code> if unknown
|
||||
*/
|
||||
Integer lookupHttpsPort(Integer httpPort);
|
||||
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.util.Assert;
|
||||
* @author colin sampaleanu
|
||||
*/
|
||||
public class PortMapperImpl implements PortMapper {
|
||||
|
||||
// ~ Instance fields
|
||||
// ================================================================================================
|
||||
|
||||
@@ -84,19 +85,16 @@ public class PortMapperImpl implements PortMapper {
|
||||
* </map>
|
||||
* </property>
|
||||
* </pre>
|
||||
*
|
||||
* @param newMappings A Map consisting of String keys and String values, where for
|
||||
* each entry the key is the string representation of an integer HTTP port number, and
|
||||
* the value is the string representation of the corresponding integer HTTPS port
|
||||
* number.
|
||||
*
|
||||
* @throws IllegalArgumentException if input map does not consist of String keys and
|
||||
* values, each representing an integer port number in the range 1-65535 for that
|
||||
* mapping.
|
||||
*/
|
||||
public void setPortMappings(Map<String, String> newMappings) {
|
||||
Assert.notNull(newMappings,
|
||||
"A valid list of HTTPS port mappings must be provided");
|
||||
Assert.notNull(newMappings, "A valid list of HTTPS port mappings must be provided");
|
||||
|
||||
this.httpsPortMappings.clear();
|
||||
|
||||
@@ -104,11 +102,9 @@ public class PortMapperImpl implements PortMapper {
|
||||
Integer httpPort = Integer.valueOf(entry.getKey());
|
||||
Integer httpsPort = Integer.valueOf(entry.getValue());
|
||||
|
||||
if ((httpPort < 1) || (httpPort > 65535)
|
||||
|| (httpsPort < 1) || (httpsPort > 65535)) {
|
||||
if ((httpPort < 1) || (httpPort > 65535) || (httpsPort < 1) || (httpsPort > 65535)) {
|
||||
throw new IllegalArgumentException(
|
||||
"one or both ports out of legal range: " + httpPort + ", "
|
||||
+ httpsPort);
|
||||
"one or both ports out of legal range: " + httpPort + ", " + httpsPort);
|
||||
}
|
||||
|
||||
this.httpsPortMappings.put(httpPort, httpsPort);
|
||||
@@ -118,4 +114,5 @@ public class PortMapperImpl implements PortMapper {
|
||||
throw new IllegalArgumentException("must map at least one port");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,15 +30,15 @@ import javax.servlet.ServletRequest;
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public interface PortResolver {
|
||||
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
/**
|
||||
* Indicates the port the <code>ServletRequest</code> was received on.
|
||||
*
|
||||
* @param request that the method should lookup the port for
|
||||
*
|
||||
* @return the port the request was received on
|
||||
*/
|
||||
int getServerPort(ServletRequest request);
|
||||
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import javax.servlet.ServletRequest;
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public class PortResolverImpl implements PortResolver {
|
||||
|
||||
// ~ Instance fields
|
||||
// ================================================================================================
|
||||
|
||||
@@ -73,4 +74,5 @@ public class PortResolverImpl implements PortResolver {
|
||||
Assert.notNull(portMapper, "portMapper cannot be null");
|
||||
this.portMapper = portMapper;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,6 +35,6 @@ public interface RedirectStrategy {
|
||||
* @param response the response to redirect
|
||||
* @param url the target URL to redirect to, for example "/login"
|
||||
*/
|
||||
void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url)
|
||||
throws IOException;
|
||||
void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url) throws IOException;
|
||||
|
||||
}
|
||||
|
||||
@@ -25,9 +25,7 @@ import java.util.*;
|
||||
* <p>
|
||||
* Used to configure a {@code FilterChainProxy}.
|
||||
*
|
||||
*
|
||||
* @author Luke Taylor
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public interface SecurityFilterChain {
|
||||
@@ -35,4 +33,5 @@ public interface SecurityFilterChain {
|
||||
boolean matches(HttpServletRequest request);
|
||||
|
||||
List<Filter> getFilters();
|
||||
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
|
||||
* @since 3.0.3
|
||||
*/
|
||||
public final class WebAttributes {
|
||||
|
||||
/**
|
||||
* Used to cache an {@code AccessDeniedException} in the request for rendering.
|
||||
*
|
||||
@@ -47,6 +48,7 @@ public final class WebAttributes {
|
||||
* @see WebInvocationPrivilegeEvaluator
|
||||
* @since 3.1.3
|
||||
*/
|
||||
public static final String WEB_INVOCATION_PRIVILEGE_EVALUATOR_ATTRIBUTE = WebAttributes.class
|
||||
.getName() + ".WEB_INVOCATION_PRIVILEGE_EVALUATOR_ATTRIBUTE";
|
||||
public static final String WEB_INVOCATION_PRIVILEGE_EVALUATOR_ATTRIBUTE = WebAttributes.class.getName()
|
||||
+ ".WEB_INVOCATION_PRIVILEGE_EVALUATOR_ATTRIBUTE";
|
||||
|
||||
}
|
||||
|
||||
@@ -31,20 +31,19 @@ import javax.servlet.http.HttpServletResponse;
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public interface AccessDeniedHandler {
|
||||
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
/**
|
||||
* Handles an access denied failure.
|
||||
*
|
||||
* @param request that resulted in an <code>AccessDeniedException</code>
|
||||
* @param response so that the user agent can be advised of the failure
|
||||
* @param accessDeniedException that caused the invocation
|
||||
*
|
||||
* @throws IOException in the event of an IOException
|
||||
* @throws ServletException in the event of a ServletException
|
||||
*/
|
||||
void handle(HttpServletRequest request, HttpServletResponse response,
|
||||
AccessDeniedException accessDeniedException) throws IOException,
|
||||
ServletException;
|
||||
void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException)
|
||||
throws IOException, ServletException;
|
||||
|
||||
}
|
||||
|
||||
+5
-8
@@ -43,6 +43,7 @@ import org.springframework.security.web.WebAttributes;
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
|
||||
|
||||
// ~ Static fields/initializers
|
||||
// =====================================================================================
|
||||
|
||||
@@ -57,13 +58,11 @@ public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
|
||||
// ========================================================================================================
|
||||
|
||||
public void handle(HttpServletRequest request, HttpServletResponse response,
|
||||
AccessDeniedException accessDeniedException) throws IOException,
|
||||
ServletException {
|
||||
AccessDeniedException accessDeniedException) throws IOException, ServletException {
|
||||
if (!response.isCommitted()) {
|
||||
if (errorPage != null) {
|
||||
// Put exception into request scope (perhaps of use to a view)
|
||||
request.setAttribute(WebAttributes.ACCESS_DENIED_403,
|
||||
accessDeniedException);
|
||||
request.setAttribute(WebAttributes.ACCESS_DENIED_403, accessDeniedException);
|
||||
|
||||
// Set the 403 status code.
|
||||
response.setStatus(HttpStatus.FORBIDDEN.value());
|
||||
@@ -73,8 +72,7 @@ public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
|
||||
dispatcher.forward(request, response);
|
||||
}
|
||||
else {
|
||||
response.sendError(HttpStatus.FORBIDDEN.value(),
|
||||
HttpStatus.FORBIDDEN.getReasonPhrase());
|
||||
response.sendError(HttpStatus.FORBIDDEN.value(), HttpStatus.FORBIDDEN.getReasonPhrase());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,9 +80,7 @@ public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
|
||||
/**
|
||||
* The error page to use. Must begin with a "/" and is interpreted relative to the
|
||||
* current context root.
|
||||
*
|
||||
* @param errorPage the dispatcher path to display
|
||||
*
|
||||
* @throws IllegalArgumentException if the argument doesn't comply with the above
|
||||
* limitations
|
||||
*/
|
||||
@@ -95,4 +91,5 @@ public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
|
||||
|
||||
this.errorPage = errorPage;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
-18
@@ -34,13 +34,12 @@ import org.springframework.util.Assert;
|
||||
* @author Luke Taylor
|
||||
* @since 3.0
|
||||
*/
|
||||
public class DefaultWebInvocationPrivilegeEvaluator implements
|
||||
WebInvocationPrivilegeEvaluator {
|
||||
public class DefaultWebInvocationPrivilegeEvaluator implements WebInvocationPrivilegeEvaluator {
|
||||
|
||||
// ~ Static fields/initializers
|
||||
// =====================================================================================
|
||||
|
||||
protected static final Log logger = LogFactory
|
||||
.getLog(DefaultWebInvocationPrivilegeEvaluator.class);
|
||||
protected static final Log logger = LogFactory.getLog(DefaultWebInvocationPrivilegeEvaluator.class);
|
||||
|
||||
// ~ Instance fields
|
||||
// ================================================================================================
|
||||
@@ -50,11 +49,9 @@ public class DefaultWebInvocationPrivilegeEvaluator implements
|
||||
// ~ Constructors
|
||||
// ===================================================================================================
|
||||
|
||||
public DefaultWebInvocationPrivilegeEvaluator(
|
||||
AbstractSecurityInterceptor securityInterceptor) {
|
||||
public DefaultWebInvocationPrivilegeEvaluator(AbstractSecurityInterceptor securityInterceptor) {
|
||||
Assert.notNull(securityInterceptor, "SecurityInterceptor cannot be null");
|
||||
Assert.isTrue(
|
||||
FilterInvocation.class.equals(securityInterceptor.getSecureObjectClass()),
|
||||
Assert.isTrue(FilterInvocation.class.equals(securityInterceptor.getSecureObjectClass()),
|
||||
"AbstractSecurityInterceptor does not support FilterInvocations");
|
||||
Assert.notNull(securityInterceptor.getAccessDecisionManager(),
|
||||
"AbstractSecurityInterceptor must provide a non-null AccessDecisionManager");
|
||||
@@ -68,7 +65,6 @@ public class DefaultWebInvocationPrivilegeEvaluator implements
|
||||
/**
|
||||
* Determines whether the user represented by the supplied <tt>Authentication</tt>
|
||||
* object is allowed to invoke the supplied URI.
|
||||
*
|
||||
* @param uri the URI excluding the context path (a default context path setting will
|
||||
* be used)
|
||||
*/
|
||||
@@ -85,7 +81,6 @@ public class DefaultWebInvocationPrivilegeEvaluator implements
|
||||
* metadata applies to a given request URI, so generally the <code>contextPath</code>
|
||||
* is unimportant unless you are using a custom
|
||||
* <code>FilterInvocationSecurityMetadataSource</code>.
|
||||
*
|
||||
* @param uri the URI excluding the context path
|
||||
* @param contextPath the context path (may be null, in which case a default value
|
||||
* will be used).
|
||||
@@ -94,13 +89,11 @@ public class DefaultWebInvocationPrivilegeEvaluator implements
|
||||
* be used in evaluation whether access should be granted.
|
||||
* @return true if access is allowed, false if denied
|
||||
*/
|
||||
public boolean isAllowed(String contextPath, String uri, String method,
|
||||
Authentication authentication) {
|
||||
public boolean isAllowed(String contextPath, String uri, String method, Authentication authentication) {
|
||||
Assert.notNull(uri, "uri parameter is required");
|
||||
|
||||
FilterInvocation fi = new FilterInvocation(contextPath, uri, method);
|
||||
Collection<ConfigAttribute> attrs = securityInterceptor
|
||||
.obtainSecurityMetadataSource().getAttributes(fi);
|
||||
Collection<ConfigAttribute> attrs = securityInterceptor.obtainSecurityMetadataSource().getAttributes(fi);
|
||||
|
||||
if (attrs == null) {
|
||||
if (securityInterceptor.isRejectPublicInvocations()) {
|
||||
@@ -115,13 +108,11 @@ public class DefaultWebInvocationPrivilegeEvaluator implements
|
||||
}
|
||||
|
||||
try {
|
||||
securityInterceptor.getAccessDecisionManager().decide(authentication, fi,
|
||||
attrs);
|
||||
securityInterceptor.getAccessDecisionManager().decide(authentication, fi, attrs);
|
||||
}
|
||||
catch (AccessDeniedException unauthorized) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(fi.toString() + " denied for " + authentication.toString(),
|
||||
unauthorized);
|
||||
logger.debug(fi.toString() + " denied for " + authentication.toString(), unauthorized);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -129,4 +120,5 @@ public class DefaultWebInvocationPrivilegeEvaluator implements
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-5
@@ -36,13 +36,13 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
*/
|
||||
public final class DelegatingAccessDeniedHandler implements AccessDeniedHandler {
|
||||
|
||||
private final LinkedHashMap<Class<? extends AccessDeniedException>, AccessDeniedHandler> handlers;
|
||||
|
||||
private final AccessDeniedHandler defaultHandler;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param handlers a map of the {@link AccessDeniedException} class to the
|
||||
* {@link AccessDeniedHandler} that should be used. Each is considered in the order
|
||||
* they are specified and only the first {@link AccessDeniedHandler} is ued.
|
||||
@@ -59,10 +59,8 @@ public final class DelegatingAccessDeniedHandler implements AccessDeniedHandler
|
||||
}
|
||||
|
||||
public void handle(HttpServletRequest request, HttpServletResponse response,
|
||||
AccessDeniedException accessDeniedException) throws IOException,
|
||||
ServletException {
|
||||
for (Entry<Class<? extends AccessDeniedException>, AccessDeniedHandler> entry : handlers
|
||||
.entrySet()) {
|
||||
AccessDeniedException accessDeniedException) throws IOException, ServletException {
|
||||
for (Entry<Class<? extends AccessDeniedException>, AccessDeniedHandler> entry : handlers.entrySet()) {
|
||||
Class<? extends AccessDeniedException> handlerClass = entry.getKey();
|
||||
if (handlerClass.isAssignableFrom(accessDeniedException.getClass())) {
|
||||
AccessDeniedHandler handler = entry.getValue();
|
||||
|
||||
+33
-42
@@ -58,13 +58,15 @@ import java.io.IOException;
|
||||
* <code>authenticationEntryPoint</code> will be launched. If they are not an anonymous
|
||||
* user, the filter will delegate to the
|
||||
* {@link org.springframework.security.web.access.AccessDeniedHandler}. By default the
|
||||
* filter will use {@link org.springframework.security.web.access.AccessDeniedHandlerImpl}.
|
||||
* filter will use
|
||||
* {@link org.springframework.security.web.access.AccessDeniedHandlerImpl}.
|
||||
* <p>
|
||||
* To use this filter, it is necessary to specify the following properties:
|
||||
* <ul>
|
||||
* <li><code>authenticationEntryPoint</code> indicates the handler that should commence
|
||||
* the authentication process if an <code>AuthenticationException</code> is detected. Note
|
||||
* that this may also switch the current protocol from http to https for an SSL login.</li>
|
||||
* that this may also switch the current protocol from http to https for an SSL
|
||||
* login.</li>
|
||||
* <li><tt>requestCache</tt> determines the strategy used to save a request during the
|
||||
* authentication process in order that it may be retrieved and reused once the user has
|
||||
* authenticated. The default implementation is {@link HttpSessionRequestCache}.</li>
|
||||
@@ -79,8 +81,11 @@ public class ExceptionTranslationFilter extends GenericFilterBean {
|
||||
// ================================================================================================
|
||||
|
||||
private AccessDeniedHandler accessDeniedHandler = new AccessDeniedHandlerImpl();
|
||||
|
||||
private AuthenticationEntryPoint authenticationEntryPoint;
|
||||
|
||||
private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
|
||||
|
||||
private ThrowableAnalyzer throwableAnalyzer = new DefaultThrowableAnalyzer();
|
||||
|
||||
private RequestCache requestCache = new HttpSessionRequestCache();
|
||||
@@ -91,10 +96,8 @@ public class ExceptionTranslationFilter extends GenericFilterBean {
|
||||
this(authenticationEntryPoint, new HttpSessionRequestCache());
|
||||
}
|
||||
|
||||
public ExceptionTranslationFilter(AuthenticationEntryPoint authenticationEntryPoint,
|
||||
RequestCache requestCache) {
|
||||
Assert.notNull(authenticationEntryPoint,
|
||||
"authenticationEntryPoint cannot be null");
|
||||
public ExceptionTranslationFilter(AuthenticationEntryPoint authenticationEntryPoint, RequestCache requestCache) {
|
||||
Assert.notNull(authenticationEntryPoint, "authenticationEntryPoint cannot be null");
|
||||
Assert.notNull(requestCache, "requestCache cannot be null");
|
||||
this.authenticationEntryPoint = authenticationEntryPoint;
|
||||
this.requestCache = requestCache;
|
||||
@@ -105,8 +108,7 @@ public class ExceptionTranslationFilter extends GenericFilterBean {
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
Assert.notNull(authenticationEntryPoint,
|
||||
"authenticationEntryPoint must be specified");
|
||||
Assert.notNull(authenticationEntryPoint, "authenticationEntryPoint must be specified");
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
|
||||
@@ -129,13 +131,15 @@ public class ExceptionTranslationFilter extends GenericFilterBean {
|
||||
.getFirstThrowableOfType(AuthenticationException.class, causeChain);
|
||||
|
||||
if (ase == null) {
|
||||
ase = (AccessDeniedException) throwableAnalyzer.getFirstThrowableOfType(
|
||||
AccessDeniedException.class, causeChain);
|
||||
ase = (AccessDeniedException) throwableAnalyzer.getFirstThrowableOfType(AccessDeniedException.class,
|
||||
causeChain);
|
||||
}
|
||||
|
||||
if (ase != null) {
|
||||
if (response.isCommitted()) {
|
||||
throw new ServletException("Unable to handle the Spring Security Exception because the response is already committed.", ex);
|
||||
throw new ServletException(
|
||||
"Unable to handle the Spring Security Exception because the response is already committed.",
|
||||
ex);
|
||||
}
|
||||
handleSpringSecurityException(request, response, chain, ase);
|
||||
}
|
||||
@@ -163,46 +167,35 @@ public class ExceptionTranslationFilter extends GenericFilterBean {
|
||||
return authenticationTrustResolver;
|
||||
}
|
||||
|
||||
private void handleSpringSecurityException(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain chain, RuntimeException exception)
|
||||
throws IOException, ServletException {
|
||||
private void handleSpringSecurityException(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain chain, RuntimeException exception) throws IOException, ServletException {
|
||||
if (exception instanceof AuthenticationException) {
|
||||
logger.debug(
|
||||
"Authentication exception occurred; redirecting to authentication entry point",
|
||||
exception);
|
||||
logger.debug("Authentication exception occurred; redirecting to authentication entry point", exception);
|
||||
|
||||
sendStartAuthentication(request, response, chain,
|
||||
(AuthenticationException) exception);
|
||||
sendStartAuthentication(request, response, chain, (AuthenticationException) exception);
|
||||
}
|
||||
else if (exception instanceof AccessDeniedException) {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (authenticationTrustResolver.isAnonymous(authentication) || authenticationTrustResolver.isRememberMe(authentication)) {
|
||||
logger.debug(
|
||||
"Access is denied (user is " + (authenticationTrustResolver.isAnonymous(authentication) ? "anonymous" : "not fully authenticated") + "); redirecting to authentication entry point",
|
||||
if (authenticationTrustResolver.isAnonymous(authentication)
|
||||
|| authenticationTrustResolver.isRememberMe(authentication)) {
|
||||
logger.debug("Access is denied (user is " + (authenticationTrustResolver.isAnonymous(authentication)
|
||||
? "anonymous" : "not fully authenticated") + "); redirecting to authentication entry point",
|
||||
exception);
|
||||
|
||||
sendStartAuthentication(
|
||||
request,
|
||||
response,
|
||||
chain,
|
||||
sendStartAuthentication(request, response, chain,
|
||||
new InsufficientAuthenticationException(
|
||||
messages.getMessage(
|
||||
"ExceptionTranslationFilter.insufficientAuthentication",
|
||||
"Full authentication is required to access this resource")));
|
||||
messages.getMessage("ExceptionTranslationFilter.insufficientAuthentication",
|
||||
"Full authentication is required to access this resource")));
|
||||
}
|
||||
else {
|
||||
logger.debug(
|
||||
"Access is denied (user is not anonymous); delegating to AccessDeniedHandler",
|
||||
exception);
|
||||
logger.debug("Access is denied (user is not anonymous); delegating to AccessDeniedHandler", exception);
|
||||
|
||||
accessDeniedHandler.handle(request, response,
|
||||
(AccessDeniedException) exception);
|
||||
accessDeniedHandler.handle(request, response, (AccessDeniedException) exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void sendStartAuthentication(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain chain,
|
||||
protected void sendStartAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
|
||||
AuthenticationException reason) throws ServletException, IOException {
|
||||
// SEC-112: Clear the SecurityContextHolder's Authentication, as the
|
||||
// existing Authentication is no longer considered valid
|
||||
@@ -217,10 +210,8 @@ public class ExceptionTranslationFilter extends GenericFilterBean {
|
||||
this.accessDeniedHandler = accessDeniedHandler;
|
||||
}
|
||||
|
||||
public void setAuthenticationTrustResolver(
|
||||
AuthenticationTrustResolver authenticationTrustResolver) {
|
||||
Assert.notNull(authenticationTrustResolver,
|
||||
"authenticationTrustResolver must not be null");
|
||||
public void setAuthenticationTrustResolver(AuthenticationTrustResolver authenticationTrustResolver) {
|
||||
Assert.notNull(authenticationTrustResolver, "authenticationTrustResolver must not be null");
|
||||
this.authenticationTrustResolver = authenticationTrustResolver;
|
||||
}
|
||||
|
||||
@@ -234,6 +225,7 @@ public class ExceptionTranslationFilter extends GenericFilterBean {
|
||||
* unwrapping <code>ServletException</code>s.
|
||||
*/
|
||||
private static final class DefaultThrowableAnalyzer extends ThrowableAnalyzer {
|
||||
|
||||
/**
|
||||
* @see org.springframework.security.web.util.ThrowableAnalyzer#initExtractorMap()
|
||||
*/
|
||||
@@ -241,8 +233,7 @@ public class ExceptionTranslationFilter extends GenericFilterBean {
|
||||
super.initExtractorMap();
|
||||
|
||||
registerExtractor(ServletException.class, throwable -> {
|
||||
ThrowableAnalyzer.verifyThrowableHierarchy(throwable,
|
||||
ServletException.class);
|
||||
ThrowableAnalyzer.verifyThrowableHierarchy(throwable, ServletException.class);
|
||||
return ((ServletException) throwable).getRootCause();
|
||||
});
|
||||
}
|
||||
|
||||
+7
-10
@@ -36,21 +36,20 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
*/
|
||||
public final class RequestMatcherDelegatingAccessDeniedHandler implements AccessDeniedHandler {
|
||||
|
||||
private final LinkedHashMap<RequestMatcher, AccessDeniedHandler> handlers;
|
||||
|
||||
private final AccessDeniedHandler defaultHandler;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param handlers a map of {@link RequestMatcher}s to
|
||||
* {@link AccessDeniedHandler}s that should be used. Each is considered in the order
|
||||
* they are specified and only the first {@link AccessDeniedHandler} is used.
|
||||
* @param handlers a map of {@link RequestMatcher}s to {@link AccessDeniedHandler}s
|
||||
* that should be used. Each is considered in the order they are specified and only
|
||||
* the first {@link AccessDeniedHandler} is used.
|
||||
* @param defaultHandler the default {@link AccessDeniedHandler} that should be used
|
||||
* if none of the matchers match.
|
||||
*/
|
||||
public RequestMatcherDelegatingAccessDeniedHandler(
|
||||
LinkedHashMap<RequestMatcher, AccessDeniedHandler> handlers,
|
||||
public RequestMatcherDelegatingAccessDeniedHandler(LinkedHashMap<RequestMatcher, AccessDeniedHandler> handlers,
|
||||
AccessDeniedHandler defaultHandler) {
|
||||
Assert.notEmpty(handlers, "handlers cannot be null or empty");
|
||||
Assert.notNull(defaultHandler, "defaultHandler cannot be null");
|
||||
@@ -59,10 +58,8 @@ public final class RequestMatcherDelegatingAccessDeniedHandler implements Access
|
||||
}
|
||||
|
||||
public void handle(HttpServletRequest request, HttpServletResponse response,
|
||||
AccessDeniedException accessDeniedException) throws IOException,
|
||||
ServletException {
|
||||
for (Entry<RequestMatcher, AccessDeniedHandler> entry : this.handlers
|
||||
.entrySet()) {
|
||||
AccessDeniedException accessDeniedException) throws IOException, ServletException {
|
||||
for (Entry<RequestMatcher, AccessDeniedHandler> entry : this.handlers.entrySet()) {
|
||||
RequestMatcher matcher = entry.getKey();
|
||||
if (matcher.matches(request)) {
|
||||
AccessDeniedHandler handler = entry.getValue();
|
||||
|
||||
+1
-2
@@ -29,7 +29,6 @@ public interface WebInvocationPrivilegeEvaluator {
|
||||
/**
|
||||
* Determines whether the user represented by the supplied <tt>Authentication</tt>
|
||||
* object is allowed to invoke the supplied URI.
|
||||
*
|
||||
* @param uri the URI excluding the context path (a default context path setting will
|
||||
* be used)
|
||||
*/
|
||||
@@ -44,7 +43,6 @@ public interface WebInvocationPrivilegeEvaluator {
|
||||
* metadata applies to a given request URI, so generally the <code>contextPath</code>
|
||||
* is unimportant unless you are using a custom
|
||||
* <code>FilterInvocationSecurityMetadataSource</code>.
|
||||
*
|
||||
* @param uri the URI excluding the context path
|
||||
* @param contextPath the context path (may be null).
|
||||
* @param method the HTTP method (or null, for any method)
|
||||
@@ -53,4 +51,5 @@ public interface WebInvocationPrivilegeEvaluator {
|
||||
* @return true if access is allowed, false if denied
|
||||
*/
|
||||
boolean isAllowed(String contextPath, String uri, String method, Authentication authentication);
|
||||
|
||||
}
|
||||
|
||||
+8
-7
@@ -29,6 +29,7 @@ import java.io.IOException;
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
public abstract class AbstractRetryEntryPoint implements ChannelEntryPoint {
|
||||
|
||||
// ~ Static fields/initializers
|
||||
// =====================================================================================
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
@@ -37,9 +38,12 @@ public abstract class AbstractRetryEntryPoint implements ChannelEntryPoint {
|
||||
// ================================================================================================
|
||||
|
||||
private PortMapper portMapper = new PortMapperImpl();
|
||||
|
||||
private PortResolver portResolver = new PortResolverImpl();
|
||||
|
||||
/** The scheme ("http://" or "https://") */
|
||||
private final String scheme;
|
||||
|
||||
/** The standard port for the scheme (80 for http, 443 for https) */
|
||||
private final int standardPort;
|
||||
|
||||
@@ -56,11 +60,9 @@ public abstract class AbstractRetryEntryPoint implements ChannelEntryPoint {
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException {
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
String queryString = request.getQueryString();
|
||||
String redirectUrl = request.getRequestURI()
|
||||
+ ((queryString == null) ? "" : ("?" + queryString));
|
||||
String redirectUrl = request.getRequestURI() + ((queryString == null) ? "" : ("?" + queryString));
|
||||
|
||||
Integer currentPort = portResolver.getServerPort(request);
|
||||
Integer redirectPort = getMappedPort(currentPort);
|
||||
@@ -68,8 +70,7 @@ public abstract class AbstractRetryEntryPoint implements ChannelEntryPoint {
|
||||
if (redirectPort != null) {
|
||||
boolean includePort = redirectPort != standardPort;
|
||||
|
||||
redirectUrl = scheme + request.getServerName()
|
||||
+ ((includePort) ? (":" + redirectPort) : "") + redirectUrl;
|
||||
redirectUrl = scheme + request.getServerName() + ((includePort) ? (":" + redirectPort) : "") + redirectUrl;
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
@@ -102,7 +103,6 @@ public abstract class AbstractRetryEntryPoint implements ChannelEntryPoint {
|
||||
/**
|
||||
* Sets the strategy to be used for redirecting to the required channel URL. A
|
||||
* {@code DefaultRedirectStrategy} instance will be used if not set.
|
||||
*
|
||||
* @param redirectStrategy the strategy instance to which the URL will be passed.
|
||||
*/
|
||||
public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
|
||||
@@ -113,4 +113,5 @@ public abstract class AbstractRetryEntryPoint implements ChannelEntryPoint {
|
||||
protected final RedirectStrategy getRedirectStrategy() {
|
||||
return redirectStrategy;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-4
@@ -30,6 +30,7 @@ import javax.servlet.ServletException;
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public interface ChannelDecisionManager {
|
||||
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
@@ -38,8 +39,7 @@ public interface ChannelDecisionManager {
|
||||
* level of channel security based on the requested list of <tt>ConfigAttribute</tt>s.
|
||||
*
|
||||
*/
|
||||
void decide(FilterInvocation invocation, Collection<ConfigAttribute> config)
|
||||
throws IOException, ServletException;
|
||||
void decide(FilterInvocation invocation, Collection<ConfigAttribute> config) throws IOException, ServletException;
|
||||
|
||||
/**
|
||||
* Indicates whether this <code>ChannelDecisionManager</code> is able to process the
|
||||
@@ -48,12 +48,11 @@ public interface ChannelDecisionManager {
|
||||
* This allows the <code>ChannelProcessingFilter</code> to check every configuration
|
||||
* attribute can be consumed by the configured <code>ChannelDecisionManager</code>.
|
||||
* </p>
|
||||
*
|
||||
* @param attribute a configuration attribute that has been configured against the
|
||||
* <code>ChannelProcessingFilter</code>
|
||||
*
|
||||
* @return true if this <code>ChannelDecisionManager</code> can support the passed
|
||||
* configuration attribute
|
||||
*/
|
||||
boolean supports(ConfigAttribute attribute);
|
||||
|
||||
}
|
||||
|
||||
+4
-5
@@ -47,8 +47,7 @@ import javax.servlet.ServletException;
|
||||
*
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public class ChannelDecisionManagerImpl implements ChannelDecisionManager,
|
||||
InitializingBean {
|
||||
public class ChannelDecisionManagerImpl implements ChannelDecisionManager, InitializingBean {
|
||||
|
||||
public static final String ANY_CHANNEL = "ANY_CHANNEL";
|
||||
|
||||
@@ -91,9 +90,8 @@ public class ChannelDecisionManagerImpl implements ChannelDecisionManager,
|
||||
channelProcessors = new ArrayList<>(newList.size());
|
||||
|
||||
for (Object currentObject : newList) {
|
||||
Assert.isInstanceOf(ChannelProcessor.class, currentObject,
|
||||
() -> "ChannelProcessor " + currentObject.getClass().getName()
|
||||
+ " must implement ChannelProcessor");
|
||||
Assert.isInstanceOf(ChannelProcessor.class, currentObject, () -> "ChannelProcessor "
|
||||
+ currentObject.getClass().getName() + " must implement ChannelProcessor");
|
||||
channelProcessors.add((ChannelProcessor) currentObject);
|
||||
}
|
||||
}
|
||||
@@ -111,4 +109,5 @@ public class ChannelDecisionManagerImpl implements ChannelDecisionManager,
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -32,6 +32,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public interface ChannelEntryPoint {
|
||||
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
@@ -41,11 +42,10 @@ public interface ChannelEntryPoint {
|
||||
* Implementations should modify the headers on the <code>ServletResponse</code> as
|
||||
* necessary to commence the user agent using the implementation's supported channel
|
||||
* type.
|
||||
*
|
||||
* @param request that a <code>ChannelProcessor</code> has rejected
|
||||
* @param response so that the user agent can begin using a new channel
|
||||
*
|
||||
*/
|
||||
void commence(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException;
|
||||
void commence(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException;
|
||||
|
||||
}
|
||||
|
||||
+9
-12
@@ -89,6 +89,7 @@ public class ChannelProcessingFilter extends GenericFilterBean {
|
||||
// ================================================================================================
|
||||
|
||||
private ChannelDecisionManager channelDecisionManager;
|
||||
|
||||
private FilterInvocationSecurityMetadataSource securityMetadataSource;
|
||||
|
||||
// ~ Methods
|
||||
@@ -96,18 +97,15 @@ public class ChannelProcessingFilter extends GenericFilterBean {
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
Assert.notNull(this.securityMetadataSource,
|
||||
"securityMetadataSource must be specified");
|
||||
Assert.notNull(this.channelDecisionManager,
|
||||
"channelDecisionManager must be specified");
|
||||
Assert.notNull(this.securityMetadataSource, "securityMetadataSource must be specified");
|
||||
Assert.notNull(this.channelDecisionManager, "channelDecisionManager must be specified");
|
||||
|
||||
Collection<ConfigAttribute> attrDefs = this.securityMetadataSource
|
||||
.getAllConfigAttributes();
|
||||
Collection<ConfigAttribute> attrDefs = this.securityMetadataSource.getAllConfigAttributes();
|
||||
|
||||
if (attrDefs == null) {
|
||||
if (this.logger.isWarnEnabled()) {
|
||||
this.logger
|
||||
.warn("Could not validate configuration attributes as the FilterInvocationSecurityMetadataSource did "
|
||||
this.logger.warn(
|
||||
"Could not validate configuration attributes as the FilterInvocationSecurityMetadataSource did "
|
||||
+ "not return any attributes");
|
||||
}
|
||||
|
||||
@@ -128,8 +126,7 @@ public class ChannelProcessingFilter extends GenericFilterBean {
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException(
|
||||
"Unsupported configuration attributes: " + unsupportedAttributes);
|
||||
throw new IllegalArgumentException("Unsupported configuration attributes: " + unsupportedAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,8 +140,7 @@ public class ChannelProcessingFilter extends GenericFilterBean {
|
||||
|
||||
if (attr != null) {
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(
|
||||
"Request: " + fi.toString() + "; ConfigAttributes: " + attr);
|
||||
this.logger.debug("Request: " + fi.toString() + "; ConfigAttributes: " + attr);
|
||||
}
|
||||
|
||||
this.channelDecisionManager.decide(fi, attr);
|
||||
@@ -173,4 +169,5 @@ public class ChannelProcessingFilter extends GenericFilterBean {
|
||||
FilterInvocationSecurityMetadataSource filterInvocationSecurityMetadataSource) {
|
||||
this.securityMetadataSource = filterInvocationSecurityMetadataSource;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-4
@@ -36,6 +36,7 @@ import javax.servlet.ServletException;
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public interface ChannelProcessor {
|
||||
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
@@ -44,8 +45,7 @@ public interface ChannelProcessor {
|
||||
* level of channel security based on the requested list of <tt>ConfigAttribute</tt>s.
|
||||
*
|
||||
*/
|
||||
void decide(FilterInvocation invocation, Collection<ConfigAttribute> config)
|
||||
throws IOException, ServletException;
|
||||
void decide(FilterInvocation invocation, Collection<ConfigAttribute> config) throws IOException, ServletException;
|
||||
|
||||
/**
|
||||
* Indicates whether this <code>ChannelProcessor</code> is able to process the passed
|
||||
@@ -53,12 +53,11 @@ public interface ChannelProcessor {
|
||||
* <p>
|
||||
* This allows the <code>ChannelProcessingFilter</code> to check every configuration
|
||||
* attribute can be consumed by the configured <code>ChannelDecisionManager</code>.
|
||||
*
|
||||
* @param attribute a configuration attribute that has been configured against the
|
||||
* <tt>ChannelProcessingFilter</tt>.
|
||||
*
|
||||
* @return true if this <code>ChannelProcessor</code> can support the passed
|
||||
* configuration attribute
|
||||
*/
|
||||
boolean supports(ConfigAttribute attribute);
|
||||
|
||||
}
|
||||
|
||||
+4
-2
@@ -41,10 +41,12 @@ import org.springframework.util.Assert;
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public class InsecureChannelProcessor implements InitializingBean, ChannelProcessor {
|
||||
|
||||
// ~ Instance fields
|
||||
// ================================================================================================
|
||||
|
||||
private ChannelEntryPoint entryPoint = new RetryWithHttpEntryPoint();
|
||||
|
||||
private String insecureKeyword = "REQUIRES_INSECURE_CHANNEL";
|
||||
|
||||
// ~ Methods
|
||||
@@ -64,8 +66,7 @@ public class InsecureChannelProcessor implements InitializingBean, ChannelProces
|
||||
for (ConfigAttribute attribute : config) {
|
||||
if (supports(attribute)) {
|
||||
if (invocation.getHttpRequest().isSecure()) {
|
||||
entryPoint
|
||||
.commence(invocation.getRequest(), invocation.getResponse());
|
||||
entryPoint.commence(invocation.getRequest(), invocation.getResponse());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,4 +92,5 @@ public class InsecureChannelProcessor implements InitializingBean, ChannelProces
|
||||
return (attribute != null) && (attribute.getAttribute() != null)
|
||||
&& attribute.getAttribute().equals(getInsecureKeyword());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
@@ -34,4 +34,5 @@ public class RetryWithHttpEntryPoint extends AbstractRetryEntryPoint {
|
||||
protected Integer getMappedPort(Integer mapFromPort) {
|
||||
return getPortMapper().lookupHttpPort(mapFromPort);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
@@ -35,4 +35,5 @@ public class RetryWithHttpsEntryPoint extends AbstractRetryEntryPoint {
|
||||
protected Integer getMappedPort(Integer mapFromPort) {
|
||||
return getPortMapper().lookupHttpsPort(mapFromPort);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-4
@@ -41,10 +41,12 @@ import org.springframework.util.Assert;
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public class SecureChannelProcessor implements InitializingBean, ChannelProcessor {
|
||||
|
||||
// ~ Instance fields
|
||||
// ================================================================================================
|
||||
|
||||
private ChannelEntryPoint entryPoint = new RetryWithHttpsEntryPoint();
|
||||
|
||||
private String secureKeyword = "REQUIRES_SECURE_CHANNEL";
|
||||
|
||||
// ~ Methods
|
||||
@@ -57,14 +59,12 @@ public class SecureChannelProcessor implements InitializingBean, ChannelProcesso
|
||||
|
||||
public void decide(FilterInvocation invocation, Collection<ConfigAttribute> config)
|
||||
throws IOException, ServletException {
|
||||
Assert.isTrue((invocation != null) && (config != null),
|
||||
"Nulls cannot be provided");
|
||||
Assert.isTrue((invocation != null) && (config != null), "Nulls cannot be provided");
|
||||
|
||||
for (ConfigAttribute attribute : config) {
|
||||
if (supports(attribute)) {
|
||||
if (!invocation.getHttpRequest().isSecure()) {
|
||||
entryPoint
|
||||
.commence(invocation.getRequest(), invocation.getResponse());
|
||||
entryPoint.commence(invocation.getRequest(), invocation.getResponse());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,4 +90,5 @@ public class SecureChannelProcessor implements InitializingBean, ChannelProcesso
|
||||
return (attribute != null) && (attribute.getAttribute() != null)
|
||||
&& attribute.getAttribute().equals(getSecureKeyword());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,4 +19,3 @@
|
||||
* Most commonly used to enforce that requests are submitted over HTTP or HTTPS.
|
||||
*/
|
||||
package org.springframework.security.web.access.channel;
|
||||
|
||||
|
||||
+1
-2
@@ -39,8 +39,7 @@ abstract class AbstractVariableEvaluationContextPostProcessor
|
||||
implements EvaluationContextPostProcessor<FilterInvocation> {
|
||||
|
||||
@Override
|
||||
public final EvaluationContext postProcess(EvaluationContext context,
|
||||
FilterInvocation invocation) {
|
||||
public final EvaluationContext postProcess(EvaluationContext context, FilterInvocation invocation) {
|
||||
final HttpServletRequest request = invocation.getHttpRequest();
|
||||
return new DelegatingEvaluationContext(context) {
|
||||
private Map<String, String> variables;
|
||||
|
||||
+12
-12
@@ -25,21 +25,20 @@ import org.springframework.security.web.FilterInvocation;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @author Eddú Meléndez
|
||||
* @since 3.0
|
||||
*/
|
||||
public class DefaultWebSecurityExpressionHandler extends
|
||||
AbstractSecurityExpressionHandler<FilterInvocation> implements
|
||||
SecurityExpressionHandler<FilterInvocation> {
|
||||
public class DefaultWebSecurityExpressionHandler extends AbstractSecurityExpressionHandler<FilterInvocation>
|
||||
implements SecurityExpressionHandler<FilterInvocation> {
|
||||
|
||||
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
|
||||
|
||||
private String defaultRolePrefix = "ROLE_";
|
||||
|
||||
@Override
|
||||
protected SecurityExpressionOperations createSecurityExpressionRoot(
|
||||
Authentication authentication, FilterInvocation fi) {
|
||||
protected SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication,
|
||||
FilterInvocation fi) {
|
||||
WebSecurityExpressionRoot root = new WebSecurityExpressionRoot(authentication, fi);
|
||||
root.setPermissionEvaluator(getPermissionEvaluator());
|
||||
root.setTrustResolver(trustResolver);
|
||||
@@ -51,7 +50,6 @@ public class DefaultWebSecurityExpressionHandler extends
|
||||
/**
|
||||
* Sets the {@link AuthenticationTrustResolver} to be used. The default is
|
||||
* {@link AuthenticationTrustResolverImpl}.
|
||||
*
|
||||
* @param trustResolver the {@link AuthenticationTrustResolver} to use. Cannot be
|
||||
* null.
|
||||
*/
|
||||
@@ -62,19 +60,21 @@ public class DefaultWebSecurityExpressionHandler extends
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Sets the default prefix to be added to {@link org.springframework.security.access.expression.SecurityExpressionRoot#hasAnyRole(String...)} or
|
||||
* {@link org.springframework.security.access.expression.SecurityExpressionRoot#hasRole(String)}. For example, if hasRole("ADMIN") or hasRole("ROLE_ADMIN")
|
||||
* is passed in, then the role ROLE_ADMIN will be used when the defaultRolePrefix is
|
||||
* "ROLE_" (default).
|
||||
* Sets the default prefix to be added to
|
||||
* {@link org.springframework.security.access.expression.SecurityExpressionRoot#hasAnyRole(String...)}
|
||||
* or
|
||||
* {@link org.springframework.security.access.expression.SecurityExpressionRoot#hasRole(String)}.
|
||||
* For example, if hasRole("ADMIN") or hasRole("ROLE_ADMIN") is passed in, then the
|
||||
* role ROLE_ADMIN will be used when the defaultRolePrefix is "ROLE_" (default).
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* If null or empty, then no default role prefix is used.
|
||||
* </p>
|
||||
*
|
||||
* @param defaultRolePrefix the default prefix to add to roles. Default "ROLE_".
|
||||
*/
|
||||
public void setDefaultRolePrefix(String defaultRolePrefix) {
|
||||
this.defaultRolePrefix = defaultRolePrefix;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
@@ -36,6 +36,7 @@ import org.springframework.expression.TypedValue;
|
||||
* @since 4.1
|
||||
*/
|
||||
class DelegatingEvaluationContext implements EvaluationContext {
|
||||
|
||||
private final EvaluationContext delegate;
|
||||
|
||||
DelegatingEvaluationContext(EvaluationContext delegate) {
|
||||
@@ -96,4 +97,5 @@ class DelegatingEvaluationContext implements EvaluationContext {
|
||||
public Object lookupVariable(String name) {
|
||||
return this.delegate.lookupVariable(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-10
@@ -16,10 +16,10 @@
|
||||
package org.springframework.security.web.access.expression;
|
||||
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
|
||||
/**
|
||||
*
|
||||
/**
|
||||
* Allows post processing the {@link EvaluationContext}
|
||||
* /** Allows post processing the {@link EvaluationContext}
|
||||
*
|
||||
* <p>
|
||||
* This API is intentionally kept package scope as it may evolve over time.
|
||||
@@ -32,15 +32,13 @@ import org.springframework.expression.EvaluationContext;
|
||||
interface EvaluationContextPostProcessor<I> {
|
||||
|
||||
/**
|
||||
* Allows post processing of the {@link EvaluationContext}. Implementations
|
||||
* may return a new instance of {@link EvaluationContext} or modify the
|
||||
* {@link EvaluationContext} that was passed in.
|
||||
*
|
||||
* @param context
|
||||
* the original {@link EvaluationContext}
|
||||
* @param invocation
|
||||
* the security invocation object (i.e. FilterInvocation)
|
||||
* Allows post processing of the {@link EvaluationContext}. Implementations may return
|
||||
* a new instance of {@link EvaluationContext} or modify the {@link EvaluationContext}
|
||||
* that was passed in.
|
||||
* @param context the original {@link EvaluationContext}
|
||||
* @param invocation the security invocation object (i.e. FilterInvocation)
|
||||
* @return the upated context.
|
||||
*/
|
||||
EvaluationContext postProcess(EvaluationContext context, I invocation);
|
||||
|
||||
}
|
||||
|
||||
+18
-26
@@ -44,45 +44,36 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public final class ExpressionBasedFilterInvocationSecurityMetadataSource
|
||||
extends DefaultFilterInvocationSecurityMetadataSource {
|
||||
private final static Log logger = LogFactory
|
||||
.getLog(ExpressionBasedFilterInvocationSecurityMetadataSource.class);
|
||||
|
||||
private final static Log logger = LogFactory.getLog(ExpressionBasedFilterInvocationSecurityMetadataSource.class);
|
||||
|
||||
public ExpressionBasedFilterInvocationSecurityMetadataSource(
|
||||
LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap,
|
||||
SecurityExpressionHandler<FilterInvocation> expressionHandler) {
|
||||
super(processMap(requestMap, expressionHandler.getExpressionParser()));
|
||||
Assert.notNull(expressionHandler,
|
||||
"A non-null SecurityExpressionHandler is required");
|
||||
Assert.notNull(expressionHandler, "A non-null SecurityExpressionHandler is required");
|
||||
}
|
||||
|
||||
private static LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> processMap(
|
||||
LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap,
|
||||
ExpressionParser parser) {
|
||||
LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap, ExpressionParser parser) {
|
||||
Assert.notNull(parser, "SecurityExpressionHandler returned a null parser object");
|
||||
|
||||
LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestToExpressionAttributesMap = new LinkedHashMap<>(
|
||||
requestMap);
|
||||
|
||||
for (Map.Entry<RequestMatcher, Collection<ConfigAttribute>> entry : requestMap
|
||||
.entrySet()) {
|
||||
for (Map.Entry<RequestMatcher, Collection<ConfigAttribute>> entry : requestMap.entrySet()) {
|
||||
RequestMatcher request = entry.getKey();
|
||||
Assert.isTrue(entry.getValue().size() == 1,
|
||||
() -> "Expected a single expression attribute for " + request);
|
||||
Assert.isTrue(entry.getValue().size() == 1, () -> "Expected a single expression attribute for " + request);
|
||||
ArrayList<ConfigAttribute> attributes = new ArrayList<>(1);
|
||||
String expression = entry.getValue().toArray(new ConfigAttribute[1])[0]
|
||||
.getAttribute();
|
||||
logger.debug("Adding web access control expression '" + expression + "', for "
|
||||
+ request);
|
||||
String expression = entry.getValue().toArray(new ConfigAttribute[1])[0].getAttribute();
|
||||
logger.debug("Adding web access control expression '" + expression + "', for " + request);
|
||||
|
||||
AbstractVariableEvaluationContextPostProcessor postProcessor = createPostProcessor(
|
||||
request);
|
||||
AbstractVariableEvaluationContextPostProcessor postProcessor = createPostProcessor(request);
|
||||
try {
|
||||
attributes.add(new WebExpressionConfigAttribute(
|
||||
parser.parseExpression(expression), postProcessor));
|
||||
attributes.add(new WebExpressionConfigAttribute(parser.parseExpression(expression), postProcessor));
|
||||
}
|
||||
catch (ParseException e) {
|
||||
throw new IllegalArgumentException(
|
||||
"Failed to parse expression '" + expression + "'");
|
||||
throw new IllegalArgumentException("Failed to parse expression '" + expression + "'");
|
||||
}
|
||||
|
||||
requestToExpressionAttributesMap.put(request, attributes);
|
||||
@@ -95,12 +86,11 @@ public final class ExpressionBasedFilterInvocationSecurityMetadataSource
|
||||
return new RequestVariablesExtractorEvaluationContextPostProcessor(request);
|
||||
}
|
||||
|
||||
static class AntPathMatcherEvaluationContextPostProcessor
|
||||
extends AbstractVariableEvaluationContextPostProcessor {
|
||||
static class AntPathMatcherEvaluationContextPostProcessor extends AbstractVariableEvaluationContextPostProcessor {
|
||||
|
||||
private final AntPathRequestMatcher matcher;
|
||||
|
||||
AntPathMatcherEvaluationContextPostProcessor(
|
||||
AntPathRequestMatcher matcher) {
|
||||
AntPathMatcherEvaluationContextPostProcessor(AntPathRequestMatcher matcher) {
|
||||
this.matcher = matcher;
|
||||
}
|
||||
|
||||
@@ -108,14 +98,15 @@ public final class ExpressionBasedFilterInvocationSecurityMetadataSource
|
||||
Map<String, String> extractVariables(HttpServletRequest request) {
|
||||
return this.matcher.matcher(request).getVariables();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class RequestVariablesExtractorEvaluationContextPostProcessor
|
||||
extends AbstractVariableEvaluationContextPostProcessor {
|
||||
|
||||
private final RequestMatcher matcher;
|
||||
|
||||
RequestVariablesExtractorEvaluationContextPostProcessor(
|
||||
RequestMatcher matcher) {
|
||||
RequestVariablesExtractorEvaluationContextPostProcessor(RequestMatcher matcher) {
|
||||
this.matcher = matcher;
|
||||
}
|
||||
|
||||
@@ -123,6 +114,7 @@ public final class ExpressionBasedFilterInvocationSecurityMetadataSource
|
||||
Map<String, String> extractVariables(HttpServletRequest request) {
|
||||
return this.matcher.matcher(request).getVariables();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-4
@@ -26,9 +26,10 @@ import org.springframework.security.web.FilterInvocation;
|
||||
* @author Luke Taylor
|
||||
* @since 3.0
|
||||
*/
|
||||
class WebExpressionConfigAttribute implements ConfigAttribute,
|
||||
EvaluationContextPostProcessor<FilterInvocation> {
|
||||
class WebExpressionConfigAttribute implements ConfigAttribute, EvaluationContextPostProcessor<FilterInvocation> {
|
||||
|
||||
private final Expression authorizeExpression;
|
||||
|
||||
private final EvaluationContextPostProcessor<FilterInvocation> postProcessor;
|
||||
|
||||
WebExpressionConfigAttribute(Expression authorizeExpression,
|
||||
@@ -43,8 +44,7 @@ class WebExpressionConfigAttribute implements ConfigAttribute,
|
||||
|
||||
@Override
|
||||
public EvaluationContext postProcess(EvaluationContext context, FilterInvocation fi) {
|
||||
return this.postProcessor == null ? context
|
||||
: this.postProcessor.postProcess(context, fi);
|
||||
return this.postProcessor == null ? context : this.postProcessor.postProcess(context, fi);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -56,4 +56,5 @@ class WebExpressionConfigAttribute implements ConfigAttribute,
|
||||
public String toString() {
|
||||
return this.authorizeExpression.getExpressionString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-10
@@ -27,14 +27,15 @@ import org.springframework.security.web.FilterInvocation;
|
||||
|
||||
/**
|
||||
* Voter which handles web authorisation decisions.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 3.0
|
||||
*/
|
||||
public class WebExpressionVoter implements AccessDecisionVoter<FilterInvocation> {
|
||||
|
||||
private SecurityExpressionHandler<FilterInvocation> expressionHandler = new DefaultWebSecurityExpressionHandler();
|
||||
|
||||
public int vote(Authentication authentication, FilterInvocation fi,
|
||||
Collection<ConfigAttribute> attributes) {
|
||||
public int vote(Authentication authentication, FilterInvocation fi, Collection<ConfigAttribute> attributes) {
|
||||
assert authentication != null;
|
||||
assert fi != null;
|
||||
assert attributes != null;
|
||||
@@ -45,16 +46,13 @@ public class WebExpressionVoter implements AccessDecisionVoter<FilterInvocation>
|
||||
return ACCESS_ABSTAIN;
|
||||
}
|
||||
|
||||
EvaluationContext ctx = expressionHandler.createEvaluationContext(authentication,
|
||||
fi);
|
||||
EvaluationContext ctx = expressionHandler.createEvaluationContext(authentication, fi);
|
||||
ctx = weca.postProcess(ctx, fi);
|
||||
|
||||
return ExpressionUtils.evaluateAsBoolean(weca.getAuthorizeExpression(), ctx) ? ACCESS_GRANTED
|
||||
: ACCESS_DENIED;
|
||||
return ExpressionUtils.evaluateAsBoolean(weca.getAuthorizeExpression(), ctx) ? ACCESS_GRANTED : ACCESS_DENIED;
|
||||
}
|
||||
|
||||
private WebExpressionConfigAttribute findConfigAttribute(
|
||||
Collection<ConfigAttribute> attributes) {
|
||||
private WebExpressionConfigAttribute findConfigAttribute(Collection<ConfigAttribute> attributes) {
|
||||
for (ConfigAttribute attribute : attributes) {
|
||||
if (attribute instanceof WebExpressionConfigAttribute) {
|
||||
return (WebExpressionConfigAttribute) attribute;
|
||||
@@ -71,8 +69,8 @@ public class WebExpressionVoter implements AccessDecisionVoter<FilterInvocation>
|
||||
return FilterInvocation.class.isAssignableFrom(clazz);
|
||||
}
|
||||
|
||||
public void setExpressionHandler(
|
||||
SecurityExpressionHandler<FilterInvocation> expressionHandler) {
|
||||
public void setExpressionHandler(SecurityExpressionHandler<FilterInvocation> expressionHandler) {
|
||||
this.expressionHandler = expressionHandler;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-2
@@ -23,11 +23,11 @@ import org.springframework.security.web.FilterInvocation;
|
||||
import org.springframework.security.web.util.matcher.IpAddressMatcher;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 3.0
|
||||
*/
|
||||
public class WebSecurityExpressionRoot extends SecurityExpressionRoot {
|
||||
|
||||
// private FilterInvocation filterInvocation;
|
||||
/** Allows direct access to the request object */
|
||||
public final HttpServletRequest request;
|
||||
@@ -41,7 +41,6 @@ public class WebSecurityExpressionRoot extends SecurityExpressionRoot {
|
||||
/**
|
||||
* Takes a specific IP address or a range using the IP/Netmask (e.g. 192.168.1.0/24 or
|
||||
* 202.24.0.0/14).
|
||||
*
|
||||
* @param ipAddress the address or range of addresses from which the request must
|
||||
* come.
|
||||
* @return true if the IP address of the current request is in the required range.
|
||||
|
||||
@@ -17,4 +17,3 @@
|
||||
* Implementation of web security expressions.
|
||||
*/
|
||||
package org.springframework.security.web.access.expression;
|
||||
|
||||
|
||||
+6
-10
@@ -44,15 +44,13 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
* <p>
|
||||
* The most common method creating an instance is using the Spring Security namespace. For
|
||||
* example, the {@code pattern} and {@code access} attributes of the
|
||||
* {@code <intercept-url>} elements defined as children of the {@code <http>}
|
||||
* element are combined to build the instance used by the
|
||||
* {@code FilterSecurityInterceptor}.
|
||||
* {@code <intercept-url>} elements defined as children of the {@code <http>} element are
|
||||
* combined to build the instance used by the {@code FilterSecurityInterceptor}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
public class DefaultFilterInvocationSecurityMetadataSource implements
|
||||
FilterInvocationSecurityMetadataSource {
|
||||
public class DefaultFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
@@ -65,7 +63,6 @@ public class DefaultFilterInvocationSecurityMetadataSource implements
|
||||
* Sets the internal request map from the supplied map. The key elements should be of
|
||||
* type {@link RequestMatcher}, which. The path stored in the key will depend on the
|
||||
* type of the supplied UrlMatcher.
|
||||
*
|
||||
* @param requestMap order-preserving map of request definitions to attribute lists
|
||||
*/
|
||||
public DefaultFilterInvocationSecurityMetadataSource(
|
||||
@@ -80,8 +77,7 @@ public class DefaultFilterInvocationSecurityMetadataSource implements
|
||||
public Collection<ConfigAttribute> getAllConfigAttributes() {
|
||||
Set<ConfigAttribute> allAttributes = new HashSet<>();
|
||||
|
||||
for (Map.Entry<RequestMatcher, Collection<ConfigAttribute>> entry : requestMap
|
||||
.entrySet()) {
|
||||
for (Map.Entry<RequestMatcher, Collection<ConfigAttribute>> entry : requestMap.entrySet()) {
|
||||
allAttributes.addAll(entry.getValue());
|
||||
}
|
||||
|
||||
@@ -90,8 +86,7 @@ public class DefaultFilterInvocationSecurityMetadataSource implements
|
||||
|
||||
public Collection<ConfigAttribute> getAttributes(Object object) {
|
||||
final HttpServletRequest request = ((FilterInvocation) object).getRequest();
|
||||
for (Map.Entry<RequestMatcher, Collection<ConfigAttribute>> entry : requestMap
|
||||
.entrySet()) {
|
||||
for (Map.Entry<RequestMatcher, Collection<ConfigAttribute>> entry : requestMap.entrySet()) {
|
||||
if (entry.getKey().matches(request)) {
|
||||
return entry.getValue();
|
||||
}
|
||||
@@ -102,4 +97,5 @@ public class DefaultFilterInvocationSecurityMetadataSource implements
|
||||
public boolean supports(Class<?> clazz) {
|
||||
return FilterInvocation.class.isAssignableFrom(clazz);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
@@ -26,4 +26,5 @@ import org.springframework.security.web.FilterInvocation;
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public interface FilterInvocationSecurityMetadataSource extends SecurityMetadataSource {
|
||||
|
||||
}
|
||||
|
||||
+7
-10
@@ -42,8 +42,8 @@ import org.springframework.security.web.FilterInvocation;
|
||||
* @author Ben Alex
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implements
|
||||
Filter {
|
||||
public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {
|
||||
|
||||
// ~ Static fields/initializers
|
||||
// =====================================================================================
|
||||
|
||||
@@ -53,6 +53,7 @@ public class FilterSecurityInterceptor extends AbstractSecurityInterceptor imple
|
||||
// ================================================================================================
|
||||
|
||||
private FilterInvocationSecurityMetadataSource securityMetadataSource;
|
||||
|
||||
private boolean observeOncePerRequest = true;
|
||||
|
||||
// ~ Methods
|
||||
@@ -60,7 +61,6 @@ public class FilterSecurityInterceptor extends AbstractSecurityInterceptor imple
|
||||
|
||||
/**
|
||||
* Not used (we rely on IoC container lifecycle services instead)
|
||||
*
|
||||
* @param arg0 ignored
|
||||
*
|
||||
*/
|
||||
@@ -76,16 +76,14 @@ public class FilterSecurityInterceptor extends AbstractSecurityInterceptor imple
|
||||
/**
|
||||
* Method that is actually called by the filter chain. Simply delegates to the
|
||||
* {@link #invoke(FilterInvocation)} method.
|
||||
*
|
||||
* @param request the servlet request
|
||||
* @param response the servlet response
|
||||
* @param chain the filter chain
|
||||
*
|
||||
* @throws IOException if the filter chain fails
|
||||
* @throws ServletException if the filter chain fails
|
||||
*/
|
||||
public void doFilter(ServletRequest request, ServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
FilterInvocation fi = new FilterInvocation(request, response, chain);
|
||||
invoke(fi);
|
||||
}
|
||||
@@ -107,8 +105,7 @@ public class FilterSecurityInterceptor extends AbstractSecurityInterceptor imple
|
||||
}
|
||||
|
||||
public void invoke(FilterInvocation fi) throws IOException, ServletException {
|
||||
if ((fi.getRequest() != null)
|
||||
&& (fi.getRequest().getAttribute(FILTER_APPLIED) != null)
|
||||
if ((fi.getRequest() != null) && (fi.getRequest().getAttribute(FILTER_APPLIED) != null)
|
||||
&& observeOncePerRequest) {
|
||||
// filter already applied to this request and user wants us to observe
|
||||
// once-per-request handling, so don't re-do security checking
|
||||
@@ -139,7 +136,6 @@ public class FilterSecurityInterceptor extends AbstractSecurityInterceptor imple
|
||||
* execute once-per-request. Sometimes users may wish it to execute more than once per
|
||||
* request, such as when JSP forwards are being used and filter security is desired on
|
||||
* each included fragment of the HTTP request.
|
||||
*
|
||||
* @return <code>true</code> (the default) if once-per-request is honoured, otherwise
|
||||
* <code>false</code> if <code>FilterSecurityInterceptor</code> will enforce
|
||||
* authorizations for each and every fragment of the HTTP request.
|
||||
@@ -151,4 +147,5 @@ public class FilterSecurityInterceptor extends AbstractSecurityInterceptor imple
|
||||
public void setObserveOncePerRequest(boolean observeOncePerRequest) {
|
||||
this.observeOncePerRequest = observeOncePerRequest;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,9 @@ import org.springframework.util.Assert;
|
||||
* @since 2.0
|
||||
*/
|
||||
public class RequestKey {
|
||||
|
||||
private final String url;
|
||||
|
||||
private final String method;
|
||||
|
||||
public RequestKey(String url) {
|
||||
@@ -81,4 +83,5 @@ public class RequestKey {
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,4 +17,3 @@
|
||||
* Enforcement of security for HTTP requests, typically by the URL requested.
|
||||
*/
|
||||
package org.springframework.security.web.access.intercept;
|
||||
|
||||
|
||||
@@ -17,4 +17,3 @@
|
||||
* Access-control related classes and packages.
|
||||
*/
|
||||
package org.springframework.security.web.access;
|
||||
|
||||
|
||||
+47
-64
@@ -100,16 +100,16 @@ import org.springframework.web.filter.GenericFilterBean;
|
||||
*
|
||||
* The class has an optional {@link SessionAuthenticationStrategy} which will be invoked
|
||||
* immediately after a successful call to {@code attemptAuthentication()}. Different
|
||||
* implementations
|
||||
* {@link #setSessionAuthenticationStrategy(SessionAuthenticationStrategy) can be
|
||||
* injected} to enable things like session-fixation attack prevention or to control the
|
||||
* number of simultaneous sessions a principal may have.
|
||||
* implementations {@link #setSessionAuthenticationStrategy(SessionAuthenticationStrategy)
|
||||
* can be injected} to enable things like session-fixation attack prevention or to control
|
||||
* the number of simultaneous sessions a principal may have.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
public abstract class AbstractAuthenticationProcessingFilter extends GenericFilterBean
|
||||
implements ApplicationEventPublisherAware, MessageSourceAware {
|
||||
|
||||
// ~ Static fields/initializers
|
||||
// =====================================================================================
|
||||
|
||||
@@ -117,9 +117,13 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
||||
// ================================================================================================
|
||||
|
||||
protected ApplicationEventPublisher eventPublisher;
|
||||
|
||||
protected AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
|
||||
|
||||
private AuthenticationManager authenticationManager;
|
||||
|
||||
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
|
||||
|
||||
private RememberMeServices rememberMeServices = new NullRememberMeServices();
|
||||
|
||||
private RequestMatcher requiresAuthenticationRequestMatcher;
|
||||
@@ -131,6 +135,7 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
||||
private boolean allowSessionCreation = true;
|
||||
|
||||
private AuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
|
||||
|
||||
private AuthenticationFailureHandler failureHandler = new SimpleUrlAuthenticationFailureHandler();
|
||||
|
||||
// ~ Constructors
|
||||
@@ -145,23 +150,20 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param requiresAuthenticationRequestMatcher the {@link RequestMatcher} used to
|
||||
* determine if authentication is required. Cannot be null.
|
||||
*/
|
||||
protected AbstractAuthenticationProcessingFilter(
|
||||
RequestMatcher requiresAuthenticationRequestMatcher) {
|
||||
Assert.notNull(requiresAuthenticationRequestMatcher,
|
||||
"requiresAuthenticationRequestMatcher cannot be null");
|
||||
protected AbstractAuthenticationProcessingFilter(RequestMatcher requiresAuthenticationRequestMatcher) {
|
||||
Assert.notNull(requiresAuthenticationRequestMatcher, "requiresAuthenticationRequestMatcher cannot be null");
|
||||
this.requiresAuthenticationRequestMatcher = requiresAuthenticationRequestMatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance with a default filterProcessesUrl and an {@link AuthenticationManager}
|
||||
*
|
||||
* Creates a new instance with a default filterProcessesUrl and an
|
||||
* {@link AuthenticationManager}
|
||||
* @param defaultFilterProcessesUrl the default value for <tt>filterProcessesUrl</tt>.
|
||||
* @param authenticationManager the {@link AuthenticationManager} used to authenticate an {@link Authentication} object.
|
||||
* Cannot be null.
|
||||
* @param authenticationManager the {@link AuthenticationManager} used to authenticate
|
||||
* an {@link Authentication} object. Cannot be null.
|
||||
*/
|
||||
protected AbstractAuthenticationProcessingFilter(String defaultFilterProcessesUrl,
|
||||
AuthenticationManager authenticationManager) {
|
||||
@@ -170,12 +172,12 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance with a {@link RequestMatcher} and an {@link AuthenticationManager}
|
||||
*
|
||||
* @param requiresAuthenticationRequestMatcher the {@link RequestMatcher} used to determine
|
||||
* if authentication is required. Cannot be null.
|
||||
* @param authenticationManager the {@link AuthenticationManager} used to authenticate an {@link Authentication} object.
|
||||
* Cannot be null.
|
||||
* Creates a new instance with a {@link RequestMatcher} and an
|
||||
* {@link AuthenticationManager}
|
||||
* @param requiresAuthenticationRequestMatcher the {@link RequestMatcher} used to
|
||||
* determine if authentication is required. Cannot be null.
|
||||
* @param authenticationManager the {@link AuthenticationManager} used to authenticate
|
||||
* an {@link Authentication} object. Cannot be null.
|
||||
*/
|
||||
protected AbstractAuthenticationProcessingFilter(RequestMatcher requiresAuthenticationRequestMatcher,
|
||||
AuthenticationManager authenticationManager) {
|
||||
@@ -192,12 +194,10 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the
|
||||
* {@link #requiresAuthentication(HttpServletRequest, HttpServletResponse)
|
||||
* Invokes the {@link #requiresAuthentication(HttpServletRequest, HttpServletResponse)
|
||||
* requiresAuthentication} method to determine whether the request is for
|
||||
* authentication and should be handled by this filter. If it is an authentication
|
||||
* request, the
|
||||
* {@link #attemptAuthentication(HttpServletRequest, HttpServletResponse)
|
||||
* request, the {@link #attemptAuthentication(HttpServletRequest, HttpServletResponse)
|
||||
* attemptAuthentication} will be invoked to perform the authentication. There are
|
||||
* then three possible outcomes:
|
||||
* <ol>
|
||||
@@ -245,9 +245,7 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
||||
sessionStrategy.onAuthentication(authResult, request, response);
|
||||
}
|
||||
catch (InternalAuthenticationServiceException failed) {
|
||||
logger.error(
|
||||
"An internal error occurred while trying to authenticate the user.",
|
||||
failed);
|
||||
logger.error("An internal error occurred while trying to authenticate the user.", failed);
|
||||
unsuccessfulAuthentication(request, response, failed);
|
||||
|
||||
return;
|
||||
@@ -276,12 +274,10 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
||||
* before matching against the <code>filterProcessesUrl</code> property.
|
||||
* <p>
|
||||
* Subclasses may override for special requirements, such as Tapestry integration.
|
||||
*
|
||||
* @return <code>true</code> if the filter should attempt authentication,
|
||||
* <code>false</code> otherwise.
|
||||
*/
|
||||
protected boolean requiresAuthentication(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
|
||||
return requiresAuthenticationRequestMatcher.matches(request);
|
||||
}
|
||||
|
||||
@@ -295,20 +291,17 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
||||
* <li>Return null, indicating that the authentication process is still in progress.
|
||||
* Before returning, the implementation should perform any additional work required to
|
||||
* complete the process.</li>
|
||||
* <li>Throw an <tt>AuthenticationException</tt> if the authentication process fails</li>
|
||||
* <li>Throw an <tt>AuthenticationException</tt> if the authentication process
|
||||
* fails</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param request from which to extract parameters and perform the authentication
|
||||
* @param response the response, which may be needed if the implementation has to do a
|
||||
* redirect as part of a multi-stage authentication process (such as OpenID).
|
||||
*
|
||||
* @return the authenticated user token, or null if authentication is incomplete.
|
||||
*
|
||||
* @throws AuthenticationException if authentication fails.
|
||||
*/
|
||||
public abstract Authentication attemptAuthentication(HttpServletRequest request,
|
||||
HttpServletResponse response) throws AuthenticationException, IOException,
|
||||
ServletException;
|
||||
public abstract Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
|
||||
throws AuthenticationException, IOException, ServletException;
|
||||
|
||||
/**
|
||||
* Default behaviour for successful authentication.
|
||||
@@ -318,7 +311,8 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
||||
* <li>Informs the configured <tt>RememberMeServices</tt> of the successful login</li>
|
||||
* <li>Fires an {@link InteractiveAuthenticationSuccessEvent} via the configured
|
||||
* <tt>ApplicationEventPublisher</tt></li>
|
||||
* <li>Delegates additional behaviour to the {@link AuthenticationSuccessHandler}.</li>
|
||||
* <li>Delegates additional behaviour to the
|
||||
* {@link AuthenticationSuccessHandler}.</li>
|
||||
* </ol>
|
||||
*
|
||||
* Subclasses can override this method to continue the {@link FilterChain} after
|
||||
@@ -331,13 +325,11 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
protected void successfulAuthentication(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain chain, Authentication authResult)
|
||||
throws IOException, ServletException {
|
||||
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
|
||||
Authentication authResult) throws IOException, ServletException {
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Authentication success. Updating SecurityContextHolder to contain: "
|
||||
+ authResult);
|
||||
logger.debug("Authentication success. Updating SecurityContextHolder to contain: " + authResult);
|
||||
}
|
||||
|
||||
SecurityContextHolder.getContext().setAuthentication(authResult);
|
||||
@@ -346,8 +338,7 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
||||
|
||||
// Fire event
|
||||
if (this.eventPublisher != null) {
|
||||
eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(
|
||||
authResult, this.getClass()));
|
||||
eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
|
||||
}
|
||||
|
||||
successHandler.onAuthenticationSuccess(request, response, authResult);
|
||||
@@ -360,12 +351,12 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
||||
* <li>Stores the exception in the session (if it exists or
|
||||
* <tt>allowSesssionCreation</tt> is set to <tt>true</tt>)</li>
|
||||
* <li>Informs the configured <tt>RememberMeServices</tt> of the failed login</li>
|
||||
* <li>Delegates additional behaviour to the {@link AuthenticationFailureHandler}.</li>
|
||||
* <li>Delegates additional behaviour to the
|
||||
* {@link AuthenticationFailureHandler}.</li>
|
||||
* </ol>
|
||||
*/
|
||||
protected void unsuccessfulAuthentication(HttpServletRequest request,
|
||||
HttpServletResponse response, AuthenticationException failed)
|
||||
throws IOException, ServletException {
|
||||
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException failed) throws IOException, ServletException {
|
||||
SecurityContextHolder.clearContext();
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
@@ -389,16 +380,13 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
||||
|
||||
/**
|
||||
* Sets the URL that determines if authentication is required
|
||||
*
|
||||
* @param filterProcessesUrl
|
||||
*/
|
||||
public void setFilterProcessesUrl(String filterProcessesUrl) {
|
||||
setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(
|
||||
filterProcessesUrl));
|
||||
setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(filterProcessesUrl));
|
||||
}
|
||||
|
||||
public final void setRequiresAuthenticationRequestMatcher(
|
||||
RequestMatcher requestMatcher) {
|
||||
public final void setRequiresAuthenticationRequestMatcher(RequestMatcher requestMatcher) {
|
||||
Assert.notNull(requestMatcher, "requestMatcher cannot be null");
|
||||
this.requiresAuthenticationRequestMatcher = requestMatcher;
|
||||
}
|
||||
@@ -418,8 +406,7 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
||||
* , which may be useful in certain environment (such as Tapestry applications).
|
||||
* Defaults to <code>false</code>.
|
||||
*/
|
||||
public void setContinueChainBeforeSuccessfulAuthentication(
|
||||
boolean continueChainBeforeSuccessfulAuthentication) {
|
||||
public void setContinueChainBeforeSuccessfulAuthentication(boolean continueChainBeforeSuccessfulAuthentication) {
|
||||
this.continueChainBeforeSuccessfulAuthentication = continueChainBeforeSuccessfulAuthentication;
|
||||
}
|
||||
|
||||
@@ -429,8 +416,7 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
||||
|
||||
public void setAuthenticationDetailsSource(
|
||||
AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource) {
|
||||
Assert.notNull(authenticationDetailsSource,
|
||||
"AuthenticationDetailsSource required");
|
||||
Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");
|
||||
this.authenticationDetailsSource = authenticationDetailsSource;
|
||||
}
|
||||
|
||||
@@ -451,12 +437,10 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
||||
* authentication request is successfully processed by the
|
||||
* <tt>AuthenticationManager</tt>. Used, for example, to handle changing of the
|
||||
* session identifier to prevent session fixation attacks.
|
||||
*
|
||||
* @param sessionStrategy the implementation to use. If not set a null implementation
|
||||
* is used.
|
||||
*/
|
||||
public void setSessionAuthenticationStrategy(
|
||||
SessionAuthenticationStrategy sessionStrategy) {
|
||||
public void setSessionAuthenticationStrategy(SessionAuthenticationStrategy sessionStrategy) {
|
||||
this.sessionStrategy = sessionStrategy;
|
||||
}
|
||||
|
||||
@@ -464,14 +448,12 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
||||
* Sets the strategy used to handle a successful authentication. By default a
|
||||
* {@link SavedRequestAwareAuthenticationSuccessHandler} is used.
|
||||
*/
|
||||
public void setAuthenticationSuccessHandler(
|
||||
AuthenticationSuccessHandler successHandler) {
|
||||
public void setAuthenticationSuccessHandler(AuthenticationSuccessHandler successHandler) {
|
||||
Assert.notNull(successHandler, "successHandler cannot be null");
|
||||
this.successHandler = successHandler;
|
||||
}
|
||||
|
||||
public void setAuthenticationFailureHandler(
|
||||
AuthenticationFailureHandler failureHandler) {
|
||||
public void setAuthenticationFailureHandler(AuthenticationFailureHandler failureHandler) {
|
||||
Assert.notNull(failureHandler, "failureHandler cannot be null");
|
||||
this.failureHandler = failureHandler;
|
||||
}
|
||||
@@ -483,4 +465,5 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
||||
protected AuthenticationFailureHandler getFailureHandler() {
|
||||
return failureHandler;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+15
-19
@@ -40,21 +40,17 @@ import org.springframework.util.StringUtils;
|
||||
* Uses the following logic sequence to determine how it should handle the
|
||||
* forward/redirect
|
||||
* <ul>
|
||||
* <li>
|
||||
* If the {@code alwaysUseDefaultTargetUrl} property is set to true, the
|
||||
* <li>If the {@code alwaysUseDefaultTargetUrl} property is set to true, the
|
||||
* {@code defaultTargetUrl} property will be used for the destination.</li>
|
||||
* <li>
|
||||
* If a parameter matching the value of {@code targetUrlParameter} has been set on the
|
||||
* <li>If a parameter matching the value of {@code targetUrlParameter} has been set on the
|
||||
* request, the value will be used as the destination. If you are enabling this
|
||||
* functionality, then you should ensure that the parameter cannot be used by an attacker
|
||||
* to redirect the user to a malicious site (by clicking on a URL with the parameter
|
||||
* included, for example). Typically it would be used when the parameter is included in
|
||||
* the login form and submitted with the username and password.</li>
|
||||
* <li>
|
||||
* If the {@code useReferer} property is set, the "Referer" HTTP header value will be
|
||||
* <li>If the {@code useReferer} property is set, the "Referer" HTTP header value will be
|
||||
* used, if present.</li>
|
||||
* <li>
|
||||
* As a fallback option, the {@code defaultTargetUrl} value will be used.</li>
|
||||
* <li>As a fallback option, the {@code defaultTargetUrl} value will be used.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Luke Taylor
|
||||
@@ -63,10 +59,15 @@ import org.springframework.util.StringUtils;
|
||||
public abstract class AbstractAuthenticationTargetUrlRequestHandler {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private String targetUrlParameter = null;
|
||||
|
||||
private String defaultTargetUrl = "/";
|
||||
|
||||
private boolean alwaysUseDefaultTargetUrl = false;
|
||||
|
||||
private boolean useReferer = false;
|
||||
|
||||
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
|
||||
|
||||
protected AbstractAuthenticationTargetUrlRequestHandler() {
|
||||
@@ -78,13 +79,12 @@ public abstract class AbstractAuthenticationTargetUrlRequestHandler {
|
||||
* <p>
|
||||
* The redirect will not be performed if the response has already been committed.
|
||||
*/
|
||||
protected void handle(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication) throws IOException, ServletException {
|
||||
protected void handle(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
||||
throws IOException, ServletException {
|
||||
String targetUrl = determineTargetUrl(request, response, authentication);
|
||||
|
||||
if (response.isCommitted()) {
|
||||
logger.debug("Response has already been committed. Unable to redirect to "
|
||||
+ targetUrl);
|
||||
logger.debug("Response has already been committed. Unable to redirect to " + targetUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -96,16 +96,15 @@ public abstract class AbstractAuthenticationTargetUrlRequestHandler {
|
||||
*
|
||||
* @since 5.2
|
||||
*/
|
||||
protected String determineTargetUrl(HttpServletRequest request,
|
||||
HttpServletResponse response, Authentication authentication) {
|
||||
protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication) {
|
||||
return determineTargetUrl(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the target URL according to the logic defined in the main class Javadoc.
|
||||
*/
|
||||
protected String determineTargetUrl(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response) {
|
||||
if (isAlwaysUseDefaultTargetUrl()) {
|
||||
return defaultTargetUrl;
|
||||
}
|
||||
@@ -140,7 +139,6 @@ public abstract class AbstractAuthenticationTargetUrlRequestHandler {
|
||||
* Supplies the default target Url that will be used if no saved request is found or
|
||||
* the {@code alwaysUseDefaultTargetUrl} property is set to true. If not set, defaults
|
||||
* to {@code /}.
|
||||
*
|
||||
* @return the defaultTargetUrl property
|
||||
*/
|
||||
protected final String getDefaultTargetUrl() {
|
||||
@@ -154,7 +152,6 @@ public abstract class AbstractAuthenticationTargetUrlRequestHandler {
|
||||
* context path, and should include the leading <code>/</code>. Alternatively,
|
||||
* inclusion of a scheme name (such as "http://" or "https://") as the prefix will
|
||||
* denote a fully-qualified URL and this is also supported.
|
||||
*
|
||||
* @param defaultTargetUrl
|
||||
*/
|
||||
public void setDefaultTargetUrl(String defaultTargetUrl) {
|
||||
@@ -178,7 +175,6 @@ public abstract class AbstractAuthenticationTargetUrlRequestHandler {
|
||||
/**
|
||||
* If this property is set, the current request will be checked for this a parameter
|
||||
* with this name and the value used as the target URL if present.
|
||||
*
|
||||
* @param targetUrlParameter the name of the parameter containing the encoded target
|
||||
* URL. Defaults to null.
|
||||
*/
|
||||
|
||||
+9
-12
@@ -42,21 +42,22 @@ import org.springframework.web.filter.GenericFilterBean;
|
||||
* @author Ben Alex
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
public class AnonymousAuthenticationFilter extends GenericFilterBean implements
|
||||
InitializingBean {
|
||||
public class AnonymousAuthenticationFilter extends GenericFilterBean implements InitializingBean {
|
||||
|
||||
// ~ Instance fields
|
||||
// ================================================================================================
|
||||
|
||||
private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
|
||||
|
||||
private String key;
|
||||
|
||||
private Object principal;
|
||||
|
||||
private List<GrantedAuthority> authorities;
|
||||
|
||||
/**
|
||||
* Creates a filter with a principal named "anonymousUser" and the single authority
|
||||
* "ROLE_ANONYMOUS".
|
||||
*
|
||||
* @param key the key to identify tokens created by this filter
|
||||
*/
|
||||
public AnonymousAuthenticationFilter(String key) {
|
||||
@@ -64,13 +65,11 @@ public class AnonymousAuthenticationFilter extends GenericFilterBean implements
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param key key the key to identify tokens created by this filter
|
||||
* @param principal the principal which will be used to represent anonymous users
|
||||
* @param authorities the authority list for anonymous users
|
||||
*/
|
||||
public AnonymousAuthenticationFilter(String key, Object principal,
|
||||
List<GrantedAuthority> authorities) {
|
||||
public AnonymousAuthenticationFilter(String key, Object principal, List<GrantedAuthority> authorities) {
|
||||
Assert.hasLength(key, "key cannot be null or empty");
|
||||
Assert.notNull(principal, "Anonymous authentication principal must be set");
|
||||
Assert.notNull(authorities, "Anonymous authorities must be set");
|
||||
@@ -93,8 +92,7 @@ public class AnonymousAuthenticationFilter extends GenericFilterBean implements
|
||||
throws IOException, ServletException {
|
||||
|
||||
if (SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||
SecurityContextHolder.getContext().setAuthentication(
|
||||
createAuthentication((HttpServletRequest) req));
|
||||
SecurityContextHolder.getContext().setAuthentication(createAuthentication((HttpServletRequest) req));
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Populated SecurityContextHolder with anonymous token: '"
|
||||
@@ -112,8 +110,7 @@ public class AnonymousAuthenticationFilter extends GenericFilterBean implements
|
||||
}
|
||||
|
||||
protected Authentication createAuthentication(HttpServletRequest request) {
|
||||
AnonymousAuthenticationToken auth = new AnonymousAuthenticationToken(key,
|
||||
principal, authorities);
|
||||
AnonymousAuthenticationToken auth = new AnonymousAuthenticationToken(key, principal, authorities);
|
||||
auth.setDetails(authenticationDetailsSource.buildDetails(request));
|
||||
|
||||
return auth;
|
||||
@@ -121,8 +118,7 @@ public class AnonymousAuthenticationFilter extends GenericFilterBean implements
|
||||
|
||||
public void setAuthenticationDetailsSource(
|
||||
AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource) {
|
||||
Assert.notNull(authenticationDetailsSource,
|
||||
"AuthenticationDetailsSource required");
|
||||
Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");
|
||||
this.authenticationDetailsSource = authenticationDetailsSource;
|
||||
}
|
||||
|
||||
@@ -133,4 +129,5 @@ public class AnonymousAuthenticationFilter extends GenericFilterBean implements
|
||||
public List<GrantedAuthority> getAuthorities() {
|
||||
return authorities;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-6
@@ -23,12 +23,11 @@ import org.springframework.security.core.AuthenticationException;
|
||||
|
||||
/**
|
||||
* A strategy used for converting from a {@link HttpServletRequest} to an
|
||||
* {@link Authentication} of particular type. Used to authenticate with
|
||||
* appropriate {@link AuthenticationManager}. If the result is null, then it
|
||||
* signals that no authentication attempt should be made. It is also possible to
|
||||
* throw {@link AuthenticationException} within the
|
||||
* {@link #convert(HttpServletRequest)} if there was invalid Authentication
|
||||
* scheme value.
|
||||
* {@link Authentication} of particular type. Used to authenticate with appropriate
|
||||
* {@link AuthenticationManager}. If the result is null, then it signals that no
|
||||
* authentication attempt should be made. It is also possible to throw
|
||||
* {@link AuthenticationException} within the {@link #convert(HttpServletRequest)} if
|
||||
* there was invalid Authentication scheme value.
|
||||
*
|
||||
* @author Sergey Bespalov
|
||||
* @since 5.2.0
|
||||
|
||||
+1
@@ -45,4 +45,5 @@ public class AuthenticationEntryPointFailureHandler implements AuthenticationFai
|
||||
AuthenticationException exception) throws IOException, ServletException {
|
||||
this.authenticationEntryPoint.commence(request, response, exception);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -45,7 +45,7 @@ public interface AuthenticationFailureHandler {
|
||||
* @param exception the exception which was thrown to reject the authentication
|
||||
* request.
|
||||
*/
|
||||
void onAuthenticationFailure(HttpServletRequest request,
|
||||
HttpServletResponse response, AuthenticationException exception)
|
||||
throws IOException, ServletException;
|
||||
void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException exception) throws IOException, ServletException;
|
||||
|
||||
}
|
||||
|
||||
+19
-16
@@ -36,26 +36,24 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
/**
|
||||
* A {@link Filter} that performs authentication of a particular request. An
|
||||
* outline of the logic:
|
||||
* A {@link Filter} that performs authentication of a particular request. An outline of
|
||||
* the logic:
|
||||
*
|
||||
* <ul>
|
||||
* <li>A request comes in and if it does not match
|
||||
* {@link #setRequestMatcher(RequestMatcher)}, then this filter does nothing and
|
||||
* the {@link FilterChain} is continued. If it does match then...</li>
|
||||
* <li>An attempt to convert the {@link HttpServletRequest} into an
|
||||
* {@link Authentication} is made. If the result is empty, then the filter does
|
||||
* nothing more and the {@link FilterChain} is continued. If it does create an
|
||||
* {@link Authentication}...</li>
|
||||
* {@link #setRequestMatcher(RequestMatcher)}, then this filter does nothing and the
|
||||
* {@link FilterChain} is continued. If it does match then...</li>
|
||||
* <li>An attempt to convert the {@link HttpServletRequest} into an {@link Authentication}
|
||||
* is made. If the result is empty, then the filter does nothing more and the
|
||||
* {@link FilterChain} is continued. If it does create an {@link Authentication}...</li>
|
||||
* <li>The {@link AuthenticationManager} specified in
|
||||
* {@link #GenericAuthenticationFilter(AuthenticationManager)} is used to
|
||||
* perform authentication.</li>
|
||||
* <li>The {@link AuthenticationManagerResolver} specified in
|
||||
* {@link #GenericAuthenticationFilter(AuthenticationManagerResolver)} is used
|
||||
* to resolve the appropriate authentication manager from context to perform
|
||||
* {@link #GenericAuthenticationFilter(AuthenticationManager)} is used to perform
|
||||
* authentication.</li>
|
||||
* <li>If authentication is successful, {@link AuthenticationSuccessHandler} is
|
||||
* invoked and the authentication is set on {@link SecurityContextHolder}, else
|
||||
* <li>The {@link AuthenticationManagerResolver} specified in
|
||||
* {@link #GenericAuthenticationFilter(AuthenticationManagerResolver)} is used to resolve
|
||||
* the appropriate authentication manager from context to perform authentication.</li>
|
||||
* <li>If authentication is successful, {@link AuthenticationSuccessHandler} is invoked
|
||||
* and the authentication is set on {@link SecurityContextHolder}, else
|
||||
* {@link AuthenticationFailureHandler} is invoked</li>
|
||||
* </ul>
|
||||
*
|
||||
@@ -65,10 +63,14 @@ import org.springframework.web.filter.OncePerRequestFilter;
|
||||
public class AuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
private RequestMatcher requestMatcher = AnyRequestMatcher.INSTANCE;
|
||||
|
||||
private AuthenticationConverter authenticationConverter;
|
||||
|
||||
private AuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
|
||||
|
||||
private AuthenticationFailureHandler failureHandler = new AuthenticationEntryPointFailureHandler(
|
||||
new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
|
||||
|
||||
private AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver;
|
||||
|
||||
public AuthenticationFilter(AuthenticationManager authenticationManager,
|
||||
@@ -152,7 +154,8 @@ public class AuthenticationFilter extends OncePerRequestFilter {
|
||||
}
|
||||
|
||||
successfulAuthentication(request, response, filterChain, authenticationResult);
|
||||
} catch (AuthenticationException e) {
|
||||
}
|
||||
catch (AuthenticationException e) {
|
||||
unsuccessfulAuthentication(request, response, e);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-9
@@ -41,31 +41,28 @@ public interface AuthenticationSuccessHandler {
|
||||
|
||||
/**
|
||||
* Called when a user has been successfully authenticated.
|
||||
*
|
||||
* @param request the request which caused the successful authentication
|
||||
* @param response the response
|
||||
* @param chain the {@link FilterChain} which can be used to proceed other filters in the chain
|
||||
* @param chain the {@link FilterChain} which can be used to proceed other filters in
|
||||
* the chain
|
||||
* @param authentication the <tt>Authentication</tt> object which was created during
|
||||
* the authentication process.
|
||||
* @since 5.2.0
|
||||
*/
|
||||
default void onAuthenticationSuccess(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain chain, Authentication authentication)
|
||||
throws IOException, ServletException{
|
||||
default void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
|
||||
Authentication authentication) throws IOException, ServletException {
|
||||
onAuthenticationSuccess(request, response, authentication);
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a user has been successfully authenticated.
|
||||
*
|
||||
* @param request the request which caused the successful authentication
|
||||
* @param response the response
|
||||
* @param authentication the <tt>Authentication</tt> object which was created during
|
||||
* the authentication process.
|
||||
*/
|
||||
void onAuthenticationSuccess(HttpServletRequest request,
|
||||
HttpServletResponse response, Authentication authentication)
|
||||
throws IOException, ServletException;
|
||||
void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication) throws IOException, ServletException;
|
||||
|
||||
}
|
||||
|
||||
+5
-4
@@ -58,15 +58,15 @@ import org.springframework.util.Assert;
|
||||
* @author Mike Wiesner
|
||||
* @since 3.0.2
|
||||
*/
|
||||
public class DelegatingAuthenticationEntryPoint implements AuthenticationEntryPoint,
|
||||
InitializingBean {
|
||||
public class DelegatingAuthenticationEntryPoint implements AuthenticationEntryPoint, InitializingBean {
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints;
|
||||
|
||||
private AuthenticationEntryPoint defaultEntryPoint;
|
||||
|
||||
public DelegatingAuthenticationEntryPoint(
|
||||
LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints) {
|
||||
public DelegatingAuthenticationEntryPoint(LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints) {
|
||||
this.entryPoints = entryPoints;
|
||||
}
|
||||
|
||||
@@ -106,4 +106,5 @@ public class DelegatingAuthenticationEntryPoint implements AuthenticationEntryPo
|
||||
Assert.notEmpty(entryPoints, "entryPoints must be specified");
|
||||
Assert.notNull(defaultEntryPoint, "defaultEntryPoint must be specified");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-8
@@ -35,8 +35,7 @@ import java.util.Map;
|
||||
* @author Kazuki Shimizu
|
||||
* @since 4.0
|
||||
*/
|
||||
public class DelegatingAuthenticationFailureHandler implements
|
||||
AuthenticationFailureHandler {
|
||||
public class DelegatingAuthenticationFailureHandler implements AuthenticationFailureHandler {
|
||||
|
||||
private final LinkedHashMap<Class<? extends AuthenticationException>, AuthenticationFailureHandler> handlers;
|
||||
|
||||
@@ -44,7 +43,6 @@ public class DelegatingAuthenticationFailureHandler implements
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param handlers a map of the {@link AuthenticationException} class to the
|
||||
* {@link AuthenticationFailureHandler} that should be used. Each is considered in the
|
||||
* order they are specified and only the first {@link AuthenticationFailureHandler} is
|
||||
@@ -66,13 +64,11 @@ public class DelegatingAuthenticationFailureHandler implements
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onAuthenticationFailure(HttpServletRequest request,
|
||||
HttpServletResponse response, AuthenticationException exception)
|
||||
throws IOException, ServletException {
|
||||
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException exception) throws IOException, ServletException {
|
||||
for (Map.Entry<Class<? extends AuthenticationException>, AuthenticationFailureHandler> entry : handlers
|
||||
.entrySet()) {
|
||||
Class<? extends AuthenticationException> handlerMappedExceptionClass = entry
|
||||
.getKey();
|
||||
Class<? extends AuthenticationException> handlerMappedExceptionClass = entry.getKey();
|
||||
if (handlerMappedExceptionClass.isAssignableFrom(exception.getClass())) {
|
||||
AuthenticationFailureHandler handler = entry.getValue();
|
||||
handler.onAuthenticationFailure(request, response, exception);
|
||||
|
||||
+7
-11
@@ -40,14 +40,13 @@ import org.springframework.util.Assert;
|
||||
* @author Luke Taylor
|
||||
* @since 3.0
|
||||
*/
|
||||
public class ExceptionMappingAuthenticationFailureHandler extends
|
||||
SimpleUrlAuthenticationFailureHandler {
|
||||
public class ExceptionMappingAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
|
||||
|
||||
private final Map<String, String> failureUrlMap = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void onAuthenticationFailure(HttpServletRequest request,
|
||||
HttpServletResponse response, AuthenticationException exception)
|
||||
throws IOException, ServletException {
|
||||
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException exception) throws IOException, ServletException {
|
||||
String url = failureUrlMap.get(exception.getClass().getName());
|
||||
|
||||
if (url != null) {
|
||||
@@ -60,10 +59,8 @@ public class ExceptionMappingAuthenticationFailureHandler extends
|
||||
|
||||
/**
|
||||
* Sets the map of exception types (by name) to URLs.
|
||||
*
|
||||
* @param failureUrlMap the map keyed by the fully-qualified name of the exception
|
||||
* class, with the corresponding failure URL as the value.
|
||||
*
|
||||
* @throws IllegalArgumentException if the entries are not Strings or the URL is not
|
||||
* valid.
|
||||
*/
|
||||
@@ -72,12 +69,11 @@ public class ExceptionMappingAuthenticationFailureHandler extends
|
||||
for (Map.Entry<?, ?> entry : failureUrlMap.entrySet()) {
|
||||
Object exception = entry.getKey();
|
||||
Object url = entry.getValue();
|
||||
Assert.isInstanceOf(String.class, exception,
|
||||
"Exception key must be a String (the exception classname).");
|
||||
Assert.isInstanceOf(String.class, exception, "Exception key must be a String (the exception classname).");
|
||||
Assert.isInstanceOf(String.class, url, "URL must be a String");
|
||||
Assert.isTrue(UrlUtils.isValidRedirectUrl((String) url),
|
||||
() -> "Not a valid redirect URL: " + url);
|
||||
Assert.isTrue(UrlUtils.isValidRedirectUrl((String) url), () -> "Not a valid redirect URL: " + url);
|
||||
this.failureUrlMap.put((String) exception, (String) url);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+54
-53
@@ -1,53 +1,54 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.web.authentication;
|
||||
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.WebAttributes;
|
||||
import org.springframework.security.web.util.UrlUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Forward Authentication Failure Handler
|
||||
* </p>
|
||||
*
|
||||
* @author Shazin Sadakath
|
||||
* @since 4.1
|
||||
*/
|
||||
public class ForwardAuthenticationFailureHandler implements AuthenticationFailureHandler {
|
||||
|
||||
private final String forwardUrl;
|
||||
|
||||
/**
|
||||
* @param forwardUrl
|
||||
*/
|
||||
public ForwardAuthenticationFailureHandler(String forwardUrl) {
|
||||
Assert.isTrue(UrlUtils.isValidRedirectUrl(forwardUrl),
|
||||
() -> "'" + forwardUrl + "' is not a valid forward URL");
|
||||
this.forwardUrl = forwardUrl;
|
||||
}
|
||||
|
||||
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
|
||||
request.setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception);
|
||||
request.getRequestDispatcher(forwardUrl).forward(request, response);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.web.authentication;
|
||||
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.WebAttributes;
|
||||
import org.springframework.security.web.util.UrlUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Forward Authentication Failure Handler
|
||||
* </p>
|
||||
*
|
||||
* @author Shazin Sadakath
|
||||
* @since 4.1
|
||||
*/
|
||||
public class ForwardAuthenticationFailureHandler implements AuthenticationFailureHandler {
|
||||
|
||||
private final String forwardUrl;
|
||||
|
||||
/**
|
||||
* @param forwardUrl
|
||||
*/
|
||||
public ForwardAuthenticationFailureHandler(String forwardUrl) {
|
||||
Assert.isTrue(UrlUtils.isValidRedirectUrl(forwardUrl), () -> "'" + forwardUrl + "' is not a valid forward URL");
|
||||
this.forwardUrl = forwardUrl;
|
||||
}
|
||||
|
||||
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException exception) throws IOException, ServletException {
|
||||
request.setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception);
|
||||
request.getRequestDispatcher(forwardUrl).forward(request, response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+53
-52
@@ -1,52 +1,53 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.web.authentication;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.util.UrlUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Forward Authentication Success Handler
|
||||
* </p>
|
||||
*
|
||||
* @author Shazin Sadakath
|
||||
* @since 4.1
|
||||
*
|
||||
*/
|
||||
public class ForwardAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
|
||||
|
||||
private final String forwardUrl;
|
||||
|
||||
/**
|
||||
* @param forwardUrl
|
||||
*/
|
||||
public ForwardAuthenticationSuccessHandler(String forwardUrl) {
|
||||
Assert.isTrue(UrlUtils.isValidRedirectUrl(forwardUrl),
|
||||
() -> "'" + forwardUrl + "' is not a valid forward URL");
|
||||
this.forwardUrl = forwardUrl;
|
||||
}
|
||||
|
||||
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
|
||||
request.getRequestDispatcher(forwardUrl).forward(request, response);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.web.authentication;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.util.UrlUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Forward Authentication Success Handler
|
||||
* </p>
|
||||
*
|
||||
* @author Shazin Sadakath
|
||||
* @since 4.1
|
||||
*
|
||||
*/
|
||||
public class ForwardAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
|
||||
|
||||
private final String forwardUrl;
|
||||
|
||||
/**
|
||||
* @param forwardUrl
|
||||
*/
|
||||
public ForwardAuthenticationSuccessHandler(String forwardUrl) {
|
||||
Assert.isTrue(UrlUtils.isValidRedirectUrl(forwardUrl), () -> "'" + forwardUrl + "' is not a valid forward URL");
|
||||
this.forwardUrl = forwardUrl;
|
||||
}
|
||||
|
||||
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication) throws IOException, ServletException {
|
||||
request.getRequestDispatcher(forwardUrl).forward(request, response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-3
@@ -39,22 +39,23 @@ import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
* <code>HttpServletResponse.SC_FORBIDDEN</code> (403 error).
|
||||
*
|
||||
* @see org.springframework.security.web.access.ExceptionTranslationFilter
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @author Ruud Senden
|
||||
* @since 2.0
|
||||
*/
|
||||
public class Http403ForbiddenEntryPoint implements AuthenticationEntryPoint {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(Http403ForbiddenEntryPoint.class);
|
||||
|
||||
/**
|
||||
* Always returns a 403 error code to the client.
|
||||
*/
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException arg2) throws IOException {
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException arg2)
|
||||
throws IOException {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Pre-authenticated entry point called. Rejecting access");
|
||||
}
|
||||
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-1
@@ -32,11 +32,11 @@ import org.springframework.util.Assert;
|
||||
* @since 4.0
|
||||
*/
|
||||
public final class HttpStatusEntryPoint implements AuthenticationEntryPoint {
|
||||
|
||||
private final HttpStatus httpStatus;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param httpStatus the HttpStatus to set
|
||||
*/
|
||||
public HttpStatusEntryPoint(HttpStatus httpStatus) {
|
||||
@@ -48,4 +48,5 @@ public final class HttpStatusEntryPoint implements AuthenticationEntryPoint {
|
||||
AuthenticationException authException) {
|
||||
response.setStatus(httpStatus.value());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+15
-26
@@ -62,13 +62,12 @@ import org.springframework.util.StringUtils;
|
||||
* @author Luke Taylor
|
||||
* @since 3.0
|
||||
*/
|
||||
public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoint,
|
||||
InitializingBean {
|
||||
public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoint, InitializingBean {
|
||||
|
||||
// ~ Static fields/initializers
|
||||
// =====================================================================================
|
||||
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(LoginUrlAuthenticationEntryPoint.class);
|
||||
private static final Log logger = LogFactory.getLog(LoginUrlAuthenticationEntryPoint.class);
|
||||
|
||||
// ~ Instance fields
|
||||
// ================================================================================================
|
||||
@@ -86,7 +85,6 @@ public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoin
|
||||
private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param loginFormUrl URL where the login page can be found. Should either be
|
||||
* relative to the web-app context path (include a leading {@code /}) or an absolute
|
||||
* URL.
|
||||
@@ -100,13 +98,10 @@ public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoin
|
||||
// ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
Assert.isTrue(
|
||||
StringUtils.hasText(loginFormUrl)
|
||||
&& UrlUtils.isValidRedirectUrl(loginFormUrl),
|
||||
Assert.isTrue(StringUtils.hasText(loginFormUrl) && UrlUtils.isValidRedirectUrl(loginFormUrl),
|
||||
"loginFormUrl must be specified and must be a valid redirect URL");
|
||||
if (useForward && UrlUtils.isAbsoluteUrl(loginFormUrl)) {
|
||||
throw new IllegalArgumentException(
|
||||
"useForward must be false if using an absolute loginFormURL");
|
||||
throw new IllegalArgumentException("useForward must be false if using an absolute loginFormURL");
|
||||
}
|
||||
Assert.notNull(portMapper, "portMapper must be specified");
|
||||
Assert.notNull(portResolver, "portResolver must be specified");
|
||||
@@ -115,14 +110,13 @@ public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoin
|
||||
/**
|
||||
* Allows subclasses to modify the login form URL that should be applicable for a
|
||||
* given request.
|
||||
*
|
||||
* @param request the request
|
||||
* @param response the response
|
||||
* @param exception the exception
|
||||
* @return the URL (cannot be null or empty; defaults to {@link #getLoginFormUrl()})
|
||||
*/
|
||||
protected String determineUrlToUseForThisRequest(HttpServletRequest request,
|
||||
HttpServletResponse response, AuthenticationException exception) {
|
||||
protected String determineUrlToUseForThisRequest(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException exception) {
|
||||
|
||||
return getLoginFormUrl();
|
||||
}
|
||||
@@ -145,8 +139,7 @@ public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoin
|
||||
}
|
||||
|
||||
if (redirectUrl == null) {
|
||||
String loginForm = determineUrlToUseForThisRequest(request, response,
|
||||
authException);
|
||||
String loginForm = determineUrlToUseForThisRequest(request, response, authException);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Server side forward to: " + loginForm);
|
||||
@@ -169,11 +162,10 @@ public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoin
|
||||
redirectStrategy.sendRedirect(request, response, redirectUrl);
|
||||
}
|
||||
|
||||
protected String buildRedirectUrlToLoginPage(HttpServletRequest request,
|
||||
HttpServletResponse response, AuthenticationException authException) {
|
||||
protected String buildRedirectUrlToLoginPage(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException authException) {
|
||||
|
||||
String loginForm = determineUrlToUseForThisRequest(request, response,
|
||||
authException);
|
||||
String loginForm = determineUrlToUseForThisRequest(request, response, authException);
|
||||
|
||||
if (UrlUtils.isAbsoluteUrl(loginForm)) {
|
||||
return loginForm;
|
||||
@@ -199,8 +191,7 @@ public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoin
|
||||
urlBuilder.setPort(httpsPort);
|
||||
}
|
||||
else {
|
||||
logger.warn("Unable to redirect to HTTPS as no port mapping found for HTTP port "
|
||||
+ serverPort);
|
||||
logger.warn("Unable to redirect to HTTPS as no port mapping found for HTTP port " + serverPort);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,8 +202,7 @@ public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoin
|
||||
* Builds a URL to redirect the supplied request to HTTPS. Used to redirect the
|
||||
* current request to HTTPS, before doing a forward to the login page.
|
||||
*/
|
||||
protected String buildHttpsRedirectUrlForRequest(HttpServletRequest request)
|
||||
throws IOException, ServletException {
|
||||
protected String buildHttpsRedirectUrlForRequest(HttpServletRequest request) throws IOException, ServletException {
|
||||
|
||||
int serverPort = portResolver.getServerPort(request);
|
||||
Integer httpsPort = portMapper.lookupHttpsPort(serverPort);
|
||||
@@ -231,8 +221,7 @@ public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoin
|
||||
}
|
||||
|
||||
// Fall through to server-side forward with warning message
|
||||
logger.warn("Unable to redirect to HTTPS as no port mapping found for HTTP port "
|
||||
+ serverPort);
|
||||
logger.warn("Unable to redirect to HTTPS as no port mapping found for HTTP port " + serverPort);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -277,7 +266,6 @@ public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoin
|
||||
/**
|
||||
* Tells if we are to do a forward to the {@code loginFormUrl} using the
|
||||
* {@code RequestDispatcher}, instead of a 302 redirect.
|
||||
*
|
||||
* @param useForward true if a forward to the login page should be used. Must be false
|
||||
* (the default) if {@code loginFormUrl} is set to an absolute value.
|
||||
*/
|
||||
@@ -288,4 +276,5 @@ public class LoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoin
|
||||
protected boolean isUseForward() {
|
||||
return useForward;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-2
@@ -30,11 +30,11 @@ import javax.servlet.http.HttpServletResponse;
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public class NullRememberMeServices implements RememberMeServices {
|
||||
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
public Authentication autoLogin(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -44,4 +44,5 @@ public class NullRememberMeServices implements RememberMeServices {
|
||||
public void loginSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication successfulAuthentication) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+7
-9
@@ -33,20 +33,21 @@ import org.springframework.security.core.Authentication;
|
||||
* this interface.
|
||||
* <p>
|
||||
* Implementations may implement any type of remember-me capability they wish. Rolling
|
||||
* cookies (as per <a
|
||||
* href="https://fishbowl.pastiche.org/2004/01/19/persistent_login_cookie_best_practice">
|
||||
* cookies (as per <a href=
|
||||
* "https://fishbowl.pastiche.org/2004/01/19/persistent_login_cookie_best_practice">
|
||||
* https://fishbowl.pastiche.org/2004/01/19/persistent_login_cookie_best_practice</a>) can
|
||||
* be used, as can simple implementations that don't require a persistent store.
|
||||
* Implementations also determine the validity period of a remember-me cookie. This
|
||||
* interface has been designed to accommodate any of these remember-me models.
|
||||
* <p>
|
||||
* This interface does not define how remember-me services should offer a
|
||||
* "cancel all remember-me tokens" type capability, as this will be implementation
|
||||
* specific and requires no hooks into Spring Security.
|
||||
* This interface does not define how remember-me services should offer a "cancel all
|
||||
* remember-me tokens" type capability, as this will be implementation specific and
|
||||
* requires no hooks into Spring Security.
|
||||
*
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public interface RememberMeServices {
|
||||
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
@@ -66,10 +67,8 @@ public interface RememberMeServices {
|
||||
* by the web application. It is recommended
|
||||
* {@link org.springframework.security.authentication.RememberMeAuthenticationToken}
|
||||
* be used in most cases, as it has a corresponding authentication provider.
|
||||
*
|
||||
* @param request to look for a remember-me token within
|
||||
* @param response to change, cancel or modify the remember-me token
|
||||
*
|
||||
* @return a valid authentication object, or <code>null</code> if the request should
|
||||
* not be authenticated
|
||||
*/
|
||||
@@ -80,7 +79,6 @@ public interface RememberMeServices {
|
||||
* supplied by the user were missing or otherwise invalid. Implementations should
|
||||
* invalidate any and all remember-me tokens indicated in the
|
||||
* <code>HttpServletRequest</code>.
|
||||
*
|
||||
* @param request that contained an invalid authentication request
|
||||
* @param response to change, cancel or modify the remember-me token
|
||||
*/
|
||||
@@ -93,7 +91,6 @@ public interface RememberMeServices {
|
||||
* implementations should typically look for a request parameter that indicates the
|
||||
* browser has presented an explicit request for authentication to be remembered, such
|
||||
* as the presence of a HTTP POST parameter.
|
||||
*
|
||||
* @param request that contained the valid authentication request
|
||||
* @param response to change, cancel or modify the remember-me token
|
||||
* @param successfulAuthentication representing the successfully authenticated
|
||||
@@ -101,4 +98,5 @@ public interface RememberMeServices {
|
||||
*/
|
||||
void loginSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication successfulAuthentication);
|
||||
|
||||
}
|
||||
|
||||
+24
-27
@@ -32,48 +32,45 @@ import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
|
||||
|
||||
/**
|
||||
* An authentication success strategy which can make use of the
|
||||
* {@link org.springframework.security.web.savedrequest.DefaultSavedRequest} which may have been stored in the session by the
|
||||
* {@link ExceptionTranslationFilter}. When such a request is intercepted and requires
|
||||
* authentication, the request data is stored to record the original destination before
|
||||
* the authentication process commenced, and to allow the request to be reconstructed when
|
||||
* a redirect to the same URL occurs. This class is responsible for performing the
|
||||
* redirect to the original URL if appropriate.
|
||||
* {@link org.springframework.security.web.savedrequest.DefaultSavedRequest} which may
|
||||
* have been stored in the session by the {@link ExceptionTranslationFilter}. When such a
|
||||
* request is intercepted and requires authentication, the request data is stored to
|
||||
* record the original destination before the authentication process commenced, and to
|
||||
* allow the request to be reconstructed when a redirect to the same URL occurs. This
|
||||
* class is responsible for performing the redirect to the original URL if appropriate.
|
||||
* <p>
|
||||
* Following a successful authentication, it decides on the redirect destination, based on
|
||||
* the following scenarios:
|
||||
* <ul>
|
||||
* <li>
|
||||
* If the {@code alwaysUseDefaultTargetUrl} property is set to true, the
|
||||
* <li>If the {@code alwaysUseDefaultTargetUrl} property is set to true, the
|
||||
* {@code defaultTargetUrl} will be used for the destination. Any
|
||||
* {@code DefaultSavedRequest} stored in the session will be removed.</li>
|
||||
* <li>
|
||||
* If the {@code targetUrlParameter} has been set on the request, the value will be used
|
||||
* as the destination. Any {@code DefaultSavedRequest} will again be removed.</li>
|
||||
* <li>
|
||||
* If a {@link org.springframework.security.web.savedrequest.SavedRequest} is found in the {@code RequestCache} (as set by the
|
||||
* {@link ExceptionTranslationFilter} to record the original destination before the
|
||||
* authentication process commenced), a redirect will be performed to the Url of that
|
||||
* original destination. The {@code SavedRequest} object will remain cached and be picked
|
||||
* up when the redirected request is received (See
|
||||
* <a href="{@docRoot}/org/springframework/security/web/savedrequest/SavedRequestAwareWrapper.html">SavedRequestAwareWrapper</a>).
|
||||
* <li>If the {@code targetUrlParameter} has been set on the request, the value will be
|
||||
* used as the destination. Any {@code DefaultSavedRequest} will again be removed.</li>
|
||||
* <li>If a {@link org.springframework.security.web.savedrequest.SavedRequest} is found in
|
||||
* the {@code RequestCache} (as set by the {@link ExceptionTranslationFilter} to record
|
||||
* the original destination before the authentication process commenced), a redirect will
|
||||
* be performed to the Url of that original destination. The {@code SavedRequest} object
|
||||
* will remain cached and be picked up when the redirected request is received (See
|
||||
* <a href="
|
||||
* {@docRoot}/org/springframework/security/web/savedrequest/SavedRequestAwareWrapper.html">SavedRequestAwareWrapper</a>).
|
||||
* </li>
|
||||
* <li>
|
||||
* If no {@link org.springframework.security.web.savedrequest.SavedRequest} is found, it will delegate to the base class.</li>
|
||||
* <li>If no {@link org.springframework.security.web.savedrequest.SavedRequest} is found,
|
||||
* it will delegate to the base class.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 3.0
|
||||
*/
|
||||
public class SavedRequestAwareAuthenticationSuccessHandler extends
|
||||
SimpleUrlAuthenticationSuccessHandler {
|
||||
public class SavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private RequestCache requestCache = new HttpSessionRequestCache();
|
||||
|
||||
@Override
|
||||
public void onAuthenticationSuccess(HttpServletRequest request,
|
||||
HttpServletResponse response, Authentication authentication)
|
||||
throws ServletException, IOException {
|
||||
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication) throws ServletException, IOException {
|
||||
SavedRequest savedRequest = requestCache.getRequest(request, response);
|
||||
|
||||
if (savedRequest == null) {
|
||||
@@ -83,8 +80,7 @@ public class SavedRequestAwareAuthenticationSuccessHandler extends
|
||||
}
|
||||
String targetUrlParameter = getTargetUrlParameter();
|
||||
if (isAlwaysUseDefaultTargetUrl()
|
||||
|| (targetUrlParameter != null && StringUtils.hasText(request
|
||||
.getParameter(targetUrlParameter)))) {
|
||||
|| (targetUrlParameter != null && StringUtils.hasText(request.getParameter(targetUrlParameter)))) {
|
||||
requestCache.removeRequest(request, response);
|
||||
super.onAuthenticationSuccess(request, response, authentication);
|
||||
|
||||
@@ -102,4 +98,5 @@ public class SavedRequestAwareAuthenticationSuccessHandler extends
|
||||
public void setRequestCache(RequestCache requestCache) {
|
||||
this.requestCache = requestCache;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+12
-14
@@ -45,13 +45,16 @@ import org.springframework.util.Assert;
|
||||
* @author Luke Taylor
|
||||
* @since 3.0
|
||||
*/
|
||||
public class SimpleUrlAuthenticationFailureHandler implements
|
||||
AuthenticationFailureHandler {
|
||||
public class SimpleUrlAuthenticationFailureHandler implements AuthenticationFailureHandler {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private String defaultFailureUrl;
|
||||
|
||||
private boolean forwardToDestination = false;
|
||||
|
||||
private boolean allowSessionCreation = true;
|
||||
|
||||
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
|
||||
|
||||
public SimpleUrlAuthenticationFailureHandler() {
|
||||
@@ -68,15 +71,13 @@ public class SimpleUrlAuthenticationFailureHandler implements
|
||||
* If redirecting or forwarding, {@code saveException} will be called to cache the
|
||||
* exception for use in the target view.
|
||||
*/
|
||||
public void onAuthenticationFailure(HttpServletRequest request,
|
||||
HttpServletResponse response, AuthenticationException exception)
|
||||
throws IOException, ServletException {
|
||||
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException exception) throws IOException, ServletException {
|
||||
|
||||
if (defaultFailureUrl == null) {
|
||||
logger.debug("No failure URL set, sending 401 Unauthorized error");
|
||||
|
||||
response.sendError(HttpStatus.UNAUTHORIZED.value(),
|
||||
HttpStatus.UNAUTHORIZED.getReasonPhrase());
|
||||
response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase());
|
||||
}
|
||||
else {
|
||||
saveException(request, exception);
|
||||
@@ -84,8 +85,7 @@ public class SimpleUrlAuthenticationFailureHandler implements
|
||||
if (forwardToDestination) {
|
||||
logger.debug("Forwarding to " + defaultFailureUrl);
|
||||
|
||||
request.getRequestDispatcher(defaultFailureUrl)
|
||||
.forward(request, response);
|
||||
request.getRequestDispatcher(defaultFailureUrl).forward(request, response);
|
||||
}
|
||||
else {
|
||||
logger.debug("Redirecting to " + defaultFailureUrl);
|
||||
@@ -102,8 +102,7 @@ public class SimpleUrlAuthenticationFailureHandler implements
|
||||
* session and {@code allowSessionCreation} is {@code true} a session will be created.
|
||||
* Otherwise the exception will not be stored.
|
||||
*/
|
||||
protected final void saveException(HttpServletRequest request,
|
||||
AuthenticationException exception) {
|
||||
protected final void saveException(HttpServletRequest request, AuthenticationException exception) {
|
||||
if (forwardToDestination) {
|
||||
request.setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception);
|
||||
}
|
||||
@@ -111,15 +110,13 @@ public class SimpleUrlAuthenticationFailureHandler implements
|
||||
HttpSession session = request.getSession(false);
|
||||
|
||||
if (session != null || allowSessionCreation) {
|
||||
request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION,
|
||||
exception);
|
||||
request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL which will be used as the failure destination.
|
||||
*
|
||||
* @param defaultFailureUrl the failure URL, for example "/loginFailed.jsp".
|
||||
*/
|
||||
public void setDefaultFailureUrl(String defaultFailureUrl) {
|
||||
@@ -158,4 +155,5 @@ public class SimpleUrlAuthenticationFailureHandler implements
|
||||
public void setAllowSessionCreation(boolean allowSessionCreation) {
|
||||
this.allowSessionCreation = allowSessionCreation;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-6
@@ -35,9 +35,8 @@ import org.springframework.security.web.WebAttributes;
|
||||
* @author Luke Taylor
|
||||
* @since 3.0
|
||||
*/
|
||||
public class SimpleUrlAuthenticationSuccessHandler extends
|
||||
AbstractAuthenticationTargetUrlRequestHandler implements
|
||||
AuthenticationSuccessHandler {
|
||||
public class SimpleUrlAuthenticationSuccessHandler extends AbstractAuthenticationTargetUrlRequestHandler
|
||||
implements AuthenticationSuccessHandler {
|
||||
|
||||
public SimpleUrlAuthenticationSuccessHandler() {
|
||||
}
|
||||
@@ -56,9 +55,8 @@ public class SimpleUrlAuthenticationSuccessHandler extends
|
||||
* URL, and then calls {@code clearAuthenticationAttributes()} to remove any leftover
|
||||
* session data.
|
||||
*/
|
||||
public void onAuthenticationSuccess(HttpServletRequest request,
|
||||
HttpServletResponse response, Authentication authentication)
|
||||
throws IOException, ServletException {
|
||||
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication) throws IOException, ServletException {
|
||||
|
||||
handle(request, response, authentication);
|
||||
clearAuthenticationAttributes(request);
|
||||
@@ -77,4 +75,5 @@ public class SimpleUrlAuthenticationSuccessHandler extends
|
||||
|
||||
session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+14
-19
@@ -45,18 +45,22 @@ import javax.servlet.http.HttpServletResponse;
|
||||
* @author Luke Taylor
|
||||
* @since 3.0
|
||||
*/
|
||||
public class UsernamePasswordAuthenticationFilter extends
|
||||
AbstractAuthenticationProcessingFilter {
|
||||
public class UsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
|
||||
|
||||
// ~ Static fields/initializers
|
||||
// =====================================================================================
|
||||
|
||||
public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username";
|
||||
|
||||
public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password";
|
||||
private static final AntPathRequestMatcher DEFAULT_ANT_PATH_REQUEST_MATCHER =
|
||||
new AntPathRequestMatcher("/login", "POST");
|
||||
|
||||
private static final AntPathRequestMatcher DEFAULT_ANT_PATH_REQUEST_MATCHER = new AntPathRequestMatcher("/login",
|
||||
"POST");
|
||||
|
||||
private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
|
||||
|
||||
private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
|
||||
|
||||
private boolean postOnly = true;
|
||||
|
||||
// ~ Constructors
|
||||
@@ -73,11 +77,10 @@ public class UsernamePasswordAuthenticationFilter extends
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
public Authentication attemptAuthentication(HttpServletRequest request,
|
||||
HttpServletResponse response) throws AuthenticationException {
|
||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
|
||||
throws AuthenticationException {
|
||||
if (postOnly && !request.getMethod().equals("POST")) {
|
||||
throw new AuthenticationServiceException(
|
||||
"Authentication method not supported: " + request.getMethod());
|
||||
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
|
||||
}
|
||||
|
||||
String username = obtainUsername(request);
|
||||
@@ -93,8 +96,7 @@ public class UsernamePasswordAuthenticationFilter extends
|
||||
|
||||
username = username.trim();
|
||||
|
||||
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
|
||||
username, password);
|
||||
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
|
||||
|
||||
// Allow subclasses to set the "details" property
|
||||
setDetails(request, authRequest);
|
||||
@@ -111,9 +113,7 @@ public class UsernamePasswordAuthenticationFilter extends
|
||||
* password and extended value(s). The <code>AuthenticationDao</code> will need to
|
||||
* generate the expected password in a corresponding manner.
|
||||
* </p>
|
||||
*
|
||||
* @param request so that request attributes can be retrieved
|
||||
*
|
||||
* @return the password that will be presented in the <code>Authentication</code>
|
||||
* request token to the <code>AuthenticationManager</code>
|
||||
*/
|
||||
@@ -125,9 +125,7 @@ public class UsernamePasswordAuthenticationFilter extends
|
||||
/**
|
||||
* Enables subclasses to override the composition of the username, such as by
|
||||
* including additional values and a separator.
|
||||
*
|
||||
* @param request so that request attributes can be retrieved
|
||||
*
|
||||
* @return the username that will be presented in the <code>Authentication</code>
|
||||
* request token to the <code>AuthenticationManager</code>
|
||||
*/
|
||||
@@ -139,20 +137,17 @@ public class UsernamePasswordAuthenticationFilter extends
|
||||
/**
|
||||
* Provided so that subclasses may configure what is put into the authentication
|
||||
* request's details property.
|
||||
*
|
||||
* @param request that an authentication request is being created for
|
||||
* @param authRequest the authentication request object that should have its details
|
||||
* set
|
||||
*/
|
||||
protected void setDetails(HttpServletRequest request,
|
||||
UsernamePasswordAuthenticationToken authRequest) {
|
||||
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
|
||||
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parameter name which will be used to obtain the username from the login
|
||||
* request.
|
||||
*
|
||||
* @param usernameParameter the parameter name. Defaults to "username".
|
||||
*/
|
||||
public void setUsernameParameter(String usernameParameter) {
|
||||
@@ -163,7 +158,6 @@ public class UsernamePasswordAuthenticationFilter extends
|
||||
/**
|
||||
* Sets the parameter name which will be used to obtain the password from the login
|
||||
* request..
|
||||
*
|
||||
* @param passwordParameter the parameter name. Defaults to "password".
|
||||
*/
|
||||
public void setPasswordParameter(String passwordParameter) {
|
||||
@@ -191,4 +185,5 @@ public class UsernamePasswordAuthenticationFilter extends
|
||||
public final String getPasswordParameter() {
|
||||
return passwordParameter;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-4
@@ -36,6 +36,7 @@ public class WebAuthenticationDetails implements Serializable {
|
||||
// ================================================================================================
|
||||
|
||||
private final String remoteAddress;
|
||||
|
||||
private final String sessionId;
|
||||
|
||||
// ~ Constructors
|
||||
@@ -44,7 +45,6 @@ public class WebAuthenticationDetails implements Serializable {
|
||||
/**
|
||||
* Records the remote address and will also set the session Id if a session already
|
||||
* exists (it won't create one).
|
||||
*
|
||||
* @param request that the authentication request was received from
|
||||
*/
|
||||
public WebAuthenticationDetails(HttpServletRequest request) {
|
||||
@@ -56,7 +56,6 @@ public class WebAuthenticationDetails implements Serializable {
|
||||
|
||||
/**
|
||||
* Constructor to add Jackson2 serialize/deserialize support
|
||||
*
|
||||
* @param remoteAddress remote address of current request
|
||||
* @param sessionId session id
|
||||
*/
|
||||
@@ -109,7 +108,6 @@ public class WebAuthenticationDetails implements Serializable {
|
||||
|
||||
/**
|
||||
* Indicates the TCP/IP address the authentication request was received from.
|
||||
*
|
||||
* @return the address
|
||||
*/
|
||||
public String getRemoteAddress() {
|
||||
@@ -119,7 +117,6 @@ public class WebAuthenticationDetails implements Serializable {
|
||||
/**
|
||||
* Indicates the <code>HttpSession</code> id the authentication request was received
|
||||
* from.
|
||||
*
|
||||
* @return the session ID
|
||||
*/
|
||||
public String getSessionId() {
|
||||
@@ -150,4 +147,5 @@ public class WebAuthenticationDetails implements Serializable {
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-2
@@ -27,8 +27,8 @@ import javax.servlet.http.HttpServletRequest;
|
||||
*
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public class WebAuthenticationDetailsSource implements
|
||||
AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> {
|
||||
public class WebAuthenticationDetailsSource
|
||||
implements AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> {
|
||||
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
@@ -41,4 +41,5 @@ public class WebAuthenticationDetailsSource implements
|
||||
public WebAuthenticationDetails buildDetails(HttpServletRequest context) {
|
||||
return new WebAuthenticationDetails(context);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-4
@@ -26,10 +26,10 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Performs a logout through all the {@link LogoutHandler} implementations.
|
||||
* If any exception is thrown by
|
||||
* {@link #logout(HttpServletRequest, HttpServletResponse, Authentication)},
|
||||
* no additional LogoutHandler are invoked.
|
||||
* Performs a logout through all the {@link LogoutHandler} implementations. If any
|
||||
* exception is thrown by
|
||||
* {@link #logout(HttpServletRequest, HttpServletResponse, Authentication)}, no additional
|
||||
* LogoutHandler are invoked.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @since 4.2.0
|
||||
@@ -54,4 +54,5 @@ public final class CompositeLogoutHandler implements LogoutHandler {
|
||||
handler.logout(request, response, authentication);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+7
-10
@@ -26,16 +26,15 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A logout handler which clears either
|
||||
* - A defined list of cookie names, using the context path as the cookie path
|
||||
* OR
|
||||
* - A given list of Cookies
|
||||
* A logout handler which clears either - A defined list of cookie names, using the
|
||||
* context path as the cookie path OR - A given list of Cookies
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @author Onur Kagan Ozcan
|
||||
* @since 3.1
|
||||
*/
|
||||
public final class CookieClearingLogoutHandler implements LogoutHandler {
|
||||
|
||||
private final List<Function<HttpServletRequest, Cookie>> cookiesToClear;
|
||||
|
||||
public CookieClearingLogoutHandler(String... cookiesToClear) {
|
||||
@@ -52,7 +51,7 @@ public final class CookieClearingLogoutHandler implements LogoutHandler {
|
||||
};
|
||||
cookieList.add(f);
|
||||
}
|
||||
this.cookiesToClear = cookieList;
|
||||
this.cookiesToClear = cookieList;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,10 +69,8 @@ public final class CookieClearingLogoutHandler implements LogoutHandler {
|
||||
this.cookiesToClear = cookieList;
|
||||
}
|
||||
|
||||
public void logout(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication) {
|
||||
cookiesToClear.forEach(
|
||||
f -> response.addCookie(f.apply(request))
|
||||
);
|
||||
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
|
||||
cookiesToClear.forEach(f -> response.addCookie(f.apply(request)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+72
-77
@@ -1,77 +1,72 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.web.authentication.logout;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Delegates to logout handlers based on matched request matchers
|
||||
*
|
||||
* @author Shazin Sadakath
|
||||
* @author Rob Winch
|
||||
* @since 4.1
|
||||
*/
|
||||
public class DelegatingLogoutSuccessHandler implements LogoutSuccessHandler {
|
||||
|
||||
private final LinkedHashMap<RequestMatcher, LogoutSuccessHandler> matcherToHandler;
|
||||
|
||||
private LogoutSuccessHandler defaultLogoutSuccessHandler;
|
||||
|
||||
public DelegatingLogoutSuccessHandler(
|
||||
LinkedHashMap<RequestMatcher, LogoutSuccessHandler> matcherToHandler) {
|
||||
Assert.notEmpty(matcherToHandler, "matcherToHandler cannot be null");
|
||||
this.matcherToHandler = matcherToHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication) throws IOException, ServletException {
|
||||
for (Map.Entry<RequestMatcher, LogoutSuccessHandler> entry : this.matcherToHandler
|
||||
.entrySet()) {
|
||||
RequestMatcher matcher = entry.getKey();
|
||||
if (matcher.matches(request)) {
|
||||
LogoutSuccessHandler handler = entry.getValue();
|
||||
handler.onLogoutSuccess(request, response, authentication);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.defaultLogoutSuccessHandler != null) {
|
||||
this.defaultLogoutSuccessHandler.onLogoutSuccess(request, response,
|
||||
authentication);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default {@link LogoutSuccessHandler} if no other handlers available
|
||||
*
|
||||
* @param defaultLogoutSuccessHandler the defaultLogoutSuccessHandler to set
|
||||
*/
|
||||
public void setDefaultLogoutSuccessHandler(
|
||||
LogoutSuccessHandler defaultLogoutSuccessHandler) {
|
||||
this.defaultLogoutSuccessHandler = defaultLogoutSuccessHandler;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.web.authentication.logout;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Delegates to logout handlers based on matched request matchers
|
||||
*
|
||||
* @author Shazin Sadakath
|
||||
* @author Rob Winch
|
||||
* @since 4.1
|
||||
*/
|
||||
public class DelegatingLogoutSuccessHandler implements LogoutSuccessHandler {
|
||||
|
||||
private final LinkedHashMap<RequestMatcher, LogoutSuccessHandler> matcherToHandler;
|
||||
|
||||
private LogoutSuccessHandler defaultLogoutSuccessHandler;
|
||||
|
||||
public DelegatingLogoutSuccessHandler(LinkedHashMap<RequestMatcher, LogoutSuccessHandler> matcherToHandler) {
|
||||
Assert.notEmpty(matcherToHandler, "matcherToHandler cannot be null");
|
||||
this.matcherToHandler = matcherToHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
||||
throws IOException, ServletException {
|
||||
for (Map.Entry<RequestMatcher, LogoutSuccessHandler> entry : this.matcherToHandler.entrySet()) {
|
||||
RequestMatcher matcher = entry.getKey();
|
||||
if (matcher.matches(request)) {
|
||||
LogoutSuccessHandler handler = entry.getValue();
|
||||
handler.onLogoutSuccess(request, response, authentication);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.defaultLogoutSuccessHandler != null) {
|
||||
this.defaultLogoutSuccessHandler.onLogoutSuccess(request, response, authentication);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default {@link LogoutSuccessHandler} if no other handlers available
|
||||
* @param defaultLogoutSuccessHandler the defaultLogoutSuccessHandler to set
|
||||
*/
|
||||
public void setDefaultLogoutSuccessHandler(LogoutSuccessHandler defaultLogoutSuccessHandler) {
|
||||
this.defaultLogoutSuccessHandler = defaultLogoutSuccessHandler;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-4
@@ -42,14 +42,13 @@ public class ForwardLogoutSuccessHandler implements LogoutSuccessHandler {
|
||||
* @param targetUrl the target URL
|
||||
*/
|
||||
public ForwardLogoutSuccessHandler(String targetUrl) {
|
||||
Assert.isTrue(UrlUtils.isValidRedirectUrl(targetUrl),
|
||||
() -> "'" + targetUrl + "' is not a valid target URL");
|
||||
Assert.isTrue(UrlUtils.isValidRedirectUrl(targetUrl), () -> "'" + targetUrl + "' is not a valid target URL");
|
||||
this.targetUrl = targetUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication) throws IOException, ServletException {
|
||||
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
||||
throws IOException, ServletException {
|
||||
request.getRequestDispatcher(this.targetUrl).forward(request, response);
|
||||
}
|
||||
|
||||
|
||||
+3
-4
@@ -24,16 +24,15 @@ import org.springframework.security.web.header.HeaderWriter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rafiullah Hamedy
|
||||
* @since 5.2
|
||||
*/
|
||||
public final class HeaderWriterLogoutHandler implements LogoutHandler {
|
||||
|
||||
private final HeaderWriter headerWriter;
|
||||
|
||||
/**
|
||||
* Constructs a new instance using the passed {@link HeaderWriter} implementation
|
||||
*
|
||||
* @param headerWriter
|
||||
* @throws {@link IllegalArgumentException} if headerWriter is null.
|
||||
*/
|
||||
@@ -43,8 +42,8 @@ public final class HeaderWriterLogoutHandler implements LogoutHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logout(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication) {
|
||||
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
|
||||
this.headerWriter.writeHeaders(request, response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-3
@@ -40,7 +40,6 @@ public class HttpStatusReturningLogoutSuccessHandler implements LogoutSuccessHan
|
||||
/**
|
||||
* Initialize the {@code HttpStatusLogoutSuccessHandler} with a user-defined
|
||||
* {@link HttpStatus}.
|
||||
*
|
||||
* @param httpStatusToReturn Must not be {@code null}.
|
||||
*/
|
||||
public HttpStatusReturningLogoutSuccessHandler(HttpStatus httpStatusToReturn) {
|
||||
@@ -61,8 +60,8 @@ public class HttpStatusReturningLogoutSuccessHandler implements LogoutSuccessHan
|
||||
* {@link LogoutSuccessHandler#onLogoutSuccess(HttpServletRequest, HttpServletResponse, Authentication)}
|
||||
* . Sets the status on the {@link HttpServletResponse}.
|
||||
*/
|
||||
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication) throws IOException {
|
||||
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
||||
throws IOException {
|
||||
response.setStatus(this.httpStatusToReturn.value());
|
||||
response.getWriter().flush();
|
||||
}
|
||||
|
||||
+6
-11
@@ -57,6 +57,7 @@ public class LogoutFilter extends GenericFilterBean {
|
||||
private RequestMatcher logoutRequestMatcher;
|
||||
|
||||
private final LogoutHandler handler;
|
||||
|
||||
private final LogoutSuccessHandler logoutSuccessHandler;
|
||||
|
||||
// ~ Constructors
|
||||
@@ -68,8 +69,7 @@ public class LogoutFilter extends GenericFilterBean {
|
||||
* intended to perform the actual logout functionality (such as clearing the security
|
||||
* context, invalidating the session, etc.).
|
||||
*/
|
||||
public LogoutFilter(LogoutSuccessHandler logoutSuccessHandler,
|
||||
LogoutHandler... handlers) {
|
||||
public LogoutFilter(LogoutSuccessHandler logoutSuccessHandler, LogoutHandler... handlers) {
|
||||
this.handler = new CompositeLogoutHandler(handlers);
|
||||
Assert.notNull(logoutSuccessHandler, "logoutSuccessHandler cannot be null");
|
||||
this.logoutSuccessHandler = logoutSuccessHandler;
|
||||
@@ -78,9 +78,7 @@ public class LogoutFilter extends GenericFilterBean {
|
||||
|
||||
public LogoutFilter(String logoutSuccessUrl, LogoutHandler... handlers) {
|
||||
this.handler = new CompositeLogoutHandler(handlers);
|
||||
Assert.isTrue(
|
||||
!StringUtils.hasLength(logoutSuccessUrl)
|
||||
|| UrlUtils.isValidRedirectUrl(logoutSuccessUrl),
|
||||
Assert.isTrue(!StringUtils.hasLength(logoutSuccessUrl) || UrlUtils.isValidRedirectUrl(logoutSuccessUrl),
|
||||
() -> logoutSuccessUrl + " isn't a valid redirect URL");
|
||||
SimpleUrlLogoutSuccessHandler urlLogoutSuccessHandler = new SimpleUrlLogoutSuccessHandler();
|
||||
if (StringUtils.hasText(logoutSuccessUrl)) {
|
||||
@@ -102,8 +100,7 @@ public class LogoutFilter extends GenericFilterBean {
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Logging out user '" + auth
|
||||
+ "' and transferring to logout destination");
|
||||
logger.debug("Logging out user '" + auth + "' and transferring to logout destination");
|
||||
}
|
||||
|
||||
this.handler.logout(request, response, auth);
|
||||
@@ -118,14 +115,11 @@ public class LogoutFilter extends GenericFilterBean {
|
||||
|
||||
/**
|
||||
* Allow subclasses to modify when a logout should take place.
|
||||
*
|
||||
* @param request the request
|
||||
* @param response the response
|
||||
*
|
||||
* @return <code>true</code> if logout should occur, <code>false</code> otherwise
|
||||
*/
|
||||
protected boolean requiresLogout(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
protected boolean requiresLogout(HttpServletRequest request, HttpServletResponse response) {
|
||||
return logoutRequestMatcher.matches(request);
|
||||
}
|
||||
|
||||
@@ -137,4 +131,5 @@ public class LogoutFilter extends GenericFilterBean {
|
||||
public void setFilterProcessesUrl(String filterProcessesUrl) {
|
||||
this.logoutRequestMatcher = new AntPathRequestMatcher(filterProcessesUrl);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -30,16 +30,16 @@ import javax.servlet.http.HttpServletResponse;
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public interface LogoutHandler {
|
||||
|
||||
// ~ Methods
|
||||
// ========================================================================================================
|
||||
|
||||
/**
|
||||
* Causes a logout to be completed. The method must complete successfully.
|
||||
*
|
||||
* @param request the HTTP request
|
||||
* @param response the HTTP response
|
||||
* @param authentication the current principal details
|
||||
*/
|
||||
void logout(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication);
|
||||
void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication);
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -36,7 +36,7 @@ import org.springframework.security.core.Authentication;
|
||||
*/
|
||||
public interface LogoutSuccessHandler {
|
||||
|
||||
void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication) throws IOException, ServletException;
|
||||
void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
||||
throws IOException, ServletException;
|
||||
|
||||
}
|
||||
|
||||
+4
-5
@@ -41,9 +41,11 @@ import org.springframework.util.Assert;
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class SecurityContextLogoutHandler implements LogoutHandler {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private boolean invalidateHttpSession = true;
|
||||
|
||||
private boolean clearAuthentication = true;
|
||||
|
||||
// ~ Methods
|
||||
@@ -51,13 +53,11 @@ public class SecurityContextLogoutHandler implements LogoutHandler {
|
||||
|
||||
/**
|
||||
* Requires the request to be passed in.
|
||||
*
|
||||
* @param request from which to obtain a HTTP session (cannot be null)
|
||||
* @param response not used (can be <code>null</code>)
|
||||
* @param authentication not used (can be <code>null</code>)
|
||||
*/
|
||||
public void logout(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication) {
|
||||
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
|
||||
Assert.notNull(request, "HttpServletRequest required");
|
||||
if (invalidateHttpSession) {
|
||||
HttpSession session = request.getSession(false);
|
||||
@@ -82,7 +82,6 @@ public class SecurityContextLogoutHandler implements LogoutHandler {
|
||||
/**
|
||||
* Causes the {@link HttpSession} to be invalidated when this {@link LogoutHandler} is
|
||||
* invoked. Defaults to true.
|
||||
*
|
||||
* @param invalidateHttpSession true if you wish the session to be invalidated
|
||||
* (default) or false if it should not be.
|
||||
*/
|
||||
@@ -93,7 +92,6 @@ public class SecurityContextLogoutHandler implements LogoutHandler {
|
||||
/**
|
||||
* If true, removes the {@link Authentication} from the {@link SecurityContext} to
|
||||
* prevent issues with concurrent requests.
|
||||
*
|
||||
* @param clearAuthentication true if you wish to clear the {@link Authentication}
|
||||
* from the {@link SecurityContext} (default) or false if the {@link Authentication}
|
||||
* should not be removed.
|
||||
@@ -101,4 +99,5 @@ public class SecurityContextLogoutHandler implements LogoutHandler {
|
||||
public void setClearAuthentication(boolean clearAuthentication) {
|
||||
this.clearAuthentication = clearAuthentication;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-4
@@ -31,11 +31,11 @@ import org.springframework.security.web.authentication.AbstractAuthenticationTar
|
||||
* @author Luke Taylor
|
||||
* @since 3.0
|
||||
*/
|
||||
public class SimpleUrlLogoutSuccessHandler extends
|
||||
AbstractAuthenticationTargetUrlRequestHandler implements LogoutSuccessHandler {
|
||||
public class SimpleUrlLogoutSuccessHandler extends AbstractAuthenticationTargetUrlRequestHandler
|
||||
implements LogoutSuccessHandler {
|
||||
|
||||
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication) throws IOException, ServletException {
|
||||
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
||||
throws IOException, ServletException {
|
||||
super.handle(request, response, authentication);
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -17,4 +17,3 @@
|
||||
* Logout functionality based around a filter which handles a specific logout URL.
|
||||
*/
|
||||
package org.springframework.security.web.authentication.logout;
|
||||
|
||||
|
||||
@@ -18,4 +18,3 @@
|
||||
* credentials using various protocols (eg BASIC, CAS, form login etc).
|
||||
*/
|
||||
package org.springframework.security.web.authentication;
|
||||
|
||||
|
||||
+33
-31
@@ -81,13 +81,21 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
||||
implements ApplicationEventPublisherAware {
|
||||
|
||||
private ApplicationEventPublisher eventPublisher = null;
|
||||
|
||||
private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
|
||||
|
||||
private AuthenticationManager authenticationManager = null;
|
||||
|
||||
private boolean continueFilterChainOnUnsuccessfulAuthentication = true;
|
||||
|
||||
private boolean checkForPrincipalChanges;
|
||||
|
||||
private boolean invalidateSessionOnPrincipalChange = true;
|
||||
|
||||
private AuthenticationSuccessHandler authenticationSuccessHandler = null;
|
||||
|
||||
private AuthenticationFailureHandler authenticationFailureHandler = null;
|
||||
|
||||
private RequestMatcher requiresAuthenticationRequestMatcher = new PreAuthenticatedProcessingRequestMatcher();
|
||||
|
||||
/**
|
||||
@@ -109,12 +117,11 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
||||
* Try to authenticate a pre-authenticated user with Spring Security if the user has
|
||||
* not yet been authenticated.
|
||||
*/
|
||||
public void doFilter(ServletRequest request, ServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Checking secure context token: "
|
||||
+ SecurityContextHolder.getContext().getAuthentication());
|
||||
logger.debug("Checking secure context token: " + SecurityContextHolder.getContext().getAuthentication());
|
||||
}
|
||||
|
||||
if (requiresAuthenticationRequestMatcher.matches((HttpServletRequest) request)) {
|
||||
@@ -128,14 +135,16 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
||||
* Determines if the current principal has changed. The default implementation tries
|
||||
*
|
||||
* <ul>
|
||||
* <li>If the {@link #getPreAuthenticatedPrincipal(HttpServletRequest)} is a String, the {@link Authentication#getName()} is compared against the pre authenticated principal</li>
|
||||
* <li>Otherwise, the {@link #getPreAuthenticatedPrincipal(HttpServletRequest)} is compared against the {@link Authentication#getPrincipal()}
|
||||
* <li>If the {@link #getPreAuthenticatedPrincipal(HttpServletRequest)} is a String,
|
||||
* the {@link Authentication#getName()} is compared against the pre authenticated
|
||||
* principal</li>
|
||||
* <li>Otherwise, the {@link #getPreAuthenticatedPrincipal(HttpServletRequest)} is
|
||||
* compared against the {@link Authentication#getPrincipal()}
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* Subclasses can override this method to determine when a principal has changed.
|
||||
* </p>
|
||||
*
|
||||
* @param request
|
||||
* @param currentAuthentication
|
||||
* @return true if the principal has changed, else false
|
||||
@@ -161,7 +170,8 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
||||
/**
|
||||
* Do the actual authentication for a pre-authenticated user.
|
||||
*/
|
||||
private void doAuthenticate(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||
private void doAuthenticate(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException {
|
||||
Authentication authResult;
|
||||
|
||||
Object principal = getPreAuthenticatedPrincipal(request);
|
||||
@@ -176,13 +186,12 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("preAuthenticatedPrincipal = " + principal
|
||||
+ ", trying to authenticate");
|
||||
logger.debug("preAuthenticatedPrincipal = " + principal + ", trying to authenticate");
|
||||
}
|
||||
|
||||
try {
|
||||
PreAuthenticatedAuthenticationToken authRequest = new PreAuthenticatedAuthenticationToken(
|
||||
principal, credentials);
|
||||
PreAuthenticatedAuthenticationToken authRequest = new PreAuthenticatedAuthenticationToken(principal,
|
||||
credentials);
|
||||
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
|
||||
authResult = authenticationManager.authenticate(authRequest);
|
||||
successfulAuthentication(request, response, authResult);
|
||||
@@ -200,16 +209,15 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
||||
* Puts the <code>Authentication</code> instance returned by the authentication
|
||||
* manager into the secure context.
|
||||
*/
|
||||
protected void successfulAuthentication(HttpServletRequest request,
|
||||
HttpServletResponse response, Authentication authResult) throws IOException, ServletException {
|
||||
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authResult) throws IOException, ServletException {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Authentication success: " + authResult);
|
||||
}
|
||||
SecurityContextHolder.getContext().setAuthentication(authResult);
|
||||
// Fire event
|
||||
if (this.eventPublisher != null) {
|
||||
eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(
|
||||
authResult, this.getClass()));
|
||||
eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
|
||||
}
|
||||
|
||||
if (authenticationSuccessHandler != null) {
|
||||
@@ -223,8 +231,8 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
||||
* <p>
|
||||
* Caches the failure exception as a request attribute
|
||||
*/
|
||||
protected void unsuccessfulAuthentication(HttpServletRequest request,
|
||||
HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
|
||||
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException failed) throws IOException, ServletException {
|
||||
SecurityContextHolder.clearContext();
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
@@ -240,8 +248,7 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
||||
/**
|
||||
* @param anApplicationEventPublisher The ApplicationEventPublisher to use
|
||||
*/
|
||||
public void setApplicationEventPublisher(
|
||||
ApplicationEventPublisher anApplicationEventPublisher) {
|
||||
public void setApplicationEventPublisher(ApplicationEventPublisher anApplicationEventPublisher) {
|
||||
this.eventPublisher = anApplicationEventPublisher;
|
||||
}
|
||||
|
||||
@@ -250,8 +257,7 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
||||
*/
|
||||
public void setAuthenticationDetailsSource(
|
||||
AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource) {
|
||||
Assert.notNull(authenticationDetailsSource,
|
||||
"AuthenticationDetailsSource required");
|
||||
Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");
|
||||
this.authenticationDetailsSource = authenticationDetailsSource;
|
||||
}
|
||||
|
||||
@@ -267,11 +273,10 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
||||
}
|
||||
|
||||
/**
|
||||
* If set to {@code true} (the default), any {@code AuthenticationException} raised by the
|
||||
* {@code AuthenticationManager} will be swallowed, and the request will be allowed to
|
||||
* proceed, potentially using alternative authentication mechanisms. If {@code false},
|
||||
* authentication failure will result in an immediate exception.
|
||||
*
|
||||
* If set to {@code true} (the default), any {@code AuthenticationException} raised by
|
||||
* the {@code AuthenticationManager} will be swallowed, and the request will be
|
||||
* allowed to proceed, potentially using alternative authentication mechanisms. If
|
||||
* {@code false}, authentication failure will result in an immediate exception.
|
||||
* @param shouldContinue set to {@code true} to allow the request to proceed after a
|
||||
* failed authentication.
|
||||
*/
|
||||
@@ -284,7 +289,6 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
||||
* compared against the name of the current <tt>Authentication</tt> object. A check to
|
||||
* determine if {@link Authentication#getPrincipal()} is equal to the principal will
|
||||
* also be performed. If a change is detected, the user will be reauthenticated.
|
||||
*
|
||||
* @param checkForPrincipalChanges
|
||||
*/
|
||||
public void setCheckForPrincipalChanges(boolean checkForPrincipalChanges) {
|
||||
@@ -295,12 +299,10 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
||||
* If <tt>checkForPrincipalChanges</tt> is set, and a change of principal is detected,
|
||||
* determines whether any existing session should be invalidated before proceeding to
|
||||
* authenticate the new principal.
|
||||
*
|
||||
* @param invalidateSessionOnPrincipalChange <tt>false</tt> to retain the existing
|
||||
* session. Defaults to <tt>true</tt>.
|
||||
*/
|
||||
public void setInvalidateSessionOnPrincipalChange(
|
||||
boolean invalidateSessionOnPrincipalChange) {
|
||||
public void setInvalidateSessionOnPrincipalChange(boolean invalidateSessionOnPrincipalChange) {
|
||||
this.invalidateSessionOnPrincipalChange = invalidateSessionOnPrincipalChange;
|
||||
}
|
||||
|
||||
|
||||
+12
-15
@@ -44,13 +44,14 @@ import org.springframework.util.Assert;
|
||||
* @author Ruud Senden
|
||||
* @since 2.0
|
||||
*/
|
||||
public class PreAuthenticatedAuthenticationProvider implements AuthenticationProvider,
|
||||
InitializingBean, Ordered {
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(PreAuthenticatedAuthenticationProvider.class);
|
||||
public class PreAuthenticatedAuthenticationProvider implements AuthenticationProvider, InitializingBean, Ordered {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(PreAuthenticatedAuthenticationProvider.class);
|
||||
|
||||
private AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> preAuthenticatedUserDetailsService = null;
|
||||
|
||||
private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker();
|
||||
|
||||
private boolean throwExceptionWhenTokenRejected = false;
|
||||
|
||||
private int order = -1; // default: same as non-ordered
|
||||
@@ -59,8 +60,7 @@ public class PreAuthenticatedAuthenticationProvider implements AuthenticationPro
|
||||
* Check whether all required properties have been set.
|
||||
*/
|
||||
public void afterPropertiesSet() {
|
||||
Assert.notNull(preAuthenticatedUserDetailsService,
|
||||
"An AuthenticationUserDetailsService must be set");
|
||||
Assert.notNull(preAuthenticatedUserDetailsService, "An AuthenticationUserDetailsService must be set");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,8 +69,7 @@ public class PreAuthenticatedAuthenticationProvider implements AuthenticationPro
|
||||
* If the principal contained in the authentication object is null, the request will
|
||||
* be ignored to allow other providers to authenticate it.
|
||||
*/
|
||||
public Authentication authenticate(Authentication authentication)
|
||||
throws AuthenticationException {
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
if (!supports(authentication.getClass())) {
|
||||
return null;
|
||||
}
|
||||
@@ -83,8 +82,7 @@ public class PreAuthenticatedAuthenticationProvider implements AuthenticationPro
|
||||
logger.debug("No pre-authenticated principal found in request.");
|
||||
|
||||
if (throwExceptionWhenTokenRejected) {
|
||||
throw new BadCredentialsException(
|
||||
"No pre-authenticated principal found in request.");
|
||||
throw new BadCredentialsException("No pre-authenticated principal found in request.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -93,8 +91,7 @@ public class PreAuthenticatedAuthenticationProvider implements AuthenticationPro
|
||||
logger.debug("No pre-authenticated credentials found in request.");
|
||||
|
||||
if (throwExceptionWhenTokenRejected) {
|
||||
throw new BadCredentialsException(
|
||||
"No pre-authenticated credentials found in request.");
|
||||
throw new BadCredentialsException("No pre-authenticated credentials found in request.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -104,8 +101,8 @@ public class PreAuthenticatedAuthenticationProvider implements AuthenticationPro
|
||||
|
||||
userDetailsChecker.check(ud);
|
||||
|
||||
PreAuthenticatedAuthenticationToken result = new PreAuthenticatedAuthenticationToken(
|
||||
ud, authentication.getCredentials(), ud.getAuthorities());
|
||||
PreAuthenticatedAuthenticationToken result = new PreAuthenticatedAuthenticationToken(ud,
|
||||
authentication.getCredentials(), ud.getAuthorities());
|
||||
result.setDetails(authentication.getDetails());
|
||||
|
||||
return result;
|
||||
@@ -122,7 +119,6 @@ public class PreAuthenticatedAuthenticationProvider implements AuthenticationPro
|
||||
/**
|
||||
* Set the AuthenticatedUserDetailsService to be used to load the {@code UserDetails}
|
||||
* for the authenticated user.
|
||||
*
|
||||
* @param uds
|
||||
*/
|
||||
public void setPreAuthenticatedUserDetailsService(
|
||||
@@ -156,4 +152,5 @@ public class PreAuthenticatedAuthenticationProvider implements AuthenticationPro
|
||||
public void setOrder(int i) {
|
||||
order = i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-2
@@ -33,13 +33,13 @@ public class PreAuthenticatedAuthenticationToken extends AbstractAuthenticationT
|
||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
||||
|
||||
private final Object principal;
|
||||
|
||||
private final Object credentials;
|
||||
|
||||
/**
|
||||
* Constructor used for an authentication request. The
|
||||
* {@link org.springframework.security.core.Authentication#isAuthenticated()} will
|
||||
* return <code>false</code>.
|
||||
*
|
||||
* @param aPrincipal The pre-authenticated principal
|
||||
* @param aCredentials The pre-authenticated credentials
|
||||
*/
|
||||
@@ -53,7 +53,6 @@ public class PreAuthenticatedAuthenticationToken extends AbstractAuthenticationT
|
||||
* Constructor used for an authentication response. The
|
||||
* {@link org.springframework.security.core.Authentication#isAuthenticated()} will
|
||||
* return <code>true</code>.
|
||||
*
|
||||
* @param aPrincipal The authenticated principal
|
||||
* @param anAuthorities The granted authorities
|
||||
*/
|
||||
|
||||
+1
-1
@@ -24,11 +24,11 @@ public class PreAuthenticatedCredentialsNotFoundException extends Authentication
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param message The message for the Exception
|
||||
* @param cause The Exception that caused this Exception.
|
||||
*/
|
||||
public PreAuthenticatedCredentialsNotFoundException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-9
@@ -45,31 +45,30 @@ import org.springframework.util.Assert;
|
||||
* @author Ruud Senden
|
||||
* @since 2.0
|
||||
*/
|
||||
public class PreAuthenticatedGrantedAuthoritiesUserDetailsService implements
|
||||
AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {
|
||||
public class PreAuthenticatedGrantedAuthoritiesUserDetailsService
|
||||
implements AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {
|
||||
|
||||
/**
|
||||
* Get a UserDetails object based on the user name contained in the given token, and
|
||||
* the GrantedAuthorities as returned by the GrantedAuthoritiesContainer
|
||||
* implementation as returned by the token.getDetails() method.
|
||||
*/
|
||||
public final UserDetails loadUserDetails(PreAuthenticatedAuthenticationToken token)
|
||||
throws AuthenticationException {
|
||||
public final UserDetails loadUserDetails(PreAuthenticatedAuthenticationToken token) throws AuthenticationException {
|
||||
Assert.notNull(token.getDetails(), "token.getDetails() cannot be null");
|
||||
Assert.isInstanceOf(GrantedAuthoritiesContainer.class, token.getDetails());
|
||||
Collection<? extends GrantedAuthority> authorities = ((GrantedAuthoritiesContainer) token
|
||||
.getDetails()).getGrantedAuthorities();
|
||||
Collection<? extends GrantedAuthority> authorities = ((GrantedAuthoritiesContainer) token.getDetails())
|
||||
.getGrantedAuthorities();
|
||||
return createUserDetails(token, authorities);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the final <tt>UserDetails</tt> object. Can be overridden to customize the
|
||||
* contents.
|
||||
*
|
||||
* @param token the authentication request token
|
||||
* @param authorities the pre-authenticated authorities.
|
||||
*/
|
||||
protected UserDetails createUserDetails(Authentication token,
|
||||
Collection<? extends GrantedAuthority> authorities) {
|
||||
protected UserDetails createUserDetails(Authentication token, Collection<? extends GrantedAuthority> authorities) {
|
||||
return new User(token.getName(), "N/A", true, true, true, true, authorities);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-4
@@ -31,15 +31,15 @@ import java.util.*;
|
||||
* @author Luke Taylor
|
||||
* @since 2.0
|
||||
*/
|
||||
public class PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails extends
|
||||
WebAuthenticationDetails implements GrantedAuthoritiesContainer {
|
||||
public class PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails extends WebAuthenticationDetails
|
||||
implements GrantedAuthoritiesContainer {
|
||||
|
||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
||||
|
||||
private final List<GrantedAuthority> authorities;
|
||||
|
||||
public PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails(
|
||||
HttpServletRequest request, Collection<? extends GrantedAuthority> authorities) {
|
||||
public PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails(HttpServletRequest request,
|
||||
Collection<? extends GrantedAuthority> authorities) {
|
||||
super(request);
|
||||
|
||||
List<GrantedAuthority> temp = new ArrayList<>(authorities.size());
|
||||
@@ -59,4 +59,5 @@ public class PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails extends
|
||||
sb.append(authorities);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
-11
@@ -22,8 +22,9 @@ import org.springframework.util.Assert;
|
||||
/**
|
||||
* A simple pre-authenticated filter which obtains the username from request attributes,
|
||||
* for use with SSO systems such as
|
||||
* <a href="https://webauth.stanford.edu/manual/mod/mod_webauth.html#java">Stanford WebAuth</a> or
|
||||
* <a href="https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPJavaInstall">Shibboleth</a>.
|
||||
* <a href="https://webauth.stanford.edu/manual/mod/mod_webauth.html#java">Stanford
|
||||
* WebAuth</a> or <a href=
|
||||
* "https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPJavaInstall">Shibboleth</a>.
|
||||
* <p>
|
||||
* As with most pre-authenticated scenarios, it is essential that the external
|
||||
* authentication system is set up correctly as this filter does no authentication
|
||||
@@ -37,20 +38,20 @@ import org.springframework.util.Assert;
|
||||
* {@code getPreAuthenticatedPrincipal} will throw an exception. You can override this
|
||||
* behaviour by setting the {@code exceptionIfVariableMissing} property.
|
||||
*
|
||||
*
|
||||
* @author Milan Sevcik
|
||||
* @since 4.2
|
||||
*/
|
||||
public class RequestAttributeAuthenticationFilter
|
||||
extends AbstractPreAuthenticatedProcessingFilter {
|
||||
public class RequestAttributeAuthenticationFilter extends AbstractPreAuthenticatedProcessingFilter {
|
||||
|
||||
private String principalEnvironmentVariable = "REMOTE_USER";
|
||||
|
||||
private String credentialsEnvironmentVariable;
|
||||
|
||||
private boolean exceptionIfVariableMissing = true;
|
||||
|
||||
/**
|
||||
* Read and returns the variable named by {@code principalEnvironmentVariable} from
|
||||
* the request.
|
||||
*
|
||||
* @throws PreAuthenticatedCredentialsNotFoundException if the environment variable is
|
||||
* missing and {@code exceptionIfVariableMissing} is set to {@code true}.
|
||||
*/
|
||||
@@ -79,25 +80,23 @@ public class RequestAttributeAuthenticationFilter
|
||||
}
|
||||
|
||||
public void setPrincipalEnvironmentVariable(String principalEnvironmentVariable) {
|
||||
Assert.hasText(principalEnvironmentVariable,
|
||||
"principalEnvironmentVariable must not be empty or null");
|
||||
Assert.hasText(principalEnvironmentVariable, "principalEnvironmentVariable must not be empty or null");
|
||||
this.principalEnvironmentVariable = principalEnvironmentVariable;
|
||||
}
|
||||
|
||||
public void setCredentialsEnvironmentVariable(String credentialsEnvironmentVariable) {
|
||||
Assert.hasText(credentialsEnvironmentVariable,
|
||||
"credentialsEnvironmentVariable must not be empty or null");
|
||||
Assert.hasText(credentialsEnvironmentVariable, "credentialsEnvironmentVariable must not be empty or null");
|
||||
this.credentialsEnvironmentVariable = credentialsEnvironmentVariable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines whether an exception should be raised if the principal variable is missing.
|
||||
* Defaults to {@code true}.
|
||||
*
|
||||
* @param exceptionIfVariableMissing set to {@code false} to override the default
|
||||
* behaviour and allow the request to proceed if no variable is found.
|
||||
*/
|
||||
public void setExceptionIfVariableMissing(boolean exceptionIfVariableMissing) {
|
||||
this.exceptionIfVariableMissing = exceptionIfVariableMissing;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+9
-11
@@ -39,20 +39,20 @@ import org.springframework.util.Assert;
|
||||
* throw an exception. You can override this behaviour by setting the
|
||||
* {@code exceptionIfHeaderMissing} property.
|
||||
*
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 2.0
|
||||
*/
|
||||
public class RequestHeaderAuthenticationFilter extends
|
||||
AbstractPreAuthenticatedProcessingFilter {
|
||||
public class RequestHeaderAuthenticationFilter extends AbstractPreAuthenticatedProcessingFilter {
|
||||
|
||||
private String principalRequestHeader = "SM_USER";
|
||||
|
||||
private String credentialsRequestHeader;
|
||||
|
||||
private boolean exceptionIfHeaderMissing = true;
|
||||
|
||||
/**
|
||||
* Read and returns the header named by {@code principalRequestHeader} from the
|
||||
* request.
|
||||
*
|
||||
* @throws PreAuthenticatedCredentialsNotFoundException if the header is missing and
|
||||
* {@code exceptionIfHeaderMissing} is set to {@code true}.
|
||||
*/
|
||||
@@ -60,8 +60,8 @@ public class RequestHeaderAuthenticationFilter extends
|
||||
String principal = request.getHeader(principalRequestHeader);
|
||||
|
||||
if (principal == null && exceptionIfHeaderMissing) {
|
||||
throw new PreAuthenticatedCredentialsNotFoundException(principalRequestHeader
|
||||
+ " header not found in request.");
|
||||
throw new PreAuthenticatedCredentialsNotFoundException(
|
||||
principalRequestHeader + " header not found in request.");
|
||||
}
|
||||
|
||||
return principal;
|
||||
@@ -81,25 +81,23 @@ public class RequestHeaderAuthenticationFilter extends
|
||||
}
|
||||
|
||||
public void setPrincipalRequestHeader(String principalRequestHeader) {
|
||||
Assert.hasText(principalRequestHeader,
|
||||
"principalRequestHeader must not be empty or null");
|
||||
Assert.hasText(principalRequestHeader, "principalRequestHeader must not be empty or null");
|
||||
this.principalRequestHeader = principalRequestHeader;
|
||||
}
|
||||
|
||||
public void setCredentialsRequestHeader(String credentialsRequestHeader) {
|
||||
Assert.hasText(credentialsRequestHeader,
|
||||
"credentialsRequestHeader must not be empty or null");
|
||||
Assert.hasText(credentialsRequestHeader, "credentialsRequestHeader must not be empty or null");
|
||||
this.credentialsRequestHeader = credentialsRequestHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines whether an exception should be raised if the principal header is missing.
|
||||
* Defaults to {@code true}.
|
||||
*
|
||||
* @param exceptionIfHeaderMissing set to {@code false} to override the default
|
||||
* behaviour and allow the request to proceed if no header is found.
|
||||
*/
|
||||
public void setExceptionIfHeaderMissing(boolean exceptionIfHeaderMissing) {
|
||||
this.exceptionIfHeaderMissing = exceptionIfHeaderMissing;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+13
-16
@@ -37,14 +37,17 @@ import java.util.*;
|
||||
* @author Ruud Senden
|
||||
* @since 2.0
|
||||
*/
|
||||
public class J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
|
||||
implements
|
||||
public class J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource implements
|
||||
AuthenticationDetailsSource<HttpServletRequest, PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails>,
|
||||
InitializingBean {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
/** The role attributes returned by the configured {@code MappableAttributesRetriever} */
|
||||
|
||||
/**
|
||||
* The role attributes returned by the configured {@code MappableAttributesRetriever}
|
||||
*/
|
||||
protected Set<String> j2eeMappableRoles;
|
||||
|
||||
protected Attributes2GrantedAuthoritiesMapper j2eeUserRoles2GrantedAuthoritiesMapper = new SimpleAttributes2GrantedAuthoritiesMapper();
|
||||
|
||||
/**
|
||||
@@ -52,8 +55,7 @@ public class J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
|
||||
*/
|
||||
public void afterPropertiesSet() {
|
||||
Assert.notNull(j2eeMappableRoles, "No mappable roles available");
|
||||
Assert.notNull(j2eeUserRoles2GrantedAuthoritiesMapper,
|
||||
"Roles to granted authorities mapper not set");
|
||||
Assert.notNull(j2eeUserRoles2GrantedAuthoritiesMapper, "Roles to granted authorities mapper not set");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,7 +63,6 @@ public class J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
|
||||
* {@link javax.servlet.http.HttpServletRequest#isUserInRole(String)} method is called
|
||||
* for each of the values in the {@code j2eeMappableRoles} set to determine if that
|
||||
* role should be assigned to the user.
|
||||
*
|
||||
* @param request the request which should be used to extract the user's roles.
|
||||
* @return The subset of {@code j2eeMappableRoles} which applies to the current user
|
||||
* making the request.
|
||||
@@ -83,16 +84,14 @@ public class J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
|
||||
*
|
||||
* @see org.springframework.security.authentication.AuthenticationDetailsSource#buildDetails(Object)
|
||||
*/
|
||||
public PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails buildDetails(
|
||||
HttpServletRequest context) {
|
||||
public PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails buildDetails(HttpServletRequest context) {
|
||||
|
||||
Collection<String> j2eeUserRoles = getUserRoles(context);
|
||||
Collection<? extends GrantedAuthority> userGas = j2eeUserRoles2GrantedAuthoritiesMapper
|
||||
.getGrantedAuthorities(j2eeUserRoles);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("J2EE roles [" + j2eeUserRoles
|
||||
+ "] mapped to Granted Authorities: [" + userGas + "]");
|
||||
logger.debug("J2EE roles [" + j2eeUserRoles + "] mapped to Granted Authorities: [" + userGas + "]");
|
||||
}
|
||||
|
||||
PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails result = new PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails(
|
||||
@@ -104,17 +103,15 @@ public class J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
|
||||
/**
|
||||
* @param aJ2eeMappableRolesRetriever The MappableAttributesRetriever to use
|
||||
*/
|
||||
public void setMappableRolesRetriever(
|
||||
MappableAttributesRetriever aJ2eeMappableRolesRetriever) {
|
||||
this.j2eeMappableRoles = Collections.unmodifiableSet(aJ2eeMappableRolesRetriever
|
||||
.getMappableAttributes());
|
||||
public void setMappableRolesRetriever(MappableAttributesRetriever aJ2eeMappableRolesRetriever) {
|
||||
this.j2eeMappableRoles = Collections.unmodifiableSet(aJ2eeMappableRolesRetriever.getMappableAttributes());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mapper The Attributes2GrantedAuthoritiesMapper to use
|
||||
*/
|
||||
public void setUserRoles2GrantedAuthoritiesMapper(
|
||||
Attributes2GrantedAuthoritiesMapper mapper) {
|
||||
public void setUserRoles2GrantedAuthoritiesMapper(Attributes2GrantedAuthoritiesMapper mapper) {
|
||||
j2eeUserRoles2GrantedAuthoritiesMapper = mapper;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-4
@@ -27,15 +27,13 @@ import org.springframework.security.web.authentication.preauth.AbstractPreAuthen
|
||||
* @author Ruud Senden
|
||||
* @since 2.0
|
||||
*/
|
||||
public class J2eePreAuthenticatedProcessingFilter extends
|
||||
AbstractPreAuthenticatedProcessingFilter {
|
||||
public class J2eePreAuthenticatedProcessingFilter extends AbstractPreAuthenticatedProcessingFilter {
|
||||
|
||||
/**
|
||||
* Return the J2EE user name.
|
||||
*/
|
||||
protected Object getPreAuthenticatedPrincipal(HttpServletRequest httpRequest) {
|
||||
Object principal = httpRequest.getUserPrincipal() == null ? null : httpRequest
|
||||
.getUserPrincipal().getName();
|
||||
Object principal = httpRequest.getUserPrincipal() == null ? null : httpRequest.getUserPrincipal().getName();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("PreAuthenticated J2EE principal: " + principal);
|
||||
}
|
||||
@@ -49,4 +47,5 @@ public class J2eePreAuthenticatedProcessingFilter extends
|
||||
protected Object getPreAuthenticatedCredentials(HttpServletRequest httpRequest) {
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+11
-7
@@ -51,11 +51,13 @@ import org.xml.sax.SAXException;
|
||||
* @author Luke Taylor
|
||||
* @since 2.0
|
||||
*/
|
||||
public class WebXmlMappableAttributesRetriever implements ResourceLoaderAware,
|
||||
MappableAttributesRetriever, InitializingBean {
|
||||
public class WebXmlMappableAttributesRetriever
|
||||
implements ResourceLoaderAware, MappableAttributesRetriever, InitializingBean {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
private Set<String> mappableAttributes;
|
||||
|
||||
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||
@@ -76,11 +78,9 @@ public class WebXmlMappableAttributesRetriever implements ResourceLoaderAware,
|
||||
Document doc = getDocument(webXml.getInputStream());
|
||||
NodeList webApp = doc.getElementsByTagName("web-app");
|
||||
if (webApp.getLength() != 1) {
|
||||
throw new IllegalArgumentException(
|
||||
"Failed to find 'web-app' element in resource" + webXml);
|
||||
throw new IllegalArgumentException("Failed to find 'web-app' element in resource" + webXml);
|
||||
}
|
||||
NodeList securityRoles = ((Element) webApp.item(0))
|
||||
.getElementsByTagName("security-role");
|
||||
NodeList securityRoles = ((Element) webApp.item(0)).getElementsByTagName("security-role");
|
||||
|
||||
ArrayList<String> roleNames = new ArrayList<>();
|
||||
|
||||
@@ -116,7 +116,8 @@ public class WebXmlMappableAttributesRetriever implements ResourceLoaderAware,
|
||||
}
|
||||
catch (FactoryConfigurationError | IOException | SAXException | ParserConfigurationException e) {
|
||||
throw new RuntimeException("Unable to parse document object", e);
|
||||
} finally {
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
aStream.close();
|
||||
}
|
||||
@@ -130,8 +131,11 @@ public class WebXmlMappableAttributesRetriever implements ResourceLoaderAware,
|
||||
* We do not need to resolve external entities, so just return an empty String.
|
||||
*/
|
||||
private static final class MyEntityResolver implements EntityResolver {
|
||||
|
||||
public InputSource resolveEntity(String publicId, String systemId) {
|
||||
return new InputSource(new StringReader(""));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -16,8 +16,8 @@
|
||||
/**
|
||||
* Pre-authentication support for container-authenticated requests.
|
||||
* <p>
|
||||
* It is assumed that standard JEE security has been configured and Spring Security hooks into the
|
||||
* security methods exposed by {@code HttpServletRequest} to build {@code Authentication} object for the user.
|
||||
* It is assumed that standard JEE security has been configured and Spring Security hooks
|
||||
* into the security methods exposed by {@code HttpServletRequest} to build
|
||||
* {@code Authentication} object for the user.
|
||||
*/
|
||||
package org.springframework.security.web.authentication.preauth.j2ee;
|
||||
|
||||
|
||||
+2
-3
@@ -14,8 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
/**
|
||||
* Support for "pre-authenticated" scenarios, where Spring Security assumes the incoming request has already been
|
||||
* authenticated by some externally configured system.
|
||||
* Support for "pre-authenticated" scenarios, where Spring Security assumes the incoming
|
||||
* request has already been authenticated by some externally configured system.
|
||||
*/
|
||||
package org.springframework.security.web.authentication.preauth;
|
||||
|
||||
|
||||
+32
-43
@@ -40,8 +40,8 @@ import org.apache.commons.logging.LogFactory;
|
||||
* @since 2.0
|
||||
*/
|
||||
final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroupsExtractor {
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(DefaultWASUsernameAndGroupsExtractor.class);
|
||||
|
||||
private static final Log logger = LogFactory.getLog(DefaultWASUsernameAndGroupsExtractor.class);
|
||||
|
||||
private static final String PORTABLE_REMOTE_OBJECT_CLASSNAME = "javax.rmi.PortableRemoteObject";
|
||||
|
||||
@@ -68,7 +68,6 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
|
||||
|
||||
/**
|
||||
* Get the security name for the given subject.
|
||||
*
|
||||
* @param subject The subject for which to retrieve the security name
|
||||
* @return String the security name for the given subject
|
||||
*/
|
||||
@@ -79,23 +78,19 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
|
||||
String userSecurityName = null;
|
||||
if (subject != null) {
|
||||
// SEC-803
|
||||
Object credential = subject.getPublicCredentials(getWSCredentialClass())
|
||||
.iterator().next();
|
||||
Object credential = subject.getPublicCredentials(getWSCredentialClass()).iterator().next();
|
||||
if (credential != null) {
|
||||
userSecurityName = (String) invokeMethod(getSecurityNameMethod(),
|
||||
credential);
|
||||
userSecurityName = (String) invokeMethod(getSecurityNameMethod(), credential);
|
||||
}
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Websphere security name is " + userSecurityName
|
||||
+ " for subject " + subject);
|
||||
logger.debug("Websphere security name is " + userSecurityName + " for subject " + subject);
|
||||
}
|
||||
return userSecurityName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current RunAs subject.
|
||||
*
|
||||
* @return Subject the current RunAs subject
|
||||
*/
|
||||
private static Subject getRunAsSubject() {
|
||||
@@ -106,7 +101,6 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
|
||||
|
||||
/**
|
||||
* Get the WebSphere group names for the given subject.
|
||||
*
|
||||
* @param subject The subject for which to retrieve the WebSphere group names
|
||||
* @return the WebSphere group names for the given subject
|
||||
*/
|
||||
@@ -116,7 +110,6 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
|
||||
|
||||
/**
|
||||
* Get the WebSphere group names for the given security name.
|
||||
*
|
||||
* @param securityName The security name for which to retrieve the WebSphere group
|
||||
* names
|
||||
* @return the WebSphere group names for the given security name
|
||||
@@ -128,13 +121,14 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
|
||||
// TODO: Cache UserRegistry object
|
||||
ic = new InitialContext();
|
||||
Object objRef = ic.lookup(USER_REGISTRY);
|
||||
Object userReg = invokeMethod(getNarrowMethod(), null , objRef, Class.forName("com.ibm.websphere.security.UserRegistry"));
|
||||
Object userReg = invokeMethod(getNarrowMethod(), null, objRef,
|
||||
Class.forName("com.ibm.websphere.security.UserRegistry"));
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Determining WebSphere groups for user " + securityName
|
||||
+ " using WebSphere UserRegistry " + userReg);
|
||||
logger.debug("Determining WebSphere groups for user " + securityName + " using WebSphere UserRegistry "
|
||||
+ userReg);
|
||||
}
|
||||
final Collection groups = (Collection) invokeMethod(getGroupsForUserMethod(),
|
||||
userReg, new Object[] { securityName });
|
||||
final Collection groups = (Collection) invokeMethod(getGroupsForUserMethod(), userReg,
|
||||
new Object[] { securityName });
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Groups for user " + securityName + ": " + groups.toString());
|
||||
}
|
||||
@@ -143,8 +137,7 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.error("Exception occured while looking up groups for user", e);
|
||||
throw new RuntimeException(
|
||||
"Exception occured while looking up groups for user", e);
|
||||
throw new RuntimeException("Exception occured while looking up groups for user", e);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
@@ -163,30 +156,26 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
|
||||
return method.invoke(instance, args);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
logger.error("Error while invoking method " + method.getClass().getName()
|
||||
+ "." + method.getName() + "(" + Arrays.asList(args) + ")", e);
|
||||
throw new RuntimeException("Error while invoking method "
|
||||
+ method.getClass().getName() + "." + method.getName() + "("
|
||||
logger.error("Error while invoking method " + method.getClass().getName() + "." + method.getName() + "("
|
||||
+ Arrays.asList(args) + ")", e);
|
||||
throw new RuntimeException("Error while invoking method " + method.getClass().getName() + "."
|
||||
+ method.getName() + "(" + Arrays.asList(args) + ")", e);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
logger.error("Error while invoking method " + method.getClass().getName()
|
||||
+ "." + method.getName() + "(" + Arrays.asList(args) + ")", e);
|
||||
throw new RuntimeException("Error while invoking method "
|
||||
+ method.getClass().getName() + "." + method.getName() + "("
|
||||
logger.error("Error while invoking method " + method.getClass().getName() + "." + method.getName() + "("
|
||||
+ Arrays.asList(args) + ")", e);
|
||||
throw new RuntimeException("Error while invoking method " + method.getClass().getName() + "."
|
||||
+ method.getName() + "(" + Arrays.asList(args) + ")", e);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
logger.error("Error while invoking method " + method.getClass().getName()
|
||||
+ "." + method.getName() + "(" + Arrays.asList(args) + ")", e);
|
||||
throw new RuntimeException("Error while invoking method "
|
||||
+ method.getClass().getName() + "." + method.getName() + "("
|
||||
logger.error("Error while invoking method " + method.getClass().getName() + "." + method.getName() + "("
|
||||
+ Arrays.asList(args) + ")", e);
|
||||
throw new RuntimeException("Error while invoking method " + method.getClass().getName() + "."
|
||||
+ method.getName() + "(" + Arrays.asList(args) + ")", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Method getMethod(String className, String methodName,
|
||||
String[] parameterTypeNames) {
|
||||
private static Method getMethod(String className, String methodName, String[] parameterTypeNames) {
|
||||
try {
|
||||
Class<?> c = Class.forName(className);
|
||||
final int len = parameterTypeNames.length;
|
||||
@@ -201,40 +190,40 @@ final class DefaultWASUsernameAndGroupsExtractor implements WASUsernameAndGroups
|
||||
throw new RuntimeException("Required class" + className + " not found", e);
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
logger.error("Required method " + methodName + " with parameter types ("
|
||||
+ Arrays.asList(parameterTypeNames) + ") not found on class "
|
||||
+ className);
|
||||
logger.error("Required method " + methodName + " with parameter types (" + Arrays.asList(parameterTypeNames)
|
||||
+ ") not found on class " + className);
|
||||
throw new RuntimeException("Required class" + className + " not found", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Method getRunAsSubjectMethod() {
|
||||
if (getRunAsSubject == null) {
|
||||
getRunAsSubject = getMethod("com.ibm.websphere.security.auth.WSSubject",
|
||||
"getRunAsSubject", new String[] {});
|
||||
getRunAsSubject = getMethod("com.ibm.websphere.security.auth.WSSubject", "getRunAsSubject",
|
||||
new String[] {});
|
||||
}
|
||||
return getRunAsSubject;
|
||||
}
|
||||
|
||||
private static Method getGroupsForUserMethod() {
|
||||
if (getGroupsForUser == null) {
|
||||
getGroupsForUser = getMethod("com.ibm.websphere.security.UserRegistry",
|
||||
"getGroupsForUser", new String[] { "java.lang.String" });
|
||||
getGroupsForUser = getMethod("com.ibm.websphere.security.UserRegistry", "getGroupsForUser",
|
||||
new String[] { "java.lang.String" });
|
||||
}
|
||||
return getGroupsForUser;
|
||||
}
|
||||
|
||||
private static Method getSecurityNameMethod() {
|
||||
if (getSecurityName == null) {
|
||||
getSecurityName = getMethod("com.ibm.websphere.security.cred.WSCredential",
|
||||
"getSecurityName", new String[] {});
|
||||
getSecurityName = getMethod("com.ibm.websphere.security.cred.WSCredential", "getSecurityName",
|
||||
new String[] {});
|
||||
}
|
||||
return getSecurityName;
|
||||
}
|
||||
|
||||
private static Method getNarrowMethod() {
|
||||
if (narrow == null) {
|
||||
narrow = getMethod(PORTABLE_REMOTE_OBJECT_CLASSNAME, "narrow", new String[] { Object.class.getName() , Class.class.getName()});
|
||||
narrow = getMethod(PORTABLE_REMOTE_OBJECT_CLASSNAME, "narrow",
|
||||
new String[] { Object.class.getName(), Class.class.getName() });
|
||||
}
|
||||
return narrow;
|
||||
}
|
||||
|
||||
+1
@@ -31,4 +31,5 @@ interface WASUsernameAndGroupsExtractor {
|
||||
List<String> getGroupsForCurrentUser();
|
||||
|
||||
String getCurrentUserName();
|
||||
|
||||
}
|
||||
|
||||
+3
-2
@@ -27,8 +27,8 @@ import org.springframework.security.web.authentication.preauth.AbstractPreAuthen
|
||||
* @author Ruud Senden
|
||||
* @since 2.0
|
||||
*/
|
||||
public class WebSpherePreAuthenticatedProcessingFilter extends
|
||||
AbstractPreAuthenticatedProcessingFilter {
|
||||
public class WebSpherePreAuthenticatedProcessingFilter extends AbstractPreAuthenticatedProcessingFilter {
|
||||
|
||||
private final WASUsernameAndGroupsExtractor wasHelper;
|
||||
|
||||
/**
|
||||
@@ -62,4 +62,5 @@ public class WebSpherePreAuthenticatedProcessingFilter extends
|
||||
protected Object getPreAuthenticatedCredentials(HttpServletRequest httpRequest) {
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-11
@@ -33,9 +33,9 @@ import java.util.*;
|
||||
*
|
||||
* @author Ruud Senden
|
||||
*/
|
||||
public class WebSpherePreAuthenticatedWebAuthenticationDetailsSource
|
||||
implements
|
||||
public class WebSpherePreAuthenticatedWebAuthenticationDetailsSource implements
|
||||
AuthenticationDetailsSource<HttpServletRequest, PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails> {
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private Attributes2GrantedAuthoritiesMapper webSphereGroups2GrantedAuthoritiesMapper = new SimpleAttributes2GrantedAuthoritiesMapper();
|
||||
@@ -46,20 +46,17 @@ public class WebSpherePreAuthenticatedWebAuthenticationDetailsSource
|
||||
this(new DefaultWASUsernameAndGroupsExtractor());
|
||||
}
|
||||
|
||||
public WebSpherePreAuthenticatedWebAuthenticationDetailsSource(
|
||||
WASUsernameAndGroupsExtractor wasHelper) {
|
||||
public WebSpherePreAuthenticatedWebAuthenticationDetailsSource(WASUsernameAndGroupsExtractor wasHelper) {
|
||||
this.wasHelper = wasHelper;
|
||||
}
|
||||
|
||||
public PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails buildDetails(
|
||||
HttpServletRequest context) {
|
||||
public PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails buildDetails(HttpServletRequest context) {
|
||||
return new PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails(context,
|
||||
getWebSphereGroupsBasedGrantedAuthorities());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of Granted Authorities based on the current user's WebSphere groups.
|
||||
*
|
||||
* @return authorities mapped from the user's WebSphere groups.
|
||||
*/
|
||||
private Collection<? extends GrantedAuthority> getWebSphereGroupsBasedGrantedAuthorities() {
|
||||
@@ -67,8 +64,7 @@ public class WebSpherePreAuthenticatedWebAuthenticationDetailsSource
|
||||
Collection<? extends GrantedAuthority> userGas = webSphereGroups2GrantedAuthoritiesMapper
|
||||
.getGrantedAuthorities(webSphereGroups);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("WebSphere groups: " + webSphereGroups
|
||||
+ " mapped to Granted Authorities: " + userGas);
|
||||
logger.debug("WebSphere groups: " + webSphereGroups + " mapped to Granted Authorities: " + userGas);
|
||||
}
|
||||
return userGas;
|
||||
}
|
||||
@@ -77,8 +73,7 @@ public class WebSpherePreAuthenticatedWebAuthenticationDetailsSource
|
||||
* @param mapper The Attributes2GrantedAuthoritiesMapper to use for converting the WAS
|
||||
* groups to authorities
|
||||
*/
|
||||
public void setWebSphereGroups2GrantedAuthoritiesMapper(
|
||||
Attributes2GrantedAuthoritiesMapper mapper) {
|
||||
public void setWebSphereGroups2GrantedAuthoritiesMapper(Attributes2GrantedAuthoritiesMapper mapper) {
|
||||
webSphereGroups2GrantedAuthoritiesMapper = mapper;
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -17,4 +17,3 @@
|
||||
* Websphere-specific pre-authentication classes.
|
||||
*/
|
||||
package org.springframework.security.web.authentication.preauth.websphere;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user