mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-07-07 03:02:23 +00:00
Use PathPatternRequestMatcher in config
This commit changes the config module to use PathPatternRequestMatcher in favor of MvcRequestMatcher and AntPathRequestMatcher. This allows removing several HandlerMappingIntrospector support classes as well which were in place to support MvcRequestMatcher. Issue gh-16886 Issue gh-16887
This commit is contained in:
parent
f709a9efef
commit
3e53cc2c4a
@ -18,41 +18,20 @@ package org.springframework.security.config.annotation.web;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import jakarta.servlet.DispatcherType;
|
import jakarta.servlet.DispatcherType;
|
||||||
import jakarta.servlet.ServletContext;
|
|
||||||
import jakarta.servlet.ServletRegistration;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.core.ResolvableType;
|
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.security.config.ObjectPostProcessor;
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
import org.springframework.security.config.annotation.web.ServletRegistrationsSupport.RegistrationMapping;
|
|
||||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher;
|
import org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
|
||||||
import org.springframework.web.servlet.DispatcherServlet;
|
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A base class for registering {@link RequestMatcher}'s. For example, it might allow for
|
* A base class for registering {@link RequestMatcher}'s. For example, it might allow for
|
||||||
@ -65,23 +44,12 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|||||||
*/
|
*/
|
||||||
public abstract class AbstractRequestMatcherRegistry<C> {
|
public abstract class AbstractRequestMatcherRegistry<C> {
|
||||||
|
|
||||||
private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector";
|
|
||||||
|
|
||||||
private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector";
|
|
||||||
|
|
||||||
private static final boolean mvcPresent;
|
|
||||||
|
|
||||||
private static final RequestMatcher ANY_REQUEST = AnyRequestMatcher.INSTANCE;
|
private static final RequestMatcher ANY_REQUEST = AnyRequestMatcher.INSTANCE;
|
||||||
|
|
||||||
private ApplicationContext context;
|
private ApplicationContext context;
|
||||||
|
|
||||||
private boolean anyRequestConfigured = false;
|
private boolean anyRequestConfigured = false;
|
||||||
|
|
||||||
static {
|
|
||||||
mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR,
|
|
||||||
AbstractRequestMatcherRegistry.class.getClassLoader());
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Log logger = LogFactory.getLog(getClass());
|
private final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
protected final void setApplicationContext(ApplicationContext context) {
|
protected final void setApplicationContext(ApplicationContext context) {
|
||||||
@ -107,40 +75,6 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||||||
return configurer;
|
return configurer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates {@link MvcRequestMatcher} instances for the method and patterns passed in
|
|
||||||
* @param method the HTTP method to use or null if any should be used
|
|
||||||
* @param mvcPatterns the Spring MVC patterns to match on
|
|
||||||
* @return a List of {@link MvcRequestMatcher} instances
|
|
||||||
* @deprecated Please use
|
|
||||||
* {@link org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.Builder}
|
|
||||||
* instead
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
protected final List<MvcRequestMatcher> createMvcMatchers(HttpMethod method, String... mvcPatterns) {
|
|
||||||
Assert.state(!this.anyRequestConfigured, "Can't configure mvcMatchers after anyRequest");
|
|
||||||
ResolvableType type = ResolvableType.forClassWithGenerics(ObjectPostProcessor.class, Object.class);
|
|
||||||
ObjectProvider<ObjectPostProcessor<Object>> postProcessors = this.context.getBeanProvider(type);
|
|
||||||
ObjectPostProcessor<Object> opp = postProcessors.getObject();
|
|
||||||
if (!this.context.containsBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) {
|
|
||||||
throw new NoSuchBeanDefinitionException("A Bean named " + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME
|
|
||||||
+ " of type " + HandlerMappingIntrospector.class.getName()
|
|
||||||
+ " is required to use MvcRequestMatcher. Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext.");
|
|
||||||
}
|
|
||||||
HandlerMappingIntrospector introspector = this.context.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME,
|
|
||||||
HandlerMappingIntrospector.class);
|
|
||||||
List<MvcRequestMatcher> matchers = new ArrayList<>(mvcPatterns.length);
|
|
||||||
for (String mvcPattern : mvcPatterns) {
|
|
||||||
MvcRequestMatcher matcher = new MvcRequestMatcher(introspector, mvcPattern);
|
|
||||||
opp.postProcess(matcher);
|
|
||||||
if (method != null) {
|
|
||||||
matcher.setMethod(method);
|
|
||||||
}
|
|
||||||
matchers.add(matcher);
|
|
||||||
}
|
|
||||||
return matchers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps a {@link List} of
|
* Maps a {@link List} of
|
||||||
* {@link org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher}
|
* {@link org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher}
|
||||||
@ -184,12 +118,9 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* If the {@link HandlerMappingIntrospector} is available in the classpath, maps to an
|
* Match when the {@link HttpMethod} is {@code method} and when the request URI
|
||||||
* {@link MvcRequestMatcher} that also specifies a specific {@link HttpMethod} to
|
* matches one of {@code patterns}. See
|
||||||
* match on. This matcher will use the same rules that Spring MVC uses for matching.
|
* {@link org.springframework.web.util.pattern.PathPattern} for matching rules.
|
||||||
* For example, often times a mapping of the path "/path" will match on "/path",
|
|
||||||
* "/path/", "/path.html", etc. If the {@link HandlerMappingIntrospector} is not
|
|
||||||
* available, maps to an {@link AntPathRequestMatcher}.
|
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* If a specific {@link RequestMatcher} must be specified, use
|
* If a specific {@link RequestMatcher} must be specified, use
|
||||||
@ -197,8 +128,7 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||||||
* </p>
|
* </p>
|
||||||
* @param method the {@link HttpMethod} to use or {@code null} for any
|
* @param method the {@link HttpMethod} to use or {@code null} for any
|
||||||
* {@link HttpMethod}.
|
* {@link HttpMethod}.
|
||||||
* @param patterns the patterns to match on. The rules for matching are defined by
|
* @param patterns the patterns to match on
|
||||||
* Spring MVC if {@link MvcRequestMatcher} is used
|
|
||||||
* @return the object that is chained after creating the {@link RequestMatcher}.
|
* @return the object that is chained after creating the {@link RequestMatcher}.
|
||||||
* @since 5.8
|
* @since 5.8
|
||||||
*/
|
*/
|
||||||
@ -209,27 +139,11 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||||||
+ "leading slash in all your request matcher patterns. In future versions of "
|
+ "leading slash in all your request matcher patterns. In future versions of "
|
||||||
+ "Spring Security, leaving out the leading slash will result in an exception.");
|
+ "Spring Security, leaving out the leading slash will result in an exception.");
|
||||||
}
|
}
|
||||||
if (!mvcPresent) {
|
Assert.state(!this.anyRequestConfigured, "Can't configure requestMatchers after anyRequest");
|
||||||
return requestMatchers(RequestMatchers.antMatchersAsArray(method, patterns));
|
PathPatternRequestMatcher.Builder builder = this.context.getBean(PathPatternRequestMatcher.Builder.class);
|
||||||
}
|
|
||||||
if (!(this.context instanceof WebApplicationContext)) {
|
|
||||||
return requestMatchers(RequestMatchers.antMatchersAsArray(method, patterns));
|
|
||||||
}
|
|
||||||
WebApplicationContext context = (WebApplicationContext) this.context;
|
|
||||||
ServletContext servletContext = context.getServletContext();
|
|
||||||
if (servletContext == null) {
|
|
||||||
return requestMatchers(RequestMatchers.antMatchersAsArray(method, patterns));
|
|
||||||
}
|
|
||||||
List<RequestMatcher> matchers = new ArrayList<>();
|
List<RequestMatcher> matchers = new ArrayList<>();
|
||||||
for (String pattern : patterns) {
|
for (String pattern : patterns) {
|
||||||
if (RequestMatcherFactory.usesPathPatterns()) {
|
matchers.add(builder.matcher(method, pattern));
|
||||||
matchers.add(RequestMatcherFactory.matcher(method, pattern));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
AntPathRequestMatcher ant = new AntPathRequestMatcher(pattern, (method != null) ? method.name() : null);
|
|
||||||
MvcRequestMatcher mvc = createMvcMatchers(method, pattern).get(0);
|
|
||||||
matchers.add(new DeferredRequestMatcher((c) -> resolve(ant, mvc, c), mvc, ant));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return requestMatchers(matchers.toArray(new RequestMatcher[0]));
|
return requestMatchers(matchers.toArray(new RequestMatcher[0]));
|
||||||
}
|
}
|
||||||
@ -243,64 +157,16 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private RequestMatcher resolve(AntPathRequestMatcher ant, MvcRequestMatcher mvc, ServletContext servletContext) {
|
|
||||||
ServletRegistrationsSupport registrations = new ServletRegistrationsSupport(servletContext);
|
|
||||||
Collection<RegistrationMapping> mappings = registrations.mappings();
|
|
||||||
if (mappings.isEmpty()) {
|
|
||||||
return new DispatcherServletDelegatingRequestMatcher(ant, mvc, new MockMvcRequestMatcher());
|
|
||||||
}
|
|
||||||
Collection<RegistrationMapping> dispatcherServletMappings = registrations.dispatcherServletMappings();
|
|
||||||
if (dispatcherServletMappings.isEmpty()) {
|
|
||||||
return new DispatcherServletDelegatingRequestMatcher(ant, mvc, new MockMvcRequestMatcher());
|
|
||||||
}
|
|
||||||
if (dispatcherServletMappings.size() > 1) {
|
|
||||||
String errorMessage = computeErrorMessage(servletContext.getServletRegistrations().values());
|
|
||||||
throw new IllegalArgumentException(errorMessage);
|
|
||||||
}
|
|
||||||
RegistrationMapping dispatcherServlet = dispatcherServletMappings.iterator().next();
|
|
||||||
if (mappings.size() > 1 && !dispatcherServlet.isDefault()) {
|
|
||||||
String errorMessage = computeErrorMessage(servletContext.getServletRegistrations().values());
|
|
||||||
throw new IllegalArgumentException(errorMessage);
|
|
||||||
}
|
|
||||||
if (dispatcherServlet.isDefault()) {
|
|
||||||
if (mappings.size() == 1) {
|
|
||||||
return mvc;
|
|
||||||
}
|
|
||||||
return new DispatcherServletDelegatingRequestMatcher(ant, mvc);
|
|
||||||
}
|
|
||||||
return mvc;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String computeErrorMessage(Collection<? extends ServletRegistration> registrations) {
|
|
||||||
String template = """
|
|
||||||
This method cannot decide whether these patterns are Spring MVC patterns or not. \
|
|
||||||
This is because there is more than one mappable servlet in your servlet context: %s.
|
|
||||||
|
|
||||||
To address this, please create one PathPatternRequestMatcher.Builder#servletPath for each servlet that has \
|
|
||||||
authorized endpoints and use them to construct request matchers manually.
|
|
||||||
""";
|
|
||||||
Map<String, Collection<String>> mappings = new LinkedHashMap<>();
|
|
||||||
for (ServletRegistration registration : registrations) {
|
|
||||||
mappings.put(registration.getClassName(), registration.getMappings());
|
|
||||||
}
|
|
||||||
return String.format(template, mappings);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* If the {@link HandlerMappingIntrospector} is available in the classpath, maps to an
|
* Match when the request URI matches one of {@code patterns}. See
|
||||||
* {@link MvcRequestMatcher} that does not care which {@link HttpMethod} is used. This
|
* {@link org.springframework.web.util.pattern.PathPattern} for matching rules.
|
||||||
* matcher will use the same rules that Spring MVC uses for matching. For example,
|
|
||||||
* often times a mapping of the path "/path" will match on "/path", "/path/",
|
|
||||||
* "/path.html", etc. If the {@link HandlerMappingIntrospector} is not available, maps
|
|
||||||
* to an {@link AntPathRequestMatcher}.
|
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* If a specific {@link RequestMatcher} must be specified, use
|
* If a specific {@link RequestMatcher} must be specified, use
|
||||||
* {@link #requestMatchers(RequestMatcher...)} instead
|
* {@link #requestMatchers(RequestMatcher...)} instead
|
||||||
* </p>
|
* </p>
|
||||||
* @param patterns the patterns to match on. The rules for matching are defined by
|
* @param patterns the patterns to match on
|
||||||
* Spring MVC if {@link MvcRequestMatcher} is used
|
|
||||||
* @return the object that is chained after creating the {@link RequestMatcher}.
|
* @return the object that is chained after creating the {@link RequestMatcher}.
|
||||||
* @since 5.8
|
* @since 5.8
|
||||||
*/
|
*/
|
||||||
@ -310,12 +176,7 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* If the {@link HandlerMappingIntrospector} is available in the classpath, maps to an
|
* Match when the {@link HttpMethod} is {@code method}
|
||||||
* {@link MvcRequestMatcher} that matches on a specific {@link HttpMethod}. This
|
|
||||||
* matcher will use the same rules that Spring MVC uses for matching. For example,
|
|
||||||
* often times a mapping of the path "/path" will match on "/path", "/path/",
|
|
||||||
* "/path.html", etc. If the {@link HandlerMappingIntrospector} is not available, maps
|
|
||||||
* to an {@link AntPathRequestMatcher}.
|
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* If a specific {@link RequestMatcher} must be specified, use
|
* If a specific {@link RequestMatcher} must be specified, use
|
||||||
@ -339,182 +200,4 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||||||
*/
|
*/
|
||||||
protected abstract C chainRequestMatchers(List<RequestMatcher> requestMatchers);
|
protected abstract C chainRequestMatchers(List<RequestMatcher> requestMatchers);
|
||||||
|
|
||||||
/**
|
|
||||||
* Utilities for creating {@link RequestMatcher} instances.
|
|
||||||
*
|
|
||||||
* @author Rob Winch
|
|
||||||
* @since 3.2
|
|
||||||
*/
|
|
||||||
private static final class RequestMatchers {
|
|
||||||
|
|
||||||
private RequestMatchers() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a {@link List} of {@link AntPathRequestMatcher} instances.
|
|
||||||
* @param httpMethod the {@link HttpMethod} to use or {@code null} for any
|
|
||||||
* {@link HttpMethod}.
|
|
||||||
* @param antPatterns the ant patterns to create {@link AntPathRequestMatcher}
|
|
||||||
* from
|
|
||||||
* @return a {@link List} of {@link AntPathRequestMatcher} instances
|
|
||||||
*/
|
|
||||||
static List<RequestMatcher> antMatchers(HttpMethod httpMethod, String... antPatterns) {
|
|
||||||
return Arrays.asList(antMatchersAsArray(httpMethod, antPatterns));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a {@link List} of {@link AntPathRequestMatcher} instances that do not
|
|
||||||
* specify an {@link HttpMethod}.
|
|
||||||
* @param antPatterns the ant patterns to create {@link AntPathRequestMatcher}
|
|
||||||
* from
|
|
||||||
* @return a {@link List} of {@link AntPathRequestMatcher} instances
|
|
||||||
*/
|
|
||||||
static List<RequestMatcher> antMatchers(String... antPatterns) {
|
|
||||||
return antMatchers(null, antPatterns);
|
|
||||||
}
|
|
||||||
|
|
||||||
static RequestMatcher[] antMatchersAsArray(HttpMethod httpMethod, String... antPatterns) {
|
|
||||||
String method = (httpMethod != null) ? httpMethod.toString() : null;
|
|
||||||
RequestMatcher[] matchers = new RequestMatcher[antPatterns.length];
|
|
||||||
for (int index = 0; index < antPatterns.length; index++) {
|
|
||||||
matchers[index] = new AntPathRequestMatcher(antPatterns[index], method);
|
|
||||||
}
|
|
||||||
return matchers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a {@link List} of {@link RegexRequestMatcher} instances.
|
|
||||||
* @param httpMethod the {@link HttpMethod} to use or {@code null} for any
|
|
||||||
* {@link HttpMethod}.
|
|
||||||
* @param regexPatterns the regular expressions to create
|
|
||||||
* {@link RegexRequestMatcher} from
|
|
||||||
* @return a {@link List} of {@link RegexRequestMatcher} instances
|
|
||||||
*/
|
|
||||||
static List<RequestMatcher> regexMatchers(HttpMethod httpMethod, String... regexPatterns) {
|
|
||||||
String method = (httpMethod != null) ? httpMethod.toString() : null;
|
|
||||||
List<RequestMatcher> matchers = new ArrayList<>();
|
|
||||||
for (String pattern : regexPatterns) {
|
|
||||||
matchers.add(new RegexRequestMatcher(pattern, method));
|
|
||||||
}
|
|
||||||
return matchers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a {@link List} of {@link RegexRequestMatcher} instances that do not
|
|
||||||
* specify an {@link HttpMethod}.
|
|
||||||
* @param regexPatterns the regular expressions to create
|
|
||||||
* {@link RegexRequestMatcher} from
|
|
||||||
* @return a {@link List} of {@link RegexRequestMatcher} instances
|
|
||||||
*/
|
|
||||||
static List<RequestMatcher> regexMatchers(String... regexPatterns) {
|
|
||||||
return regexMatchers(null, regexPatterns);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class DeferredRequestMatcher implements RequestMatcher {
|
|
||||||
|
|
||||||
final Function<ServletContext, RequestMatcher> requestMatcherFactory;
|
|
||||||
|
|
||||||
final AtomicReference<String> description = new AtomicReference<>();
|
|
||||||
|
|
||||||
final Map<ServletContext, RequestMatcher> requestMatchers = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
DeferredRequestMatcher(Function<ServletContext, RequestMatcher> resolver, RequestMatcher... candidates) {
|
|
||||||
this.requestMatcherFactory = (sc) -> this.requestMatchers.computeIfAbsent(sc, resolver);
|
|
||||||
this.description.set("Deferred " + Arrays.toString(candidates));
|
|
||||||
}
|
|
||||||
|
|
||||||
RequestMatcher requestMatcher(ServletContext servletContext) {
|
|
||||||
return this.requestMatcherFactory.apply(servletContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean matches(HttpServletRequest request) {
|
|
||||||
return this.requestMatcherFactory.apply(request.getServletContext()).matches(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MatchResult matcher(HttpServletRequest request) {
|
|
||||||
return this.requestMatcherFactory.apply(request.getServletContext()).matcher(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return this.description.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class MockMvcRequestMatcher implements RequestMatcher {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean matches(HttpServletRequest request) {
|
|
||||||
return request.getAttribute("org.springframework.test.web.servlet.MockMvc.MVC_RESULT_ATTRIBUTE") != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class DispatcherServletRequestMatcher implements RequestMatcher {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean matches(HttpServletRequest request) {
|
|
||||||
String name = request.getHttpServletMapping().getServletName();
|
|
||||||
ServletRegistration registration = request.getServletContext().getServletRegistration(name);
|
|
||||||
Assert.notNull(registration,
|
|
||||||
() -> computeErrorMessage(request.getServletContext().getServletRegistrations().values()));
|
|
||||||
try {
|
|
||||||
Class<?> clazz = Class.forName(registration.getClassName());
|
|
||||||
return DispatcherServlet.class.isAssignableFrom(clazz);
|
|
||||||
}
|
|
||||||
catch (ClassNotFoundException ex) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class DispatcherServletDelegatingRequestMatcher implements RequestMatcher {
|
|
||||||
|
|
||||||
private final AntPathRequestMatcher ant;
|
|
||||||
|
|
||||||
private final MvcRequestMatcher mvc;
|
|
||||||
|
|
||||||
private final RequestMatcher dispatcherServlet;
|
|
||||||
|
|
||||||
DispatcherServletDelegatingRequestMatcher(AntPathRequestMatcher ant, MvcRequestMatcher mvc) {
|
|
||||||
this(ant, mvc, new OrRequestMatcher(new MockMvcRequestMatcher(), new DispatcherServletRequestMatcher()));
|
|
||||||
}
|
|
||||||
|
|
||||||
DispatcherServletDelegatingRequestMatcher(AntPathRequestMatcher ant, MvcRequestMatcher mvc,
|
|
||||||
RequestMatcher dispatcherServlet) {
|
|
||||||
this.ant = ant;
|
|
||||||
this.mvc = mvc;
|
|
||||||
this.dispatcherServlet = dispatcherServlet;
|
|
||||||
}
|
|
||||||
|
|
||||||
RequestMatcher requestMatcher(HttpServletRequest request) {
|
|
||||||
if (this.dispatcherServlet.matches(request)) {
|
|
||||||
return this.mvc;
|
|
||||||
}
|
|
||||||
return this.ant;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean matches(HttpServletRequest request) {
|
|
||||||
return requestMatcher(request).matches(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MatchResult matcher(HttpServletRequest request) {
|
|
||||||
return requestMatcher(request).matcher(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "DispatcherServletDelegating [" + "ant = " + this.ant + ", mvc = " + this.mvc + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2002-2025 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.config.annotation.web;
|
|
||||||
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.http.HttpMethod;
|
|
||||||
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This utility exists only to facilitate applications opting into using path patterns in
|
|
||||||
* the HttpSecurity DSL. It is for internal use only.
|
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
public final class RequestMatcherFactory {
|
|
||||||
|
|
||||||
private static PathPatternRequestMatcher.Builder builder;
|
|
||||||
|
|
||||||
public static void setApplicationContext(ApplicationContext context) {
|
|
||||||
builder = context.getBeanProvider(PathPatternRequestMatcher.Builder.class).getIfUnique();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean usesPathPatterns() {
|
|
||||||
return builder != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static RequestMatcher matcher(String path) {
|
|
||||||
return matcher(null, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static RequestMatcher matcher(HttpMethod method, String path) {
|
|
||||||
if (builder != null) {
|
|
||||||
return builder.matcher(method, path);
|
|
||||||
}
|
|
||||||
return new AntPathRequestMatcher(path, (method != null) ? method.name() : null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private RequestMatcherFactory() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -28,7 +28,6 @@ import jakarta.servlet.ServletRequest;
|
|||||||
import jakarta.servlet.ServletResponse;
|
import jakarta.servlet.ServletResponse;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.core.OrderComparator;
|
import org.springframework.core.OrderComparator;
|
||||||
@ -45,7 +44,6 @@ import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
|
|||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
import org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry;
|
import org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry;
|
||||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||||
import org.springframework.security.config.annotation.web.RequestMatcherFactory;
|
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration;
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration;
|
||||||
import org.springframework.security.config.annotation.web.configurers.AnonymousConfigurer;
|
import org.springframework.security.config.annotation.web.configurers.AnonymousConfigurer;
|
||||||
@ -91,17 +89,14 @@ import org.springframework.security.web.PortMapperImpl;
|
|||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
|
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
|
||||||
import org.springframework.security.web.context.SecurityContextRepository;
|
import org.springframework.security.web.context.SecurityContextRepository;
|
||||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
import org.springframework.security.web.session.HttpSessionEventPublisher;
|
import org.springframework.security.web.session.HttpSessionEventPublisher;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
import org.springframework.web.cors.CorsConfiguration;
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
import org.springframework.web.filter.CorsFilter;
|
import org.springframework.web.filter.CorsFilter;
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link HttpSecurity} is similar to Spring Security's XML <http> element in the
|
* A {@link HttpSecurity} is similar to Spring Security's XML <http> element in the
|
||||||
@ -153,12 +148,6 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|||||||
public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<DefaultSecurityFilterChain, HttpSecurity>
|
public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<DefaultSecurityFilterChain, HttpSecurity>
|
||||||
implements SecurityBuilder<DefaultSecurityFilterChain>, HttpSecurityBuilder<HttpSecurity> {
|
implements SecurityBuilder<DefaultSecurityFilterChain>, HttpSecurityBuilder<HttpSecurity> {
|
||||||
|
|
||||||
private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector";
|
|
||||||
|
|
||||||
private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector";
|
|
||||||
|
|
||||||
private static final boolean mvcPresent;
|
|
||||||
|
|
||||||
private final RequestMatcherConfigurer requestMatcherConfigurer;
|
private final RequestMatcherConfigurer requestMatcherConfigurer;
|
||||||
|
|
||||||
private List<OrderedFilter> filters = new ArrayList<>();
|
private List<OrderedFilter> filters = new ArrayList<>();
|
||||||
@ -169,10 +158,6 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
|||||||
|
|
||||||
private AuthenticationManager authenticationManager;
|
private AuthenticationManager authenticationManager;
|
||||||
|
|
||||||
static {
|
|
||||||
mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, HttpSecurity.class.getClassLoader());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
* @param objectPostProcessor the {@link ObjectPostProcessor} that should be used
|
* @param objectPostProcessor the {@link ObjectPostProcessor} that should be used
|
||||||
@ -303,9 +288,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
|||||||
/**
|
/**
|
||||||
* Adds a {@link CorsFilter} to be used. If a bean by the name of corsFilter is
|
* Adds a {@link CorsFilter} to be used. If a bean by the name of corsFilter is
|
||||||
* provided, that {@link CorsFilter} is used. Else if corsConfigurationSource is
|
* provided, that {@link CorsFilter} is used. Else if corsConfigurationSource is
|
||||||
* defined, then that {@link CorsConfiguration} is used. Otherwise, if Spring MVC is
|
* defined, then that {@link CorsConfiguration} is used. You can enable CORS using:
|
||||||
* on the classpath a {@link HandlerMappingIntrospector} is used. You can enable CORS
|
|
||||||
* using:
|
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* @Configuration
|
* @Configuration
|
||||||
@ -2174,7 +2157,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
|||||||
* {@link #securityMatchers()}
|
* {@link #securityMatchers()}
|
||||||
* </p>
|
* </p>
|
||||||
* @param requestMatcher the {@link RequestMatcher} to use, for example,
|
* @param requestMatcher the {@link RequestMatcher} to use, for example,
|
||||||
* {@code PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.GET, "/admin/**")}
|
* {@code PathPatternRequestMatcher.pathPattern(HttpMethod.GET, "/admin/**")}
|
||||||
* @return the {@link HttpSecurity} for further customizations
|
* @return the {@link HttpSecurity} for further customizations
|
||||||
* @see #securityMatcher(String...)
|
* @see #securityMatcher(String...)
|
||||||
*/
|
*/
|
||||||
@ -2185,10 +2168,8 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows configuring the {@link HttpSecurity} to only be invoked when matching the
|
* Allows configuring the {@link HttpSecurity} to only be invoked when matching the
|
||||||
* provided pattern. This method creates a {@link MvcRequestMatcher} if Spring MVC is
|
* provided set of {@code patterns}. See
|
||||||
* in the classpath or creates an {@link AntPathRequestMatcher} if not. If more
|
* {@link org.springframework.web.util.pattern.PathPattern} for matching rules
|
||||||
* advanced configuration is necessary, consider using
|
|
||||||
* {@link #securityMatchers(Customizer)} or {@link #securityMatcher(RequestMatcher)}.
|
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Invoking {@link #securityMatcher(String...)} will override previous invocations of
|
* Invoking {@link #securityMatcher(String...)} will override previous invocations of
|
||||||
@ -2198,19 +2179,14 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
|||||||
* </p>
|
* </p>
|
||||||
* @param patterns the pattern to match on (i.e. "/admin/**")
|
* @param patterns the pattern to match on (i.e. "/admin/**")
|
||||||
* @return the {@link HttpSecurity} for further customizations
|
* @return the {@link HttpSecurity} for further customizations
|
||||||
* @see AntPathRequestMatcher
|
* @see org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher
|
||||||
* @see MvcRequestMatcher
|
* @see org.springframework.web.util.pattern.PathPattern
|
||||||
*/
|
*/
|
||||||
public HttpSecurity securityMatcher(String... patterns) {
|
public HttpSecurity securityMatcher(String... patterns) {
|
||||||
List<RequestMatcher> matchers = new ArrayList<>();
|
List<RequestMatcher> matchers = new ArrayList<>();
|
||||||
|
PathPatternRequestMatcher.Builder builder = getContext().getBean(PathPatternRequestMatcher.Builder.class);
|
||||||
for (String pattern : patterns) {
|
for (String pattern : patterns) {
|
||||||
if (RequestMatcherFactory.usesPathPatterns()) {
|
matchers.add(builder.matcher(pattern));
|
||||||
matchers.add(RequestMatcherFactory.matcher(pattern));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
RequestMatcher matcher = mvcPresent ? createMvcMatcher(pattern) : createAntMatcher(pattern);
|
|
||||||
matchers.add(matcher);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.requestMatcher = new OrRequestMatcher(matchers);
|
this.requestMatcher = new OrRequestMatcher(matchers);
|
||||||
return this;
|
return this;
|
||||||
@ -2241,26 +2217,6 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
|||||||
return HttpSecurity.this;
|
return HttpSecurity.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private RequestMatcher createAntMatcher(String pattern) {
|
|
||||||
return new AntPathRequestMatcher(pattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
private RequestMatcher createMvcMatcher(String mvcPattern) {
|
|
||||||
ResolvableType type = ResolvableType.forClassWithGenerics(ObjectPostProcessor.class, Object.class);
|
|
||||||
ObjectProvider<ObjectPostProcessor<Object>> postProcessors = getContext().getBeanProvider(type);
|
|
||||||
ObjectPostProcessor<Object> opp = postProcessors.getObject();
|
|
||||||
if (!getContext().containsBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) {
|
|
||||||
throw new NoSuchBeanDefinitionException("A Bean named " + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME
|
|
||||||
+ " of type " + HandlerMappingIntrospector.class.getName()
|
|
||||||
+ " is required to use MvcRequestMatcher. Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext.");
|
|
||||||
}
|
|
||||||
HandlerMappingIntrospector introspector = getContext().getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME,
|
|
||||||
HandlerMappingIntrospector.class);
|
|
||||||
MvcRequestMatcher matcher = new MvcRequestMatcher(introspector, mvcPattern);
|
|
||||||
opp.postProcess(matcher);
|
|
||||||
return matcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the {@link SecurityConfigurer} has already been specified get the original,
|
* If the {@link SecurityConfigurer} has already been specified get the original,
|
||||||
* otherwise apply the new {@link SecurityConfigurerAdapter}.
|
* otherwise apply the new {@link SecurityConfigurerAdapter}.
|
||||||
|
@ -55,6 +55,7 @@ import org.springframework.security.web.SecurityFilterChain;
|
|||||||
import org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator;
|
import org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator;
|
||||||
import org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator.HttpServletRequestTransformer;
|
import org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator.HttpServletRequestTransformer;
|
||||||
import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator;
|
import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator;
|
||||||
|
import org.springframework.security.web.access.PathPatternRequestTransformer;
|
||||||
import org.springframework.security.web.access.RequestMatcherDelegatingWebInvocationPrivilegeEvaluator;
|
import org.springframework.security.web.access.RequestMatcherDelegatingWebInvocationPrivilegeEvaluator;
|
||||||
import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
|
import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
|
||||||
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
|
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
|
||||||
@ -422,7 +423,7 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder<Filter,
|
|||||||
this.filterChainDecoratorPostProcessor = postProcessor.getIfUnique(ObjectPostProcessor::identity);
|
this.filterChainDecoratorPostProcessor = postProcessor.getIfUnique(ObjectPostProcessor::identity);
|
||||||
Class<HttpServletRequestTransformer> requestTransformerClass = HttpServletRequestTransformer.class;
|
Class<HttpServletRequestTransformer> requestTransformerClass = HttpServletRequestTransformer.class;
|
||||||
this.privilegeEvaluatorRequestTransformer = applicationContext.getBeanProvider(requestTransformerClass)
|
this.privilegeEvaluatorRequestTransformer = applicationContext.getBeanProvider(requestTransformerClass)
|
||||||
.getIfUnique();
|
.getIfUnique(PathPatternRequestTransformer::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -35,7 +35,6 @@ import org.springframework.security.config.annotation.authentication.configurati
|
|||||||
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
|
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
|
||||||
import org.springframework.security.config.annotation.authentication.configurers.provisioning.JdbcUserDetailsManagerConfigurer;
|
import org.springframework.security.config.annotation.authentication.configurers.provisioning.JdbcUserDetailsManagerConfigurer;
|
||||||
import org.springframework.security.config.annotation.authentication.configurers.userdetails.DaoAuthenticationConfigurer;
|
import org.springframework.security.config.annotation.authentication.configurers.userdetails.DaoAuthenticationConfigurer;
|
||||||
import org.springframework.security.config.annotation.web.RequestMatcherFactory;
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||||
import org.springframework.security.config.annotation.web.configurers.DefaultLoginPageConfigurer;
|
import org.springframework.security.config.annotation.web.configurers.DefaultLoginPageConfigurer;
|
||||||
@ -105,7 +104,6 @@ class HttpSecurityConfiguration {
|
|||||||
@Bean(HTTPSECURITY_BEAN_NAME)
|
@Bean(HTTPSECURITY_BEAN_NAME)
|
||||||
@Scope("prototype")
|
@Scope("prototype")
|
||||||
HttpSecurity httpSecurity() throws Exception {
|
HttpSecurity httpSecurity() throws Exception {
|
||||||
RequestMatcherFactory.setApplicationContext(this.context);
|
|
||||||
LazyPasswordEncoder passwordEncoder = new LazyPasswordEncoder(this.context);
|
LazyPasswordEncoder passwordEncoder = new LazyPasswordEncoder(this.context);
|
||||||
AuthenticationManagerBuilder authenticationBuilder = new DefaultPasswordEncoderAuthenticationManagerBuilder(
|
AuthenticationManagerBuilder authenticationBuilder = new DefaultPasswordEncoderAuthenticationManagerBuilder(
|
||||||
this.objectPostProcessor, passwordEncoder);
|
this.objectPostProcessor, passwordEncoder);
|
||||||
|
@ -26,15 +26,7 @@ import jakarta.servlet.ServletRequest;
|
|||||||
import jakarta.servlet.ServletResponse;
|
import jakarta.servlet.ServletResponse;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import org.springframework.beans.BeanMetadataElement;
|
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
|
||||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
|
|
||||||
import org.springframework.beans.factory.support.ManagedList;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationContextAware;
|
import org.springframework.context.ApplicationContextAware;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@ -45,8 +37,6 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
|||||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||||
import org.springframework.security.web.FilterChainProxy;
|
import org.springframework.security.web.FilterChainProxy;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.access.HandlerMappingIntrospectorRequestTransformer;
|
|
||||||
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
|
|
||||||
import org.springframework.security.web.debug.DebugFilter;
|
import org.springframework.security.web.debug.DebugFilter;
|
||||||
import org.springframework.security.web.firewall.HttpFirewall;
|
import org.springframework.security.web.firewall.HttpFirewall;
|
||||||
import org.springframework.security.web.firewall.RequestRejectedHandler;
|
import org.springframework.security.web.firewall.RequestRejectedHandler;
|
||||||
@ -58,7 +48,6 @@ import org.springframework.web.filter.CompositeFilter;
|
|||||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|
||||||
import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -76,10 +65,6 @@ import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
|||||||
*/
|
*/
|
||||||
class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContextAware {
|
class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContextAware {
|
||||||
|
|
||||||
private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector";
|
|
||||||
|
|
||||||
private static final String PATH_PATTERN_REQUEST_TRANSFORMER_BEAN_NAME = "pathPatternRequestTransformer";
|
|
||||||
|
|
||||||
private BeanResolver beanResolver;
|
private BeanResolver beanResolver;
|
||||||
|
|
||||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||||
@ -121,86 +106,6 @@ class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
static BeanDefinitionRegistryPostProcessor springSecurityHandlerMappingIntrospectorBeanDefinitionRegistryPostProcessor() {
|
|
||||||
return new BeanDefinitionRegistryPostProcessor() {
|
|
||||||
@Override
|
|
||||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
|
|
||||||
if (!registry.containsBeanDefinition(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String hmiRequestTransformerBeanName = HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME + "RequestTransformer";
|
|
||||||
if (!registry.containsBeanDefinition(PATH_PATTERN_REQUEST_TRANSFORMER_BEAN_NAME)
|
|
||||||
&& !registry.containsBeanDefinition(hmiRequestTransformerBeanName)) {
|
|
||||||
if (!registry.containsBeanDefinition(hmiRequestTransformerBeanName)) {
|
|
||||||
BeanDefinition hmiRequestTransformer = BeanDefinitionBuilder
|
|
||||||
.rootBeanDefinition(HandlerMappingIntrospectorRequestTransformer.class)
|
|
||||||
.addConstructorArgReference(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)
|
|
||||||
.getBeanDefinition();
|
|
||||||
registry.registerBeanDefinition(hmiRequestTransformerBeanName, hmiRequestTransformer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BeanDefinition filterChainProxy = registry
|
|
||||||
.getBeanDefinition(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME);
|
|
||||||
|
|
||||||
if (!filterChainProxy.getResolvableType().isInstance(CompositeFilterChainProxy.class)) {
|
|
||||||
BeanDefinitionBuilder hmiCacheFilterBldr = BeanDefinitionBuilder
|
|
||||||
.rootBeanDefinition(HandlerMappingIntrospectorCacheFilterFactoryBean.class)
|
|
||||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
|
||||||
|
|
||||||
ManagedList<BeanMetadataElement> filters = new ManagedList<>();
|
|
||||||
filters.add(hmiCacheFilterBldr.getBeanDefinition());
|
|
||||||
filters.add(filterChainProxy);
|
|
||||||
BeanDefinitionBuilder compositeSpringSecurityFilterChainBldr = BeanDefinitionBuilder
|
|
||||||
.rootBeanDefinition(CompositeFilterChainProxy.class)
|
|
||||||
.addConstructorArgValue(filters);
|
|
||||||
|
|
||||||
registry.removeBeanDefinition(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME);
|
|
||||||
registry.registerBeanDefinition(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME,
|
|
||||||
compositeSpringSecurityFilterChainBldr.getBeanDefinition());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link FactoryBean} to defer creation of
|
|
||||||
* {@link HandlerMappingIntrospector#createCacheFilter()}
|
|
||||||
*
|
|
||||||
* @deprecated see {@link WebSecurityConfiguration} for
|
|
||||||
* {@link org.springframework.web.util.pattern.PathPattern} replacement
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
static class HandlerMappingIntrospectorCacheFilterFactoryBean
|
|
||||||
implements ApplicationContextAware, FactoryBean<Filter> {
|
|
||||||
|
|
||||||
private ApplicationContext applicationContext;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setApplicationContext(ApplicationContext applicationContext) {
|
|
||||||
this.applicationContext = applicationContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Filter getObject() throws Exception {
|
|
||||||
HandlerMappingIntrospector handlerMappingIntrospector = this.applicationContext
|
|
||||||
.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, HandlerMappingIntrospector.class);
|
|
||||||
return handlerMappingIntrospector.createCacheFilter();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> getObjectType() {
|
|
||||||
return Filter.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends {@link FilterChainProxy} to provide as much passivity as possible but
|
* Extends {@link FilterChainProxy} to provide as much passivity as possible but
|
||||||
* delegates to {@link CompositeFilter} for
|
* delegates to {@link CompositeFilter} for
|
||||||
|
@ -42,6 +42,7 @@ import org.springframework.beans.factory.support.ManagedList;
|
|||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.DependsOn;
|
import org.springframework.context.annotation.DependsOn;
|
||||||
|
import org.springframework.context.annotation.Fallback;
|
||||||
import org.springframework.context.annotation.ImportAware;
|
import org.springframework.context.annotation.ImportAware;
|
||||||
import org.springframework.core.OrderComparator;
|
import org.springframework.core.OrderComparator;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
@ -57,6 +58,7 @@ import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
|
|||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||||
import org.springframework.security.config.crypto.RsaKeyConversionServicePostProcessor;
|
import org.springframework.security.config.crypto.RsaKeyConversionServicePostProcessor;
|
||||||
|
import org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean;
|
||||||
import org.springframework.security.context.DelegatingApplicationListener;
|
import org.springframework.security.context.DelegatingApplicationListener;
|
||||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||||
import org.springframework.security.web.FilterChainProxy;
|
import org.springframework.security.web.FilterChainProxy;
|
||||||
@ -69,7 +71,6 @@ import org.springframework.security.web.firewall.HttpFirewall;
|
|||||||
import org.springframework.security.web.firewall.RequestRejectedHandler;
|
import org.springframework.security.web.firewall.RequestRejectedHandler;
|
||||||
import org.springframework.web.filter.CompositeFilter;
|
import org.springframework.web.filter.CompositeFilter;
|
||||||
import org.springframework.web.filter.ServletRequestPathFilter;
|
import org.springframework.web.filter.ServletRequestPathFilter;
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses a {@link WebSecurity} to create the {@link FilterChainProxy} that performs the web
|
* Uses a {@link WebSecurity} to create the {@link FilterChainProxy} that performs the web
|
||||||
@ -143,6 +144,12 @@ public class WebSecurityConfiguration implements ImportAware {
|
|||||||
return this.webSecurity.getPrivilegeEvaluator();
|
return this.webSecurity.getPrivilegeEvaluator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Fallback
|
||||||
|
public PathPatternRequestMatcherBuilderFactoryBean pathPatternRequestMatcherBuilder() {
|
||||||
|
return new PathPatternRequestMatcherBuilderFactoryBean();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the {@code <SecurityConfigurer<FilterChainProxy, WebSecurityBuilder>}
|
* Sets the {@code <SecurityConfigurer<FilterChainProxy, WebSecurityBuilder>}
|
||||||
* instances used to create the web configuration.
|
* instances used to create the web configuration.
|
||||||
@ -209,12 +216,11 @@ public class WebSecurityConfiguration implements ImportAware {
|
|||||||
/**
|
/**
|
||||||
* Used to ensure Spring MVC request matching is cached.
|
* Used to ensure Spring MVC request matching is cached.
|
||||||
*
|
*
|
||||||
* Creates a {@link BeanDefinitionRegistryPostProcessor} that detects if a bean named
|
* Creates a {@link BeanDefinitionRegistryPostProcessor} that moves the
|
||||||
* HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME is defined. If so, it moves the
|
|
||||||
* AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME to another bean name
|
* AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME to another bean name
|
||||||
* and then adds a {@link CompositeFilter} that contains
|
* and then adds a {@link CompositeFilter} that contains
|
||||||
* {@link HandlerMappingIntrospector#createCacheFilter()} and the original
|
* {@link ServletRequestPathFilter} and the original FilterChainProxy under the
|
||||||
* FilterChainProxy under the original Bean name.
|
* original Bean name.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
|
@ -25,6 +25,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
|||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||||
import org.springframework.security.web.DefaultSecurityFilterChain;
|
import org.springframework.security.web.DefaultSecurityFilterChain;
|
||||||
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a convenient base class for {@link SecurityConfigurer} instances that operate on
|
* Adds a convenient base class for {@link SecurityConfigurer} instances that operate on
|
||||||
@ -38,6 +39,8 @@ public abstract class AbstractHttpConfigurer<T extends AbstractHttpConfigurer<T,
|
|||||||
|
|
||||||
private SecurityContextHolderStrategy securityContextHolderStrategy;
|
private SecurityContextHolderStrategy securityContextHolderStrategy;
|
||||||
|
|
||||||
|
private PathPatternRequestMatcher.Builder requestMatcherBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disables the {@link AbstractHttpConfigurer} by removing it. After doing so a fresh
|
* Disables the {@link AbstractHttpConfigurer} by removing it. After doing so a fresh
|
||||||
* version of the configuration can be applied.
|
* version of the configuration can be applied.
|
||||||
@ -65,4 +68,13 @@ public abstract class AbstractHttpConfigurer<T extends AbstractHttpConfigurer<T,
|
|||||||
return this.securityContextHolderStrategy;
|
return this.securityContextHolderStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected PathPatternRequestMatcher.Builder getRequestMatcherBuilder() {
|
||||||
|
if (this.requestMatcherBuilder != null) {
|
||||||
|
return this.requestMatcherBuilder;
|
||||||
|
}
|
||||||
|
ApplicationContext context = getBuilder().getSharedObject(ApplicationContext.class);
|
||||||
|
this.requestMatcherBuilder = context.getBean(PathPatternRequestMatcher.Builder.class);
|
||||||
|
return this.requestMatcherBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,18 +22,14 @@ import org.springframework.security.config.Customizer;
|
|||||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
import org.springframework.web.cors.CorsConfiguration;
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
import org.springframework.web.cors.CorsConfigurationSource;
|
import org.springframework.web.cors.CorsConfigurationSource;
|
||||||
import org.springframework.web.filter.CorsFilter;
|
import org.springframework.web.filter.CorsFilter;
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds {@link CorsFilter} to the Spring Security filter chain. If a bean by the name of
|
* Adds {@link CorsFilter} to the Spring Security filter chain. If a bean by the name of
|
||||||
* corsFilter is provided, that {@link CorsFilter} is used. Else if
|
* corsFilter is provided, that {@link CorsFilter} is used. Else if
|
||||||
* corsConfigurationSource is defined, then that {@link CorsConfiguration} is used.
|
* corsConfigurationSource is defined, then that {@link CorsConfiguration} is used.
|
||||||
* Otherwise, if Spring MVC is on the classpath a {@link HandlerMappingIntrospector} is
|
|
||||||
* used.
|
|
||||||
*
|
*
|
||||||
* @param <H> the builder to return.
|
* @param <H> the builder to return.
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
@ -45,16 +41,8 @@ public class CorsConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractHt
|
|||||||
|
|
||||||
private static final String CORS_FILTER_BEAN_NAME = "corsFilter";
|
private static final String CORS_FILTER_BEAN_NAME = "corsFilter";
|
||||||
|
|
||||||
private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector";
|
|
||||||
|
|
||||||
private static final boolean mvcPresent;
|
|
||||||
|
|
||||||
private CorsConfigurationSource configurationSource;
|
private CorsConfigurationSource configurationSource;
|
||||||
|
|
||||||
static {
|
|
||||||
mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, CorsConfigurer.class.getClassLoader());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
*
|
*
|
||||||
@ -91,10 +79,7 @@ public class CorsConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractHt
|
|||||||
CorsConfigurationSource.class);
|
CorsConfigurationSource.class);
|
||||||
return new CorsFilter(configurationSource);
|
return new CorsFilter(configurationSource);
|
||||||
}
|
}
|
||||||
if (mvcPresent) {
|
return MvcCorsFilter.getMvcCorsFilter(context);
|
||||||
return MvcCorsFilter.getMvcCorsFilter(context);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class MvcCorsFilter {
|
static class MvcCorsFilter {
|
||||||
|
@ -19,7 +19,6 @@ package org.springframework.security.config.annotation.web.configurers;
|
|||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.security.config.Customizer;
|
import org.springframework.security.config.Customizer;
|
||||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||||
import org.springframework.security.config.annotation.web.RequestMatcherFactory;
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
@ -236,7 +235,7 @@ public final class FormLoginConfigurer<H extends HttpSecurityBuilder<H>> extends
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {
|
protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {
|
||||||
return RequestMatcherFactory.matcher(HttpMethod.POST, loginProcessingUrl);
|
return getRequestMatcherBuilder().matcher(HttpMethod.POST, loginProcessingUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,7 +26,6 @@ import org.springframework.http.HttpMethod;
|
|||||||
import org.springframework.security.config.Customizer;
|
import org.springframework.security.config.Customizer;
|
||||||
import org.springframework.security.config.annotation.SecurityConfigurer;
|
import org.springframework.security.config.annotation.SecurityConfigurer;
|
||||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||||
import org.springframework.security.config.annotation.web.RequestMatcherFactory;
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler;
|
import org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler;
|
||||||
@ -146,7 +145,7 @@ public final class LogoutConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
* (i.e. log out) to protect against
|
* (i.e. log out) to protect against
|
||||||
* <a href="https://en.wikipedia.org/wiki/Cross-site_request_forgery">CSRF
|
* <a href="https://en.wikipedia.org/wiki/Cross-site_request_forgery">CSRF
|
||||||
* attacks</a>. If you really want to use an HTTP GET, you can use
|
* attacks</a>. If you really want to use an HTTP GET, you can use
|
||||||
* <code>logoutRequestMatcher(PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.GEt, logoutUrl));</code>
|
* <code>logoutRequestMatcher(PathPatternRequestMatcher.pathPattern(HttpMethod.GEt, logoutUrl));</code>
|
||||||
* </p>
|
* </p>
|
||||||
* @param logoutUrl the URL that will invoke logout.
|
* @param logoutUrl the URL that will invoke logout.
|
||||||
* @return the {@link LogoutConfigurer} for further customization
|
* @return the {@link LogoutConfigurer} for further customization
|
||||||
@ -370,7 +369,7 @@ public final class LogoutConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
}
|
}
|
||||||
|
|
||||||
private RequestMatcher createLogoutRequestMatcher(String httpMethod) {
|
private RequestMatcher createLogoutRequestMatcher(String httpMethod) {
|
||||||
return RequestMatcherFactory.matcher(HttpMethod.valueOf(httpMethod), this.logoutUrl);
|
return getRequestMatcherBuilder().matcher(HttpMethod.valueOf(httpMethod), this.logoutUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
package org.springframework.security.config.annotation.web.configurers;
|
package org.springframework.security.config.annotation.web.configurers;
|
||||||
|
|
||||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||||
import org.springframework.security.config.annotation.web.RequestMatcherFactory;
|
|
||||||
import org.springframework.security.web.RequestMatcherRedirectFilter;
|
import org.springframework.security.web.RequestMatcherRedirectFilter;
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
@ -55,7 +54,7 @@ public final class PasswordManagementConfigurer<B extends HttpSecurityBuilder<B>
|
|||||||
@Override
|
@Override
|
||||||
public void configure(B http) throws Exception {
|
public void configure(B http) throws Exception {
|
||||||
RequestMatcherRedirectFilter changePasswordFilter = new RequestMatcherRedirectFilter(
|
RequestMatcherRedirectFilter changePasswordFilter = new RequestMatcherRedirectFilter(
|
||||||
RequestMatcherFactory.matcher(WELL_KNOWN_CHANGE_PASSWORD_PATTERN), this.changePasswordPage);
|
getRequestMatcherBuilder().matcher(WELL_KNOWN_CHANGE_PASSWORD_PATTERN), this.changePasswordPage);
|
||||||
http.addFilterBefore(postProcess(changePasswordFilter), UsernamePasswordAuthenticationFilter.class);
|
http.addFilterBefore(postProcess(changePasswordFilter), UsernamePasswordAuthenticationFilter.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,14 +24,12 @@ import org.springframework.context.ApplicationContext;
|
|||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||||
import org.springframework.security.config.annotation.web.RequestMatcherFactory;
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
|
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
|
||||||
import org.springframework.security.web.savedrequest.NullRequestCache;
|
import org.springframework.security.web.savedrequest.NullRequestCache;
|
||||||
import org.springframework.security.web.savedrequest.RequestCache;
|
import org.springframework.security.web.savedrequest.RequestCache;
|
||||||
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
|
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
|
||||||
import org.springframework.security.web.util.matcher.AndRequestMatcher;
|
import org.springframework.security.web.util.matcher.AndRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
|
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
|
import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;
|
||||||
@ -151,7 +149,7 @@ public final class RequestCacheConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
boolean isCsrfEnabled = http.getConfigurer(CsrfConfigurer.class) != null;
|
boolean isCsrfEnabled = http.getConfigurer(CsrfConfigurer.class) != null;
|
||||||
List<RequestMatcher> matchers = new ArrayList<>();
|
List<RequestMatcher> matchers = new ArrayList<>();
|
||||||
if (isCsrfEnabled) {
|
if (isCsrfEnabled) {
|
||||||
RequestMatcher getRequests = RequestMatcherFactory.matcher(HttpMethod.GET, "/**");
|
RequestMatcher getRequests = getRequestMatcherBuilder().matcher(HttpMethod.GET, "/**");
|
||||||
matchers.add(0, getRequests);
|
matchers.add(0, getRequests);
|
||||||
}
|
}
|
||||||
matchers.add(notFavIcon);
|
matchers.add(notFavIcon);
|
||||||
@ -174,12 +172,7 @@ public final class RequestCacheConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
}
|
}
|
||||||
|
|
||||||
private RequestMatcher getFaviconRequestMatcher() {
|
private RequestMatcher getFaviconRequestMatcher() {
|
||||||
if (RequestMatcherFactory.usesPathPatterns()) {
|
return getRequestMatcherBuilder().matcher("/favicon.*");
|
||||||
return RequestMatcherFactory.matcher("/favicon.*");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return new AntPathRequestMatcher("/**/favicon.*");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,6 @@ import org.springframework.security.authentication.ott.OneTimeTokenAuthenticatio
|
|||||||
import org.springframework.security.authentication.ott.OneTimeTokenService;
|
import org.springframework.security.authentication.ott.OneTimeTokenService;
|
||||||
import org.springframework.security.config.Customizer;
|
import org.springframework.security.config.Customizer;
|
||||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||||
import org.springframework.security.config.annotation.web.RequestMatcherFactory;
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
|
import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
|
||||||
@ -122,12 +121,15 @@ public final class OneTimeTokenLoginConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
private GenerateOneTimeTokenRequestResolver requestResolver;
|
private GenerateOneTimeTokenRequestResolver requestResolver;
|
||||||
|
|
||||||
public OneTimeTokenLoginConfigurer(ApplicationContext context) {
|
public OneTimeTokenLoginConfigurer(ApplicationContext context) {
|
||||||
super(new OneTimeTokenAuthenticationFilter(), OneTimeTokenAuthenticationFilter.DEFAULT_LOGIN_PROCESSING_URL);
|
super(new OneTimeTokenAuthenticationFilter(), null);
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(H http) throws Exception {
|
public void init(H http) throws Exception {
|
||||||
|
if (getLoginProcessingUrl() == null) {
|
||||||
|
loginProcessingUrl(OneTimeTokenAuthenticationFilter.DEFAULT_LOGIN_PROCESSING_URL);
|
||||||
|
}
|
||||||
super.init(http);
|
super.init(http);
|
||||||
AuthenticationProvider authenticationProvider = getAuthenticationProvider();
|
AuthenticationProvider authenticationProvider = getAuthenticationProvider();
|
||||||
http.authenticationProvider(postProcess(authenticationProvider));
|
http.authenticationProvider(postProcess(authenticationProvider));
|
||||||
@ -162,7 +164,7 @@ public final class OneTimeTokenLoginConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
private void configureOttGenerateFilter(H http) {
|
private void configureOttGenerateFilter(H http) {
|
||||||
GenerateOneTimeTokenFilter generateFilter = new GenerateOneTimeTokenFilter(getOneTimeTokenService(),
|
GenerateOneTimeTokenFilter generateFilter = new GenerateOneTimeTokenFilter(getOneTimeTokenService(),
|
||||||
getOneTimeTokenGenerationSuccessHandler());
|
getOneTimeTokenGenerationSuccessHandler());
|
||||||
generateFilter.setRequestMatcher(RequestMatcherFactory.matcher(HttpMethod.POST, this.tokenGeneratingUrl));
|
generateFilter.setRequestMatcher(getRequestMatcherBuilder().matcher(HttpMethod.POST, this.tokenGeneratingUrl));
|
||||||
generateFilter.setRequestResolver(getGenerateRequestResolver());
|
generateFilter.setRequestResolver(getGenerateRequestResolver());
|
||||||
http.addFilter(postProcess(generateFilter));
|
http.addFilter(postProcess(generateFilter));
|
||||||
http.addFilter(DefaultResourcesFilter.css());
|
http.addFilter(DefaultResourcesFilter.css());
|
||||||
@ -189,7 +191,7 @@ public final class OneTimeTokenLoginConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
}
|
}
|
||||||
DefaultOneTimeTokenSubmitPageGeneratingFilter submitPage = new DefaultOneTimeTokenSubmitPageGeneratingFilter();
|
DefaultOneTimeTokenSubmitPageGeneratingFilter submitPage = new DefaultOneTimeTokenSubmitPageGeneratingFilter();
|
||||||
submitPage.setResolveHiddenInputs(this::hiddenInputs);
|
submitPage.setResolveHiddenInputs(this::hiddenInputs);
|
||||||
submitPage.setRequestMatcher(RequestMatcherFactory.matcher(HttpMethod.GET, this.defaultSubmitPageUrl));
|
submitPage.setRequestMatcher(getRequestMatcherBuilder().matcher(HttpMethod.GET, this.defaultSubmitPageUrl));
|
||||||
submitPage.setLoginProcessingUrl(this.getLoginProcessingUrl());
|
submitPage.setLoginProcessingUrl(this.getLoginProcessingUrl());
|
||||||
http.addFilter(postProcess(submitPage));
|
http.addFilter(postProcess(submitPage));
|
||||||
}
|
}
|
||||||
@ -206,7 +208,7 @@ public final class OneTimeTokenLoginConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {
|
protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {
|
||||||
return RequestMatcherFactory.matcher(HttpMethod.POST, loginProcessingUrl);
|
return getRequestMatcherBuilder().matcher(HttpMethod.POST, loginProcessingUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,10 +35,6 @@ class WebMvcSecurityConfigurationRuntimeHints implements RuntimeHintsRegistrar {
|
|||||||
.registerType(TypeReference
|
.registerType(TypeReference
|
||||||
.of("org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$CompositeFilterChainProxy"),
|
.of("org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$CompositeFilterChainProxy"),
|
||||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
|
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
|
||||||
hints.reflection()
|
|
||||||
.registerType(TypeReference
|
|
||||||
.of("org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$HandlerMappingIntrospectorCacheFilterFactoryBean"),
|
|
||||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,7 @@ class AuthorizationFilterParser implements BeanDefinitionParser {
|
|||||||
if (!StringUtils.hasText(servletPath)) {
|
if (!StringUtils.hasText(servletPath)) {
|
||||||
servletPath = null;
|
servletPath = null;
|
||||||
}
|
}
|
||||||
else if (!MatcherType.mvc.equals(matcherType)) {
|
else if (!MatcherType.path.equals(matcherType)) {
|
||||||
parserContext.getReaderContext()
|
parserContext.getReaderContext()
|
||||||
.error(ATT_SERVLET_PATH + " is not applicable for request-matcher: '" + matcherType.name() + "'",
|
.error(ATT_SERVLET_PATH + " is not applicable for request-matcher: '" + matcherType.name() + "'",
|
||||||
urlElt);
|
urlElt);
|
||||||
|
@ -24,7 +24,6 @@ import org.springframework.beans.factory.config.RuntimeBeanReference;
|
|||||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||||
import org.springframework.beans.factory.xml.ParserContext;
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.filter.CorsFilter;
|
import org.springframework.web.filter.CorsFilter;
|
||||||
|
|
||||||
@ -40,15 +39,6 @@ public class CorsBeanDefinitionParser {
|
|||||||
|
|
||||||
private static final String ATT_REF = "ref";
|
private static final String ATT_REF = "ref";
|
||||||
|
|
||||||
private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector";
|
|
||||||
|
|
||||||
private static final boolean mvcPresent;
|
|
||||||
|
|
||||||
static {
|
|
||||||
mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR,
|
|
||||||
CorsBeanDefinitionParser.class.getClassLoader());
|
|
||||||
}
|
|
||||||
|
|
||||||
public BeanMetadataElement parse(Element element, ParserContext parserContext) {
|
public BeanMetadataElement parse(Element element, ParserContext parserContext) {
|
||||||
if (element == null) {
|
if (element == null) {
|
||||||
return null;
|
return null;
|
||||||
@ -71,10 +61,7 @@ public class CorsBeanDefinitionParser {
|
|||||||
if (StringUtils.hasText(configurationSourceRef)) {
|
if (StringUtils.hasText(configurationSourceRef)) {
|
||||||
return new RuntimeBeanReference(configurationSourceRef);
|
return new RuntimeBeanReference(configurationSourceRef);
|
||||||
}
|
}
|
||||||
if (!mvcPresent) {
|
return new RootBeanDefinition(CorsConfigurationSourceFactoryBean.class);
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new RootBeanDefinition(HandlerMappingIntrospectorFactoryBean.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,38 +22,37 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
|||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationContextAware;
|
import org.springframework.context.ApplicationContextAware;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
import org.springframework.web.cors.CorsConfigurationSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for creating an instance of {@link HandlerMappingIntrospector} and autowiring the
|
* Used for creating an instance of {@link CorsConfigurationSource} and autowiring the
|
||||||
* {@link ApplicationContext}.
|
* {@link ApplicationContext}.
|
||||||
*
|
*
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
* @since 4.1.1
|
* @since 4.1.1
|
||||||
*/
|
*/
|
||||||
class HandlerMappingIntrospectorFactoryBean
|
class CorsConfigurationSourceFactoryBean implements FactoryBean<CorsConfigurationSource>, ApplicationContextAware {
|
||||||
implements FactoryBean<HandlerMappingIntrospector>, ApplicationContextAware {
|
|
||||||
|
|
||||||
private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector";
|
private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector";
|
||||||
|
|
||||||
private ApplicationContext context;
|
private ApplicationContext context;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HandlerMappingIntrospector getObject() {
|
public CorsConfigurationSource getObject() {
|
||||||
if (!this.context.containsBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) {
|
if (!this.context.containsBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) {
|
||||||
throw new NoSuchBeanDefinitionException(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME,
|
throw new NoSuchBeanDefinitionException(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME,
|
||||||
"A Bean named " + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME + " of type "
|
"A Bean named " + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME + " of type "
|
||||||
+ HandlerMappingIntrospector.class.getName()
|
+ CorsConfigurationSource.class.getName()
|
||||||
+ " is required to use MvcRequestMatcher. Please ensure Spring Security & Spring "
|
+ " is required to use <cors>. Please ensure Spring Security & Spring "
|
||||||
+ "MVC are configured in a shared ApplicationContext.");
|
+ "MVC are configured in a shared ApplicationContext.");
|
||||||
}
|
}
|
||||||
return this.context.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, HandlerMappingIntrospector.class);
|
return this.context.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, CorsConfigurationSource.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public Class<?> getObjectType() {
|
public Class<?> getObjectType() {
|
||||||
return HandlerMappingIntrospector.class;
|
return CorsConfigurationSource.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -40,7 +40,9 @@ import org.springframework.security.web.FilterChainProxy;
|
|||||||
import org.springframework.security.web.FilterInvocation;
|
import org.springframework.security.web.FilterInvocation;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.UnreachableFilterChainException;
|
import org.springframework.security.web.UnreachableFilterChainException;
|
||||||
|
import org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator;
|
||||||
import org.springframework.security.web.access.ExceptionTranslationFilter;
|
import org.springframework.security.web.access.ExceptionTranslationFilter;
|
||||||
|
import org.springframework.security.web.access.PathPatternRequestTransformer;
|
||||||
import org.springframework.security.web.access.intercept.AuthorizationFilter;
|
import org.springframework.security.web.access.intercept.AuthorizationFilter;
|
||||||
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
|
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
|
||||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
||||||
@ -61,6 +63,8 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
|
|||||||
|
|
||||||
private final Log logger = LogFactory.getLog(getClass());
|
private final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
|
private final AuthorizationManagerWebInvocationPrivilegeEvaluator.HttpServletRequestTransformer requestTransformer = new PathPatternRequestTransformer();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void validate(FilterChainProxy fcp) {
|
public void validate(FilterChainProxy fcp) {
|
||||||
for (SecurityFilterChain filterChain : fcp.getFilterChains()) {
|
for (SecurityFilterChain filterChain : fcp.getFilterChains()) {
|
||||||
@ -188,7 +192,8 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
|
|||||||
String loginPage = ((LoginUrlAuthenticationEntryPoint) exceptions.getAuthenticationEntryPoint())
|
String loginPage = ((LoginUrlAuthenticationEntryPoint) exceptions.getAuthenticationEntryPoint())
|
||||||
.getLoginFormUrl();
|
.getLoginFormUrl();
|
||||||
this.logger.info("Checking whether login URL '" + loginPage + "' is accessible with your configuration");
|
this.logger.info("Checking whether login URL '" + loginPage + "' is accessible with your configuration");
|
||||||
FilterInvocation loginRequest = new FilterInvocation(loginPage, "POST");
|
FilterInvocation invocation = new FilterInvocation(loginPage, "POST");
|
||||||
|
HttpServletRequest loginRequest = this.requestTransformer.transform(invocation.getRequest());
|
||||||
List<Filter> filters = null;
|
List<Filter> filters = null;
|
||||||
try {
|
try {
|
||||||
filters = fcp.getFilters(loginPage);
|
filters = fcp.getFilters(loginPage);
|
||||||
@ -237,7 +242,7 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkLoginPageIsPublic(List<Filter> filters, FilterInvocation loginRequest) {
|
private boolean checkLoginPageIsPublic(List<Filter> filters, HttpServletRequest loginRequest) {
|
||||||
FilterSecurityInterceptor authorizationInterceptor = getFilter(FilterSecurityInterceptor.class, filters);
|
FilterSecurityInterceptor authorizationInterceptor = getFilter(FilterSecurityInterceptor.class, filters);
|
||||||
if (authorizationInterceptor != null) {
|
if (authorizationInterceptor != null) {
|
||||||
FilterInvocationSecurityMetadataSource fids = authorizationInterceptor.getSecurityMetadataSource();
|
FilterInvocationSecurityMetadataSource fids = authorizationInterceptor.getSecurityMetadataSource();
|
||||||
@ -257,7 +262,7 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
|
|||||||
AuthorizationManager<HttpServletRequest> authorizationManager = authorizationFilter
|
AuthorizationManager<HttpServletRequest> authorizationManager = authorizationFilter
|
||||||
.getAuthorizationManager();
|
.getAuthorizationManager();
|
||||||
try {
|
try {
|
||||||
AuthorizationResult result = authorizationManager.authorize(() -> TEST, loginRequest.getHttpRequest());
|
AuthorizationResult result = authorizationManager.authorize(() -> TEST, loginRequest);
|
||||||
return result != null && result.isGranted();
|
return result != null && result.isGranted();
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
@ -267,7 +272,7 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Supplier<Boolean> deriveAnonymousCheck(List<Filter> filters, FilterInvocation loginRequest,
|
private Supplier<Boolean> deriveAnonymousCheck(List<Filter> filters, HttpServletRequest loginRequest,
|
||||||
AnonymousAuthenticationToken token) {
|
AnonymousAuthenticationToken token) {
|
||||||
FilterSecurityInterceptor authorizationInterceptor = getFilter(FilterSecurityInterceptor.class, filters);
|
FilterSecurityInterceptor authorizationInterceptor = getFilter(FilterSecurityInterceptor.class, filters);
|
||||||
if (authorizationInterceptor != null) {
|
if (authorizationInterceptor != null) {
|
||||||
@ -288,7 +293,7 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
|
|||||||
return () -> {
|
return () -> {
|
||||||
AuthorizationManager<HttpServletRequest> authorizationManager = authorizationFilter
|
AuthorizationManager<HttpServletRequest> authorizationManager = authorizationFilter
|
||||||
.getAuthorizationManager();
|
.getAuthorizationManager();
|
||||||
AuthorizationResult result = authorizationManager.authorize(() -> token, loginRequest.getHttpRequest());
|
AuthorizationResult result = authorizationManager.authorize(() -> token, loginRequest);
|
||||||
return result != null && result.isGranted();
|
return result != null && result.isGranted();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,7 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
|
|||||||
if (!StringUtils.hasText(servletPath)) {
|
if (!StringUtils.hasText(servletPath)) {
|
||||||
servletPath = null;
|
servletPath = null;
|
||||||
}
|
}
|
||||||
else if (!MatcherType.mvc.equals(matcherType)) {
|
else if (!MatcherType.path.equals(matcherType)) {
|
||||||
parserContext.getReaderContext()
|
parserContext.getReaderContext()
|
||||||
.error(ATT_SERVLET_PATH + " is not applicable for request-matcher: '" + matcherType.name() + "'",
|
.error(ATT_SERVLET_PATH + " is not applicable for request-matcher: '" + matcherType.name() + "'",
|
||||||
urlElt);
|
urlElt);
|
||||||
|
@ -45,12 +45,12 @@ import org.springframework.security.access.vote.AuthenticatedVoter;
|
|||||||
import org.springframework.security.access.vote.RoleVoter;
|
import org.springframework.security.access.vote.RoleVoter;
|
||||||
import org.springframework.security.config.Elements;
|
import org.springframework.security.config.Elements;
|
||||||
import org.springframework.security.config.http.GrantedAuthorityDefaultsParserUtils.AbstractGrantedAuthorityDefaultsBeanFactory;
|
import org.springframework.security.config.http.GrantedAuthorityDefaultsParserUtils.AbstractGrantedAuthorityDefaultsBeanFactory;
|
||||||
|
import org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||||
import org.springframework.security.core.session.SessionRegistryImpl;
|
import org.springframework.security.core.session.SessionRegistryImpl;
|
||||||
import org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator;
|
import org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator;
|
||||||
import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator;
|
import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator;
|
||||||
import org.springframework.security.web.access.HandlerMappingIntrospectorRequestTransformer;
|
|
||||||
import org.springframework.security.web.access.PathPatternRequestTransformer;
|
import org.springframework.security.web.access.PathPatternRequestTransformer;
|
||||||
import org.springframework.security.web.access.channel.ChannelDecisionManagerImpl;
|
import org.springframework.security.web.access.channel.ChannelDecisionManagerImpl;
|
||||||
import org.springframework.security.web.access.channel.ChannelProcessingFilter;
|
import org.springframework.security.web.access.channel.ChannelProcessingFilter;
|
||||||
@ -88,7 +88,6 @@ import org.springframework.util.Assert;
|
|||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.util.xml.DomUtils;
|
import org.springframework.util.xml.DomUtils;
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stateful class which helps HttpSecurityBDP to create the configuration for the
|
* Stateful class which helps HttpSecurityBDP to create the configuration for the
|
||||||
@ -100,11 +99,6 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|||||||
*/
|
*/
|
||||||
class HttpConfigurationBuilder {
|
class HttpConfigurationBuilder {
|
||||||
|
|
||||||
private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector";
|
|
||||||
|
|
||||||
private static final boolean mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR,
|
|
||||||
HttpConfigurationBuilder.class.getClassLoader());
|
|
||||||
|
|
||||||
private static final String ATT_CREATE_SESSION = "create-session";
|
private static final String ATT_CREATE_SESSION = "create-session";
|
||||||
|
|
||||||
private static final String ATT_SESSION_FIXATION_PROTECTION = "session-fixation-protection";
|
private static final String ATT_SESSION_FIXATION_PROTECTION = "session-fixation-protection";
|
||||||
@ -165,6 +159,8 @@ class HttpConfigurationBuilder {
|
|||||||
|
|
||||||
private static final String DEF_JAAS_API_PROVISION = "false";
|
private static final String DEF_JAAS_API_PROVISION = "false";
|
||||||
|
|
||||||
|
private static final String REQUEST_MATCHER_BUILDER_BEAN_NAME = "HttpConfigurationBuilder-pathPatternRequestMatcherBuilder";
|
||||||
|
|
||||||
private final Element httpElt;
|
private final Element httpElt;
|
||||||
|
|
||||||
private final ParserContext pc;
|
private final ParserContext pc;
|
||||||
@ -244,6 +240,13 @@ class HttpConfigurationBuilder {
|
|||||||
String createSession = element.getAttribute(ATT_CREATE_SESSION);
|
String createSession = element.getAttribute(ATT_CREATE_SESSION);
|
||||||
this.sessionPolicy = !StringUtils.hasText(createSession) ? SessionCreationPolicy.IF_REQUIRED
|
this.sessionPolicy = !StringUtils.hasText(createSession) ? SessionCreationPolicy.IF_REQUIRED
|
||||||
: createPolicy(createSession);
|
: createPolicy(createSession);
|
||||||
|
if (!this.pc.getRegistry().containsBeanDefinition(REQUEST_MATCHER_BUILDER_BEAN_NAME)) {
|
||||||
|
BeanDefinitionBuilder pathPatternRequestMatcherBuilder = BeanDefinitionBuilder
|
||||||
|
.rootBeanDefinition(PathPatternRequestMatcherBuilderFactoryBean.class);
|
||||||
|
pathPatternRequestMatcherBuilder.setFallback(true);
|
||||||
|
BeanDefinition bean = pathPatternRequestMatcherBuilder.getBeanDefinition();
|
||||||
|
this.pc.registerBeanComponent(new BeanComponentDefinition(bean, REQUEST_MATCHER_BUILDER_BEAN_NAME));
|
||||||
|
}
|
||||||
createSecurityContextHolderStrategy();
|
createSecurityContextHolderStrategy();
|
||||||
createForceEagerSessionCreationFilter();
|
createForceEagerSessionCreationFilter();
|
||||||
createDisableEncodeUrlFilter();
|
createDisableEncodeUrlFilter();
|
||||||
@ -793,10 +796,8 @@ class HttpConfigurationBuilder {
|
|||||||
BeanDefinitionBuilder wipeBldr = BeanDefinitionBuilder
|
BeanDefinitionBuilder wipeBldr = BeanDefinitionBuilder
|
||||||
.rootBeanDefinition(AuthorizationManagerWebInvocationPrivilegeEvaluator.class)
|
.rootBeanDefinition(AuthorizationManagerWebInvocationPrivilegeEvaluator.class)
|
||||||
.addConstructorArgReference(authorizationFilterParser.getAuthorizationManagerRef());
|
.addConstructorArgReference(authorizationFilterParser.getAuthorizationManagerRef());
|
||||||
if (mvcPresent) {
|
wipeBldr.addPropertyValue("requestTransformer",
|
||||||
wipeBldr.addPropertyValue("requestTransformer",
|
new RootBeanDefinition(PathPatternRequestTransformerFactoryBean.class));
|
||||||
new RootBeanDefinition(HandlerMappingIntrospectorRequestTransformerFactoryBean.class));
|
|
||||||
}
|
|
||||||
BeanDefinition wipe = wipeBldr.getBeanDefinition();
|
BeanDefinition wipe = wipeBldr.getBeanDefinition();
|
||||||
this.pc.registerBeanComponent(
|
this.pc.registerBeanComponent(
|
||||||
new BeanComponentDefinition(wipe, this.pc.getReaderContext().generateBeanName(wipe)));
|
new BeanComponentDefinition(wipe, this.pc.getReaderContext().generateBeanName(wipe)));
|
||||||
@ -966,7 +967,7 @@ class HttpConfigurationBuilder {
|
|||||||
return BeanDefinitionBuilder.rootBeanDefinition(ObservationRegistryFactory.class).getBeanDefinition();
|
return BeanDefinitionBuilder.rootBeanDefinition(ObservationRegistryFactory.class).getBeanDefinition();
|
||||||
}
|
}
|
||||||
|
|
||||||
static class HandlerMappingIntrospectorRequestTransformerFactoryBean
|
static class PathPatternRequestTransformerFactoryBean
|
||||||
implements FactoryBean<AuthorizationManagerWebInvocationPrivilegeEvaluator.HttpServletRequestTransformer>,
|
implements FactoryBean<AuthorizationManagerWebInvocationPrivilegeEvaluator.HttpServletRequestTransformer>,
|
||||||
ApplicationContextAware {
|
ApplicationContextAware {
|
||||||
|
|
||||||
@ -982,10 +983,7 @@ class HttpConfigurationBuilder {
|
|||||||
if (requestTransformer != null) {
|
if (requestTransformer != null) {
|
||||||
return requestTransformer;
|
return requestTransformer;
|
||||||
}
|
}
|
||||||
HandlerMappingIntrospector hmi = this.applicationContext.getBeanProvider(HandlerMappingIntrospector.class)
|
return new PathPatternRequestTransformer();
|
||||||
.getIfAvailable();
|
|
||||||
return (hmi != null) ? new HandlerMappingIntrospectorRequestTransformer(hmi)
|
|
||||||
: new PathPatternRequestTransformer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -22,13 +22,12 @@ import org.springframework.beans.factory.config.BeanDefinition;
|
|||||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||||
import org.springframework.beans.factory.xml.ParserContext;
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
import org.springframework.http.HttpMethod;
|
|
||||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
||||||
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,21 +38,13 @@ import org.springframework.util.StringUtils;
|
|||||||
*/
|
*/
|
||||||
public enum MatcherType {
|
public enum MatcherType {
|
||||||
|
|
||||||
ant(AntPathRequestMatcher.class), regex(RegexRequestMatcher.class), ciRegex(RegexRequestMatcher.class),
|
ant(AntPathRequestMatcher.class), path(PathPatternRequestMatcher.class), regex(RegexRequestMatcher.class),
|
||||||
mvc(MvcRequestMatcher.class);
|
ciRegex(RegexRequestMatcher.class), mvc(MvcRequestMatcher.class);
|
||||||
|
|
||||||
private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector";
|
|
||||||
|
|
||||||
private static final boolean mvcPresent;
|
|
||||||
|
|
||||||
private static final String ATT_MATCHER_TYPE = "request-matcher";
|
private static final String ATT_MATCHER_TYPE = "request-matcher";
|
||||||
|
|
||||||
final Class<? extends RequestMatcher> type;
|
final Class<? extends RequestMatcher> type;
|
||||||
|
|
||||||
static {
|
|
||||||
mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, MatcherType.class.getClassLoader());
|
|
||||||
}
|
|
||||||
|
|
||||||
MatcherType(Class<? extends RequestMatcher> type) {
|
MatcherType(Class<? extends RequestMatcher> type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
@ -66,18 +57,17 @@ public enum MatcherType {
|
|||||||
if (("/**".equals(path) || "**".equals(path)) && method == null) {
|
if (("/**".equals(path) || "**".equals(path)) && method == null) {
|
||||||
return new RootBeanDefinition(AnyRequestMatcher.class);
|
return new RootBeanDefinition(AnyRequestMatcher.class);
|
||||||
}
|
}
|
||||||
BeanDefinitionBuilder matcherBldr = BeanDefinitionBuilder.rootBeanDefinition(this.type);
|
BeanDefinitionBuilder matcherBldr;
|
||||||
if (this == mvc) {
|
if (this == MatcherType.path) {
|
||||||
matcherBldr.addConstructorArgValue(new RootBeanDefinition(HandlerMappingIntrospectorFactoryBean.class));
|
matcherBldr = BeanDefinitionBuilder.rootBeanDefinition(PathPatternRequestMatcherFactoryBean.class);
|
||||||
}
|
matcherBldr.addConstructorArgValue(path);
|
||||||
matcherBldr.addConstructorArgValue(path);
|
matcherBldr.addPropertyValue("basePath", servletPath);
|
||||||
if (this == mvc) {
|
|
||||||
matcherBldr.addPropertyValue("method", (StringUtils.hasText(method) ? HttpMethod.valueOf(method) : null));
|
|
||||||
matcherBldr.addPropertyValue("servletPath", servletPath);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
matcherBldr.addConstructorArgValue(method);
|
matcherBldr = BeanDefinitionBuilder.rootBeanDefinition(this.type);
|
||||||
|
matcherBldr.addConstructorArgValue(path);
|
||||||
}
|
}
|
||||||
|
matcherBldr.addConstructorArgValue(method);
|
||||||
if (this == ciRegex) {
|
if (this == ciRegex) {
|
||||||
matcherBldr.addConstructorArgValue(true);
|
matcherBldr.addConstructorArgValue(true);
|
||||||
}
|
}
|
||||||
@ -89,14 +79,10 @@ public enum MatcherType {
|
|||||||
return valueOf(elt.getAttribute(ATT_MATCHER_TYPE));
|
return valueOf(elt.getAttribute(ATT_MATCHER_TYPE));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ant;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
static MatcherType fromElementOrMvc(Element elt) {
|
static MatcherType fromElementOrMvc(Element elt) {
|
||||||
String matcherTypeName = elt.getAttribute(ATT_MATCHER_TYPE);
|
|
||||||
if (!StringUtils.hasText(matcherTypeName) && mvcPresent) {
|
|
||||||
return MatcherType.mvc;
|
|
||||||
}
|
|
||||||
return MatcherType.fromElement(elt);
|
return MatcherType.fromElement(elt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2025 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.config.http;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
public final class PathPatternRequestMatcherFactoryBean
|
||||||
|
implements FactoryBean<PathPatternRequestMatcher>, ApplicationContextAware, InitializingBean {
|
||||||
|
|
||||||
|
private final String pattern;
|
||||||
|
|
||||||
|
private String basePath;
|
||||||
|
|
||||||
|
private HttpMethod method;
|
||||||
|
|
||||||
|
private PathPatternRequestMatcher.Builder builder;
|
||||||
|
|
||||||
|
PathPatternRequestMatcherFactoryBean(String pattern) {
|
||||||
|
this.pattern = pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
PathPatternRequestMatcherFactoryBean(String pattern, String method) {
|
||||||
|
this.pattern = pattern;
|
||||||
|
this.method = StringUtils.hasText(method) ? HttpMethod.valueOf(method) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable PathPatternRequestMatcher getObject() throws Exception {
|
||||||
|
return this.builder.matcher(this.method, this.pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable Class<?> getObjectType() {
|
||||||
|
return PathPatternRequestMatcher.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBasePath(String basePath) {
|
||||||
|
this.basePath = basePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
||||||
|
this.builder = context.getBeanProvider(PathPatternRequestMatcher.Builder.class)
|
||||||
|
.getIfUnique(PathPatternRequestMatcher::withDefaults);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
if (this.basePath != null) {
|
||||||
|
this.builder.basePath(this.basePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -22,7 +22,6 @@ import org.springframework.context.ApplicationContext;
|
|||||||
import org.springframework.context.ApplicationContextAware;
|
import org.springframework.context.ApplicationContextAware;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@ -45,10 +44,7 @@ public final class RequestMatcherFactoryBean implements FactoryBean<RequestMatch
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RequestMatcher getObject() throws Exception {
|
public RequestMatcher getObject() throws Exception {
|
||||||
if (this.builder != null) {
|
return this.builder.matcher(this.method, this.path);
|
||||||
return this.builder.matcher(this.method, this.path);
|
|
||||||
}
|
|
||||||
return new AntPathRequestMatcher(this.path, (this.method != null) ? this.method.name() : null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -58,7 +54,7 @@ public final class RequestMatcherFactoryBean implements FactoryBean<RequestMatch
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
||||||
this.builder = context.getBeanProvider(PathPatternRequestMatcher.Builder.class).getIfUnique();
|
this.builder = context.getBean(PathPatternRequestMatcher.Builder.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,6 @@ abstract class AbstractRequestMatcherDsl {
|
|||||||
protected abstract class AuthorizationManagerRule(open val rule: AuthorizationManager<RequestAuthorizationContext>)
|
protected abstract class AuthorizationManagerRule(open val rule: AuthorizationManager<RequestAuthorizationContext>)
|
||||||
|
|
||||||
protected enum class PatternType {
|
protected enum class PatternType {
|
||||||
ANT, MVC
|
ANT, MVC, PATH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,11 +31,9 @@ import org.springframework.security.core.Authentication
|
|||||||
import org.springframework.security.web.access.IpAddressAuthorizationManager
|
import org.springframework.security.web.access.IpAddressAuthorizationManager
|
||||||
import org.springframework.security.web.access.intercept.AuthorizationFilter
|
import org.springframework.security.web.access.intercept.AuthorizationFilter
|
||||||
import org.springframework.security.web.access.intercept.RequestAuthorizationContext
|
import org.springframework.security.web.access.intercept.RequestAuthorizationContext
|
||||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher
|
||||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher
|
import org.springframework.security.web.util.matcher.AnyRequestMatcher
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher
|
import org.springframework.security.web.util.matcher.RequestMatcher
|
||||||
import org.springframework.util.ClassUtils
|
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector
|
|
||||||
import java.util.function.Supplier
|
import java.util.function.Supplier
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -69,12 +67,7 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl {
|
|||||||
private val rolePrefix: String
|
private val rolePrefix: String
|
||||||
private val roleHierarchy: RoleHierarchy
|
private val roleHierarchy: RoleHierarchy
|
||||||
|
|
||||||
private val HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector"
|
private val PATTERN_TYPE = PatternType.PATH
|
||||||
private val HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector"
|
|
||||||
private val MVC_PRESENT = ClassUtils.isPresent(
|
|
||||||
HANDLER_MAPPING_INTROSPECTOR,
|
|
||||||
AuthorizeHttpRequestsDsl::class.java.classLoader)
|
|
||||||
private val PATTERN_TYPE = if (MVC_PRESENT) PatternType.MVC else PatternType.ANT
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a request authorization rule.
|
* Adds a request authorization rule.
|
||||||
@ -288,17 +281,13 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl {
|
|||||||
when (rule) {
|
when (rule) {
|
||||||
is MatcherAuthorizationManagerRule -> requests.requestMatchers(rule.matcher).access(rule.rule)
|
is MatcherAuthorizationManagerRule -> requests.requestMatchers(rule.matcher).access(rule.rule)
|
||||||
is PatternAuthorizationManagerRule -> {
|
is PatternAuthorizationManagerRule -> {
|
||||||
when (rule.patternType) {
|
var builder = requests.applicationContext.getBeanProvider(
|
||||||
PatternType.ANT -> requests.requestMatchers(rule.httpMethod, rule.pattern).access(rule.rule)
|
PathPatternRequestMatcher.Builder::class.java)
|
||||||
PatternType.MVC -> {
|
.getIfUnique(PathPatternRequestMatcher::withDefaults)
|
||||||
val introspector = requests.applicationContext.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, HandlerMappingIntrospector::class.java)
|
if (rule.servletPath != null) {
|
||||||
val mvcMatcher = MvcRequestMatcher.Builder(introspector)
|
builder = builder.basePath(rule.servletPath)
|
||||||
.servletPath(rule.servletPath)
|
|
||||||
.pattern(rule.pattern)
|
|
||||||
mvcMatcher.setMethod(rule.httpMethod)
|
|
||||||
requests.requestMatchers(mvcMatcher).access(rule.rule)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
requests.requestMatchers(builder.matcher(rule.httpMethod, rule.pattern)).access(rule.rule)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,9 @@ package org.springframework.security.config.annotation.web
|
|||||||
import org.springframework.http.HttpMethod
|
import org.springframework.http.HttpMethod
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer
|
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer
|
||||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher
|
||||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher
|
import org.springframework.security.web.util.matcher.AnyRequestMatcher
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher
|
import org.springframework.security.web.util.matcher.RequestMatcher
|
||||||
import org.springframework.util.ClassUtils
|
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Kotlin DSL to configure [HttpSecurity] request authorization using idiomatic Kotlin code.
|
* A Kotlin DSL to configure [HttpSecurity] request authorization using idiomatic Kotlin code.
|
||||||
@ -33,13 +31,7 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector
|
|||||||
*/
|
*/
|
||||||
class AuthorizeRequestsDsl : AbstractRequestMatcherDsl() {
|
class AuthorizeRequestsDsl : AbstractRequestMatcherDsl() {
|
||||||
private val authorizationRules = mutableListOf<AuthorizationRule>()
|
private val authorizationRules = mutableListOf<AuthorizationRule>()
|
||||||
|
private val PATTERN_TYPE = PatternType.PATH;
|
||||||
private val HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector"
|
|
||||||
private val HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector"
|
|
||||||
private val MVC_PRESENT = ClassUtils.isPresent(
|
|
||||||
HANDLER_MAPPING_INTROSPECTOR,
|
|
||||||
AuthorizeRequestsDsl::class.java.classLoader)
|
|
||||||
private val PATTERN_TYPE = if (MVC_PRESENT) PatternType.MVC else PatternType.ANT
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a request authorization rule.
|
* Adds a request authorization rule.
|
||||||
@ -226,17 +218,13 @@ class AuthorizeRequestsDsl : AbstractRequestMatcherDsl() {
|
|||||||
when (rule) {
|
when (rule) {
|
||||||
is MatcherAuthorizationRule -> requests.requestMatchers(rule.matcher).access(rule.rule)
|
is MatcherAuthorizationRule -> requests.requestMatchers(rule.matcher).access(rule.rule)
|
||||||
is PatternAuthorizationRule -> {
|
is PatternAuthorizationRule -> {
|
||||||
when (rule.patternType) {
|
var builder = requests.applicationContext.getBeanProvider(
|
||||||
PatternType.ANT -> requests.requestMatchers(rule.httpMethod, rule.pattern).access(rule.rule)
|
PathPatternRequestMatcher.Builder::class.java)
|
||||||
PatternType.MVC -> {
|
.getIfUnique(PathPatternRequestMatcher::withDefaults);
|
||||||
val introspector = requests.applicationContext.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, HandlerMappingIntrospector::class.java)
|
if (rule.servletPath != null) {
|
||||||
val mvcMatcher = MvcRequestMatcher.Builder(introspector)
|
builder = builder.basePath(rule.servletPath)
|
||||||
.servletPath(rule.servletPath)
|
|
||||||
.pattern(rule.pattern)
|
|
||||||
mvcMatcher.setMethod(rule.httpMethod)
|
|
||||||
requests.requestMatchers(mvcMatcher).access(rule.rule)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
requests.requestMatchers(builder.matcher(rule.httpMethod, rule.pattern)).access(rule.rule)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,6 @@ operator fun HttpSecurity.invoke(httpConfiguration: HttpSecurityDsl.() -> Unit)
|
|||||||
*/
|
*/
|
||||||
@SecurityMarker
|
@SecurityMarker
|
||||||
class HttpSecurityDsl(private val http: HttpSecurity, private val init: HttpSecurityDsl.() -> Unit) {
|
class HttpSecurityDsl(private val http: HttpSecurity, private val init: HttpSecurityDsl.() -> Unit) {
|
||||||
private val HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector"
|
|
||||||
|
|
||||||
var authenticationManager: AuthenticationManager? = null
|
var authenticationManager: AuthenticationManager? = null
|
||||||
val context: ApplicationContext = http.getSharedObject(ApplicationContext::class.java)
|
val context: ApplicationContext = http.getSharedObject(ApplicationContext::class.java)
|
||||||
@ -192,7 +191,7 @@ class HttpSecurityDsl(private val http: HttpSecurity, private val init: HttpSecu
|
|||||||
* @Bean
|
* @Bean
|
||||||
* fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
* fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||||
* http {
|
* http {
|
||||||
* securityMatcher(PathPatternRequestMatcher.withDefaults().matcher("/private/**"))
|
* securityMatcher(pathPattern("/private/**"))
|
||||||
* formLogin {
|
* formLogin {
|
||||||
* loginPage = "/log-in"
|
* loginPage = "/log-in"
|
||||||
* }
|
* }
|
||||||
|
@ -20,11 +20,9 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
|||||||
import org.springframework.security.config.annotation.web.configurers.ChannelSecurityConfigurer
|
import org.springframework.security.config.annotation.web.configurers.ChannelSecurityConfigurer
|
||||||
import org.springframework.security.web.access.channel.ChannelDecisionManagerImpl
|
import org.springframework.security.web.access.channel.ChannelDecisionManagerImpl
|
||||||
import org.springframework.security.web.access.channel.ChannelProcessor
|
import org.springframework.security.web.access.channel.ChannelProcessor
|
||||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher
|
||||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher
|
import org.springframework.security.web.util.matcher.AnyRequestMatcher
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher
|
import org.springframework.security.web.util.matcher.RequestMatcher
|
||||||
import org.springframework.util.ClassUtils
|
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Kotlin DSL to configure [HttpSecurity] channel security using idiomatic
|
* A Kotlin DSL to configure [HttpSecurity] channel security using idiomatic
|
||||||
@ -38,12 +36,7 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector
|
|||||||
class RequiresChannelDsl : AbstractRequestMatcherDsl() {
|
class RequiresChannelDsl : AbstractRequestMatcherDsl() {
|
||||||
private val channelSecurityRules = mutableListOf<AuthorizationRule>()
|
private val channelSecurityRules = mutableListOf<AuthorizationRule>()
|
||||||
|
|
||||||
private val HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector"
|
private val PATTERN_TYPE = PatternType.PATH
|
||||||
private val HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector"
|
|
||||||
private val MVC_PRESENT = ClassUtils.isPresent(
|
|
||||||
HANDLER_MAPPING_INTROSPECTOR,
|
|
||||||
RequiresChannelDsl::class.java.classLoader)
|
|
||||||
private val PATTERN_TYPE = if (MVC_PRESENT) PatternType.MVC else PatternType.ANT
|
|
||||||
|
|
||||||
var channelProcessors: List<ChannelProcessor>? = null
|
var channelProcessors: List<ChannelProcessor>? = null
|
||||||
|
|
||||||
@ -121,17 +114,13 @@ class RequiresChannelDsl : AbstractRequestMatcherDsl() {
|
|||||||
when (rule) {
|
when (rule) {
|
||||||
is MatcherAuthorizationRule -> channelSecurity.requestMatchers(rule.matcher).requires(rule.rule)
|
is MatcherAuthorizationRule -> channelSecurity.requestMatchers(rule.matcher).requires(rule.rule)
|
||||||
is PatternAuthorizationRule -> {
|
is PatternAuthorizationRule -> {
|
||||||
when (rule.patternType) {
|
var builder = channelSecurity.applicationContext.getBeanProvider(
|
||||||
PatternType.ANT -> channelSecurity.requestMatchers(rule.pattern).requires(rule.rule)
|
PathPatternRequestMatcher.Builder::class.java)
|
||||||
PatternType.MVC -> {
|
.getIfUnique(PathPatternRequestMatcher::withDefaults);
|
||||||
val introspector = channelSecurity.applicationContext.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, HandlerMappingIntrospector::class.java)
|
if (rule.servletPath != null) {
|
||||||
val mvcMatcher = MvcRequestMatcher.Builder(introspector)
|
builder = builder.basePath(rule.servletPath)
|
||||||
.servletPath(rule.servletPath)
|
|
||||||
.pattern(rule.pattern)
|
|
||||||
mvcMatcher.setMethod(rule.httpMethod)
|
|
||||||
channelSecurity.requestMatchers(mvcMatcher).requires(rule.rule)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
channelSecurity.requestMatchers(builder.matcher(rule.httpMethod, rule.pattern)).requires(rule.rule)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1183,7 +1183,7 @@ hsts-options.attlist &=
|
|||||||
attribute preload {xsd:boolean}?
|
attribute preload {xsd:boolean}?
|
||||||
|
|
||||||
cors =
|
cors =
|
||||||
## Element for configuration of CorsFilter. If no CorsFilter or CorsConfigurationSource is specified a HandlerMappingIntrospector is used as the CorsConfigurationSource
|
## Element for configuration of CorsFilter. A CorsConfigurationSource must be specified. If Spring MVC is present, then it will attempt to look up its `CorsConfigurationSource`.
|
||||||
element cors { cors-options.attlist }
|
element cors { cors-options.attlist }
|
||||||
cors-options.attlist &=
|
cors-options.attlist &=
|
||||||
ref?
|
ref?
|
||||||
|
@ -3317,8 +3317,8 @@
|
|||||||
</xs:attributeGroup>
|
</xs:attributeGroup>
|
||||||
<xs:element name="cors">
|
<xs:element name="cors">
|
||||||
<xs:annotation>
|
<xs:annotation>
|
||||||
<xs:documentation>Element for configuration of CorsFilter. If no CorsFilter or CorsConfigurationSource is
|
<xs:documentation>Element for configuration of CorsFilter. A CorsConfigurationSource must be specified. If
|
||||||
specified a HandlerMappingIntrospector is used as the CorsConfigurationSource
|
Spring MVC is present, then it will attempt to look up its `CorsConfigurationSource`.
|
||||||
</xs:documentation>
|
</xs:documentation>
|
||||||
</xs:annotation>
|
</xs:annotation>
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
|
@ -39,6 +39,7 @@ import org.springframework.security.web.servletapi.SecurityContextHolderAwareReq
|
|||||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
import org.springframework.test.util.ReflectionTestUtils;
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
|
import org.springframework.web.util.pattern.PathPattern;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
@ -121,7 +122,7 @@ public class FilterChainProxyConfigTests {
|
|||||||
|
|
||||||
private String getPattern(SecurityFilterChain chain) {
|
private String getPattern(SecurityFilterChain chain) {
|
||||||
RequestMatcher requestMatcher = ((DefaultSecurityFilterChain) chain).getRequestMatcher();
|
RequestMatcher requestMatcher = ((DefaultSecurityFilterChain) chain).getRequestMatcher();
|
||||||
return (String) ReflectionTestUtils.getField(requestMatcher, "pattern");
|
return ((PathPattern) ReflectionTestUtils.getField(requestMatcher, "pattern")).getPatternString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkPathAndFilterOrder(FilterChainProxy filterChainProxy) {
|
private void checkPathAndFilterOrder(FilterChainProxy filterChainProxy) {
|
||||||
|
@ -32,9 +32,10 @@ import org.springframework.security.core.Authentication;
|
|||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
*
|
*
|
||||||
@ -52,7 +53,7 @@ public class SecurityConfig {
|
|||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.authorizeRequests((requests) -> requests
|
.authorizeRequests((requests) -> requests
|
||||||
.requestMatchers(new AntPathRequestMatcher("/*")).permitAll())
|
.requestMatchers(pathPattern("/*")).permitAll())
|
||||||
.authenticationProvider(authenticationProvider());
|
.authenticationProvider(authenticationProvider());
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
return http.build();
|
return http.build();
|
||||||
|
@ -25,13 +25,12 @@ import org.springframework.mock.web.MockServletContext;
|
|||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
||||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
|
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link AbstractRequestMatcherRegistry}.
|
* Tests for {@link AbstractRequestMatcherRegistry}.
|
||||||
@ -88,7 +87,7 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests {
|
|||||||
http
|
http
|
||||||
.authorizeRequests((requests) -> requests
|
.authorizeRequests((requests) -> requests
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated()
|
||||||
.requestMatchers(new AntPathRequestMatcher("/demo/**")).permitAll());
|
.requestMatchers(pathPattern("/demo/**")).permitAll());
|
||||||
return http.build();
|
return http.build();
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
@ -100,12 +99,12 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests {
|
|||||||
static class MvcMatchersAfterAnyRequestConfig {
|
static class MvcMatchersAfterAnyRequestConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.authorizeRequests((requests) -> requests
|
.authorizeRequests((requests) -> requests
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated()
|
||||||
.requestMatchers(new MvcRequestMatcher(introspector, "/demo/**")).permitAll());
|
.requestMatchers(builder.matcher("/demo/**")).permitAll());
|
||||||
return http.build();
|
return http.build();
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
@ -156,7 +155,7 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests {
|
|||||||
http
|
http
|
||||||
.authorizeRequests((requests) -> requests
|
.authorizeRequests((requests) -> requests
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated()
|
||||||
.requestMatchers(new AntPathRequestMatcher("/**")).permitAll());
|
.requestMatchers(pathPattern("/**")).permitAll());
|
||||||
return http.build();
|
return http.build();
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
@ -21,9 +21,10 @@ import java.util.List;
|
|||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.security.test.support.ClassPathExclusions;
|
import org.springframework.security.test.support.ClassPathExclusions;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@ -41,22 +42,26 @@ public class AbstractRequestMatcherRegistryNoMvcTests {
|
|||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
this.matcherRegistry = new TestRequestMatcherRegistry();
|
this.matcherRegistry = new TestRequestMatcherRegistry();
|
||||||
|
GenericApplicationContext context = new GenericApplicationContext();
|
||||||
|
context.registerBean(PathPatternRequestMatcher.Builder.class, PathPatternRequestMatcher::withDefaults);
|
||||||
|
context.refresh();
|
||||||
|
this.matcherRegistry.setApplicationContext(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requestMatchersWhenPatternAndMvcNotPresentThenReturnAntPathRequestMatcherType() {
|
public void requestMatchersWhenPatternAndMvcNotPresentThenReturnPathPatternRequestMatcherType() {
|
||||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers("/path");
|
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers("/path");
|
||||||
assertThat(requestMatchers).isNotEmpty();
|
assertThat(requestMatchers).isNotEmpty();
|
||||||
assertThat(requestMatchers).hasSize(1);
|
assertThat(requestMatchers).hasSize(1);
|
||||||
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(AntPathRequestMatcher.class);
|
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requestMatchersWhenHttpMethodAndPatternAndMvcNotPresentThenReturnAntPathRequestMatcherType() {
|
public void requestMatchersWhenHttpMethodAndPatternAndMvcNotPresentThenReturnPathPatternRequestMatcherType() {
|
||||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers(HttpMethod.GET, "/path");
|
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers(HttpMethod.GET, "/path");
|
||||||
assertThat(requestMatchers).isNotEmpty();
|
assertThat(requestMatchers).isNotEmpty();
|
||||||
assertThat(requestMatchers).hasSize(1);
|
assertThat(requestMatchers).hasSize(1);
|
||||||
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(AntPathRequestMatcher.class);
|
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -64,7 +69,7 @@ public class AbstractRequestMatcherRegistryNoMvcTests {
|
|||||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers(HttpMethod.GET);
|
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers(HttpMethod.GET);
|
||||||
assertThat(requestMatchers).isNotEmpty();
|
assertThat(requestMatchers).isNotEmpty();
|
||||||
assertThat(requestMatchers).hasSize(1);
|
assertThat(requestMatchers).hasSize(1);
|
||||||
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(AntPathRequestMatcher.class);
|
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class TestRequestMatcherRegistry extends AbstractRequestMatcherRegistry<List<RequestMatcher>> {
|
private static class TestRequestMatcherRegistry extends AbstractRequestMatcherRegistry<List<RequestMatcher>> {
|
||||||
|
@ -16,47 +16,29 @@
|
|||||||
|
|
||||||
package org.springframework.security.config.annotation.web;
|
package org.springframework.security.config.annotation.web;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import jakarta.servlet.DispatcherType;
|
import jakarta.servlet.DispatcherType;
|
||||||
import jakarta.servlet.Servlet;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.ResolvableType;
|
import org.springframework.core.ResolvableType;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
|
||||||
import org.springframework.security.config.ObjectPostProcessor;
|
import org.springframework.security.config.ObjectPostProcessor;
|
||||||
import org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry.DispatcherServletDelegatingRequestMatcher;
|
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.test.SpringTestContext;
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
import org.springframework.security.web.servlet.MockServletContext;
|
|
||||||
import org.springframework.security.web.servlet.TestMockHttpServletMappings;
|
|
||||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher;
|
import org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
|
||||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
import org.springframework.web.servlet.DispatcherServlet;
|
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
|
||||||
import static org.assertj.core.api.InstanceOfAssertFactories.type;
|
|
||||||
import static org.mockito.BDDMockito.given;
|
import static org.mockito.BDDMockito.given;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
|
||||||
import static org.mockito.Mockito.verifyNoInteractions;
|
|
||||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link AbstractRequestMatcherRegistry}.
|
* Tests for {@link AbstractRequestMatcherRegistry}.
|
||||||
@ -86,9 +68,9 @@ public class AbstractRequestMatcherRegistryTests {
|
|||||||
ObjectProvider<ObjectPostProcessor<Object>> given = this.context.getBeanProvider(type);
|
ObjectProvider<ObjectPostProcessor<Object>> given = this.context.getBeanProvider(type);
|
||||||
given(given).willReturn(postProcessors);
|
given(given).willReturn(postProcessors);
|
||||||
given(postProcessors.getObject()).willReturn(NO_OP_OBJECT_POST_PROCESSOR);
|
given(postProcessors.getObject()).willReturn(NO_OP_OBJECT_POST_PROCESSOR);
|
||||||
given(this.context.getServletContext()).willReturn(MockServletContext.mvc());
|
given(this.context.getBean(PathPatternRequestMatcher.Builder.class))
|
||||||
|
.willReturn(PathPatternRequestMatcher.withDefaults());
|
||||||
this.matcherRegistry.setApplicationContext(this.context);
|
this.matcherRegistry.setApplicationContext(this.context);
|
||||||
mockMvcIntrospector(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -110,24 +92,24 @@ public class AbstractRequestMatcherRegistryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void antMatchersWhenHttpMethodAndPatternParamsThenReturnAntPathRequestMatcherType() {
|
public void pathPatternWhenHttpMethodAndPatternParamsThenReturnPathPatternRequestMatcherType() {
|
||||||
List<RequestMatcher> requestMatchers = this.matcherRegistry
|
List<RequestMatcher> requestMatchers = this.matcherRegistry
|
||||||
.requestMatchers(new AntPathRequestMatcher("/a.*", HttpMethod.GET.name()));
|
.requestMatchers(pathPattern(HttpMethod.GET, "/a.*"));
|
||||||
assertThat(requestMatchers).isNotEmpty();
|
assertThat(requestMatchers).isNotEmpty();
|
||||||
assertThat(requestMatchers).hasSize(1);
|
assertThat(requestMatchers).hasSize(1);
|
||||||
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(AntPathRequestMatcher.class);
|
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void antMatchersWhenPatternParamThenReturnAntPathRequestMatcherType() {
|
public void pathPatternWhenPatternParamThenReturnPathPatternRequestMatcherType() {
|
||||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers(new AntPathRequestMatcher("/a.*"));
|
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers(pathPattern("/a.*"));
|
||||||
assertThat(requestMatchers).isNotEmpty();
|
assertThat(requestMatchers).isNotEmpty();
|
||||||
assertThat(requestMatchers).hasSize(1);
|
assertThat(requestMatchers).hasSize(1);
|
||||||
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(AntPathRequestMatcher.class);
|
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void dispatcherTypeMatchersWhenHttpMethodAndPatternParamsThenReturnAntPathRequestMatcherType() {
|
public void dispatcherTypeMatchersWhenHttpMethodAndPatternParamsThenReturnPathPatternRequestMatcherType() {
|
||||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.dispatcherTypeMatchers(HttpMethod.GET,
|
List<RequestMatcher> requestMatchers = this.matcherRegistry.dispatcherTypeMatchers(HttpMethod.GET,
|
||||||
DispatcherType.ASYNC);
|
DispatcherType.ASYNC);
|
||||||
assertThat(requestMatchers).isNotEmpty();
|
assertThat(requestMatchers).isNotEmpty();
|
||||||
@ -136,7 +118,7 @@ public class AbstractRequestMatcherRegistryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void dispatcherMatchersWhenPatternParamThenReturnAntPathRequestMatcherType() {
|
public void dispatcherMatchersWhenPatternParamThenReturnPathPatternRequestMatcherType() {
|
||||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.dispatcherTypeMatchers(DispatcherType.INCLUDE);
|
List<RequestMatcher> requestMatchers = this.matcherRegistry.dispatcherTypeMatchers(DispatcherType.INCLUDE);
|
||||||
assertThat(requestMatchers).isNotEmpty();
|
assertThat(requestMatchers).isNotEmpty();
|
||||||
assertThat(requestMatchers).hasSize(1);
|
assertThat(requestMatchers).hasSize(1);
|
||||||
@ -144,252 +126,36 @@ public class AbstractRequestMatcherRegistryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requestMatchersWhenPatternAndMvcPresentThenReturnMvcRequestMatcherType() {
|
public void requestMatchersWhenPatternAndMvcPresentThenReturnPathPatternRequestMatcherType() {
|
||||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers("/path");
|
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers("/path");
|
||||||
assertThat(requestMatchers).isNotEmpty();
|
assertThat(requestMatchers).isNotEmpty();
|
||||||
assertThat(requestMatchers).hasSize(1);
|
assertThat(requestMatchers).hasSize(1);
|
||||||
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(MvcRequestMatcher.class);
|
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requestMatchersWhenHttpMethodAndPatternAndMvcPresentThenReturnMvcRequestMatcherType() {
|
public void requestMatchersWhenHttpMethodAndPatternAndMvcPresentThenReturnPathPatternRequestMatcherType() {
|
||||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers(HttpMethod.GET, "/path");
|
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers(HttpMethod.GET, "/path");
|
||||||
assertThat(requestMatchers).isNotEmpty();
|
assertThat(requestMatchers).isNotEmpty();
|
||||||
assertThat(requestMatchers).hasSize(1);
|
assertThat(requestMatchers).hasSize(1);
|
||||||
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(MvcRequestMatcher.class);
|
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requestMatchersWhenHttpMethodAndMvcPresentThenReturnMvcRequestMatcherType() {
|
public void requestMatchersWhenHttpMethodAndMvcPresentThenReturnPathPatternRequestMatcherType() {
|
||||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers(HttpMethod.GET);
|
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers(HttpMethod.GET);
|
||||||
assertThat(requestMatchers).isNotEmpty();
|
assertThat(requestMatchers).isNotEmpty();
|
||||||
assertThat(requestMatchers).hasSize(1);
|
assertThat(requestMatchers).hasSize(1);
|
||||||
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(MvcRequestMatcher.class);
|
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class);
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void requestMatchersWhenMvcPresentInClassPathAndMvcIntrospectorBeanNotAvailableThenException() {
|
|
||||||
mockMvcIntrospector(false);
|
|
||||||
assertThatExceptionOfType(NoSuchBeanDefinitionException.class)
|
|
||||||
.isThrownBy(() -> this.matcherRegistry.requestMatchers("/path"))
|
|
||||||
.withMessageContaining(
|
|
||||||
"Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void requestMatchersWhenNoDispatcherServletThenAntPathRequestMatcherType() {
|
|
||||||
mockMvcIntrospector(true);
|
|
||||||
MockServletContext servletContext = new MockServletContext();
|
|
||||||
given(this.context.getServletContext()).willReturn(servletContext);
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
|
||||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers("/**");
|
|
||||||
assertThat(requestMatchers).isNotEmpty();
|
|
||||||
assertThat(requestMatchers).hasSize(1);
|
|
||||||
assertThat(requestMatchers.get(0)).asInstanceOf(type(DispatcherServletDelegatingRequestMatcher.class))
|
|
||||||
.extracting((matcher) -> matcher.requestMatcher(request))
|
|
||||||
.isInstanceOf(AntPathRequestMatcher.class);
|
|
||||||
servletContext.addServlet("servletOne", Servlet.class).addMapping("/one");
|
|
||||||
servletContext.addServlet("servletTwo", Servlet.class).addMapping("/two");
|
|
||||||
requestMatchers = this.matcherRegistry.requestMatchers("/**");
|
|
||||||
assertThat(requestMatchers).isNotEmpty();
|
|
||||||
assertThat(requestMatchers).hasSize(1);
|
|
||||||
assertThat(requestMatchers.get(0)).asInstanceOf(type(DispatcherServletDelegatingRequestMatcher.class))
|
|
||||||
.extracting((matcher) -> matcher.requestMatcher(request))
|
|
||||||
.isInstanceOf(AntPathRequestMatcher.class);
|
|
||||||
servletContext.addServlet("servletOne", Servlet.class);
|
|
||||||
servletContext.addServlet("servletTwo", Servlet.class);
|
|
||||||
requestMatchers = this.matcherRegistry.requestMatchers("/**");
|
|
||||||
assertThat(requestMatchers).isNotEmpty();
|
|
||||||
assertThat(requestMatchers).hasSize(1);
|
|
||||||
assertThat(requestMatchers.get(0)).asInstanceOf(type(DispatcherServletDelegatingRequestMatcher.class))
|
|
||||||
.extracting((matcher) -> matcher.requestMatcher(request))
|
|
||||||
.isInstanceOf(AntPathRequestMatcher.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
// gh-14418
|
|
||||||
@Test
|
|
||||||
public void requestMatchersWhenNoDispatcherServletMockMvcThenMvcRequestMatcherType() throws Exception {
|
|
||||||
MockServletContext servletContext = new MockServletContext();
|
|
||||||
try (SpringTestContext spring = new SpringTestContext(this)) {
|
|
||||||
spring.register(MockMvcConfiguration.class)
|
|
||||||
.postProcessor((context) -> context.setServletContext(servletContext))
|
|
||||||
.autowire();
|
|
||||||
this.matcherRegistry.setApplicationContext(spring.getContext());
|
|
||||||
MockMvc mvc = MockMvcBuilders.webAppContextSetup(spring.getContext()).build();
|
|
||||||
MockHttpServletRequest request = mvc.perform(get("/")).andReturn().getRequest();
|
|
||||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers("/**");
|
|
||||||
assertThat(requestMatchers).isNotEmpty();
|
|
||||||
assertThat(requestMatchers).hasSize(1);
|
|
||||||
assertThat(requestMatchers.get(0)).asInstanceOf(type(DispatcherServletDelegatingRequestMatcher.class))
|
|
||||||
.extracting((matcher) -> matcher.requestMatcher(request))
|
|
||||||
.isInstanceOf(MvcRequestMatcher.class);
|
|
||||||
servletContext.addServlet("servletOne", Servlet.class).addMapping("/one");
|
|
||||||
servletContext.addServlet("servletTwo", Servlet.class).addMapping("/two");
|
|
||||||
requestMatchers = this.matcherRegistry.requestMatchers("/**");
|
|
||||||
assertThat(requestMatchers).isNotEmpty();
|
|
||||||
assertThat(requestMatchers).hasSize(1);
|
|
||||||
assertThat(requestMatchers.get(0)).asInstanceOf(type(DispatcherServletDelegatingRequestMatcher.class))
|
|
||||||
.extracting((matcher) -> matcher.requestMatcher(request))
|
|
||||||
.isInstanceOf(MvcRequestMatcher.class);
|
|
||||||
servletContext.addServlet("servletOne", Servlet.class);
|
|
||||||
servletContext.addServlet("servletTwo", Servlet.class);
|
|
||||||
requestMatchers = this.matcherRegistry.requestMatchers("/**");
|
|
||||||
assertThat(requestMatchers).isNotEmpty();
|
|
||||||
assertThat(requestMatchers).hasSize(1);
|
|
||||||
assertThat(requestMatchers.get(0)).asInstanceOf(type(DispatcherServletDelegatingRequestMatcher.class))
|
|
||||||
.extracting((matcher) -> matcher.requestMatcher(request))
|
|
||||||
.isInstanceOf(MvcRequestMatcher.class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void requestMatchersWhenAmbiguousServletsThenException() {
|
|
||||||
mockMvcIntrospector(true);
|
|
||||||
MockServletContext servletContext = new MockServletContext();
|
|
||||||
given(this.context.getServletContext()).willReturn(servletContext);
|
|
||||||
servletContext.addServlet("dispatcherServlet", DispatcherServlet.class).addMapping("/");
|
|
||||||
servletContext.addServlet("servletTwo", DispatcherServlet.class).addMapping("/servlet/*");
|
|
||||||
assertThatExceptionOfType(IllegalArgumentException.class)
|
|
||||||
.isThrownBy(() -> this.matcherRegistry.requestMatchers("/**"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void requestMatchersWhenMultipleDispatcherServletMappingsThenException() {
|
|
||||||
mockMvcIntrospector(true);
|
|
||||||
MockServletContext servletContext = new MockServletContext();
|
|
||||||
given(this.context.getServletContext()).willReturn(servletContext);
|
|
||||||
servletContext.addServlet("dispatcherServlet", DispatcherServlet.class).addMapping("/", "/mvc/*");
|
|
||||||
assertThatExceptionOfType(IllegalArgumentException.class)
|
|
||||||
.isThrownBy(() -> this.matcherRegistry.requestMatchers("/**"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void requestMatchersWhenPathDispatcherServletAndOtherServletsThenException() {
|
|
||||||
mockMvcIntrospector(true);
|
|
||||||
MockServletContext servletContext = new MockServletContext();
|
|
||||||
given(this.context.getServletContext()).willReturn(servletContext);
|
|
||||||
servletContext.addServlet("dispatcherServlet", DispatcherServlet.class).addMapping("/mvc/*");
|
|
||||||
servletContext.addServlet("default", Servlet.class).addMapping("/");
|
|
||||||
assertThatExceptionOfType(IllegalArgumentException.class)
|
|
||||||
.isThrownBy(() -> this.matcherRegistry.requestMatchers("/**"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void requestMatchersWhenUnmappableServletsThenSkips() {
|
|
||||||
mockMvcIntrospector(true);
|
|
||||||
MockServletContext servletContext = new MockServletContext();
|
|
||||||
given(this.context.getServletContext()).willReturn(servletContext);
|
|
||||||
servletContext.addServlet("dispatcherServlet", DispatcherServlet.class).addMapping("/");
|
|
||||||
servletContext.addServlet("servletTwo", Servlet.class);
|
|
||||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers("/**");
|
|
||||||
assertThat(requestMatchers).hasSize(1);
|
|
||||||
assertThat(requestMatchers.get(0)).isInstanceOf(MvcRequestMatcher.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void requestMatchersWhenOnlyDispatcherServletThenAllows() {
|
|
||||||
MockServletContext servletContext = new MockServletContext();
|
|
||||||
given(this.context.getServletContext()).willReturn(servletContext);
|
|
||||||
servletContext.addServlet("dispatcherServlet", DispatcherServlet.class).addMapping("/mvc/*");
|
|
||||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers("/**");
|
|
||||||
assertThat(requestMatchers).hasSize(1);
|
|
||||||
assertThat(requestMatchers.get(0)).isInstanceOf(MvcRequestMatcher.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void requestMatchersWhenImplicitServletsThenAllows() {
|
|
||||||
mockMvcIntrospector(true);
|
|
||||||
MockServletContext servletContext = new MockServletContext();
|
|
||||||
given(this.context.getServletContext()).willReturn(servletContext);
|
|
||||||
servletContext.addServlet("defaultServlet", Servlet.class);
|
|
||||||
servletContext.addServlet("jspServlet", Servlet.class).addMapping("*.jsp", "*.jspx");
|
|
||||||
servletContext.addServlet("dispatcherServlet", DispatcherServlet.class).addMapping("/");
|
|
||||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers("/**");
|
|
||||||
assertThat(requestMatchers).hasSize(1);
|
|
||||||
assertThat(requestMatchers.get(0)).isInstanceOf(DispatcherServletDelegatingRequestMatcher.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void requestMatchersWhenPathBasedNonDispatcherServletThenAllows() {
|
|
||||||
MockServletContext servletContext = new MockServletContext();
|
|
||||||
given(this.context.getServletContext()).willReturn(servletContext);
|
|
||||||
servletContext.addServlet("path", Servlet.class).addMapping("/services/*");
|
|
||||||
servletContext.addServlet("default", DispatcherServlet.class).addMapping("/");
|
|
||||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers("/services/*");
|
|
||||||
assertThat(requestMatchers).hasSize(1);
|
|
||||||
assertThat(requestMatchers.get(0)).isInstanceOf(DispatcherServletDelegatingRequestMatcher.class);
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(servletContext, "GET", "/services/endpoint");
|
|
||||||
request.setHttpServletMapping(TestMockHttpServletMappings.defaultMapping());
|
|
||||||
assertThat(requestMatchers.get(0).matcher(request).isMatch()).isTrue();
|
|
||||||
request.setHttpServletMapping(TestMockHttpServletMappings.path(request, "/services"));
|
|
||||||
request.setServletPath("/services");
|
|
||||||
request.setPathInfo("/endpoint");
|
|
||||||
assertThat(requestMatchers.get(0).matcher(request).isMatch()).isTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void matchesWhenDispatcherServletThenMvc() {
|
|
||||||
MockServletContext servletContext = new MockServletContext();
|
|
||||||
servletContext.addServlet("default", DispatcherServlet.class).addMapping("/");
|
|
||||||
servletContext.addServlet("path", Servlet.class).addMapping("/services/*");
|
|
||||||
MvcRequestMatcher mvc = mock(MvcRequestMatcher.class);
|
|
||||||
AntPathRequestMatcher ant = mock(AntPathRequestMatcher.class);
|
|
||||||
RequestMatcher requestMatcher = new DispatcherServletDelegatingRequestMatcher(ant, mvc);
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(servletContext, "GET", "/services/endpoint");
|
|
||||||
request.setHttpServletMapping(TestMockHttpServletMappings.defaultMapping());
|
|
||||||
assertThat(requestMatcher.matches(request)).isFalse();
|
|
||||||
verify(mvc).matches(request);
|
|
||||||
verifyNoInteractions(ant);
|
|
||||||
request.setHttpServletMapping(TestMockHttpServletMappings.path(request, "/services"));
|
|
||||||
assertThat(requestMatcher.matches(request)).isFalse();
|
|
||||||
verify(ant).matches(request);
|
|
||||||
verifyNoMoreInteractions(mvc);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void matchesWhenNoMappingThenException() {
|
|
||||||
MockServletContext servletContext = new MockServletContext();
|
|
||||||
servletContext.addServlet("default", DispatcherServlet.class).addMapping("/");
|
|
||||||
servletContext.addServlet("path", Servlet.class).addMapping("/services/*");
|
|
||||||
MvcRequestMatcher mvc = mock(MvcRequestMatcher.class);
|
|
||||||
AntPathRequestMatcher ant = mock(AntPathRequestMatcher.class);
|
|
||||||
RequestMatcher requestMatcher = new DispatcherServletDelegatingRequestMatcher(ant, mvc);
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(servletContext, "GET", "/services/endpoint");
|
|
||||||
assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> requestMatcher.matcher(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void mockMvcIntrospector(boolean isPresent) {
|
|
||||||
ApplicationContext context = this.matcherRegistry.getApplicationContext();
|
|
||||||
given(context.containsBean("mvcHandlerMappingIntrospector")).willReturn(isPresent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class TestRequestMatcherRegistry extends AbstractRequestMatcherRegistry<List<RequestMatcher>> {
|
private static class TestRequestMatcherRegistry extends AbstractRequestMatcherRegistry<List<RequestMatcher>> {
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<RequestMatcher> requestMatchers(RequestMatcher... requestMatchers) {
|
|
||||||
return unwrap(super.requestMatchers(requestMatchers));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<RequestMatcher> chainRequestMatchers(List<RequestMatcher> requestMatchers) {
|
protected List<RequestMatcher> chainRequestMatchers(List<RequestMatcher> requestMatchers) {
|
||||||
return requestMatchers;
|
return requestMatchers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<RequestMatcher> unwrap(List<RequestMatcher> wrappedMatchers) {
|
|
||||||
List<RequestMatcher> requestMatchers = new ArrayList<>();
|
|
||||||
for (RequestMatcher requestMatcher : wrappedMatchers) {
|
|
||||||
if (requestMatcher instanceof DeferredRequestMatcher) {
|
|
||||||
DeferredRequestMatcher deferred = (DeferredRequestMatcher) requestMatcher;
|
|
||||||
WebApplicationContext web = (WebApplicationContext) getApplicationContext();
|
|
||||||
requestMatchers.add(deferred.requestMatcher(web.getServletContext()));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
requestMatchers.add(requestMatcher);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return requestMatchers;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@ -39,7 +39,6 @@ import org.springframework.security.core.userdetails.PasswordEncodedUser;
|
|||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
@ -49,6 +48,7 @@ import static org.mockito.ArgumentMatchers.any;
|
|||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.springframework.security.config.Customizer.withDefaults;
|
import static org.springframework.security.config.Customizer.withDefaults;
|
||||||
|
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
@ -150,8 +150,8 @@ public class HttpConfigurationTests {
|
|||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatchers((security) -> security
|
.securityMatchers((security) -> security
|
||||||
.requestMatchers(new AntPathRequestMatcher("/api/**"))
|
.requestMatchers(pathPattern("/api/**"))
|
||||||
.requestMatchers(new AntPathRequestMatcher("/oauth/**")))
|
.requestMatchers(pathPattern("/oauth/**")))
|
||||||
.authorizeRequests((requests) -> requests
|
.authorizeRequests((requests) -> requests
|
||||||
.anyRequest().hasRole("USER"))
|
.anyRequest().hasRole("USER"))
|
||||||
.httpBasic(withDefaults());
|
.httpBasic(withDefaults());
|
||||||
|
@ -54,8 +54,8 @@ import org.springframework.security.web.access.intercept.FilterSecurityIntercept
|
|||||||
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
|
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
|
||||||
import org.springframework.security.web.context.NullSecurityContextRepository;
|
import org.springframework.security.web.context.NullSecurityContextRepository;
|
||||||
import org.springframework.security.web.jaasapi.JaasApiIntegrationFilter;
|
import org.springframework.security.web.jaasapi.JaasApiIntegrationFilter;
|
||||||
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestWrapper;
|
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestWrapper;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
@ -75,6 +75,7 @@ import static org.springframework.security.config.Customizer.withDefaults;
|
|||||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
|
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
|
||||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication;
|
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication;
|
||||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
|
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
|
||||||
|
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||||
@ -195,13 +196,13 @@ public class NamespaceHttpTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test // http@request-matcher-ref ant
|
@Test // http@request-matcher-ref ant
|
||||||
public void configureWhenAntPatternMatchingThenAntPathRequestMatcherUsed() {
|
public void configureWhenAntPatternMatchingThenPathPatternRequestMatcherUsed() {
|
||||||
this.spring.register(RequestMatcherAntConfig.class).autowire();
|
this.spring.register(RequestMatcherAntConfig.class).autowire();
|
||||||
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
|
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
|
||||||
assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class);
|
assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class);
|
||||||
DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains()
|
DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains()
|
||||||
.get(0);
|
.get(0);
|
||||||
assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class);
|
assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(PathPatternRequestMatcher.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // http@request-matcher-ref regex
|
@Test // http@request-matcher-ref regex
|
||||||
@ -226,21 +227,19 @@ public class NamespaceHttpTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test // http@security=none
|
@Test // http@security=none
|
||||||
public void configureWhenIgnoredAntPatternsThenAntPathRequestMatcherUsedWithNoFilters() {
|
public void configureWhenIgnoredAntPatternsThenPathPatternRequestMatcherUsedWithNoFilters() {
|
||||||
this.spring.register(SecurityNoneConfig.class).autowire();
|
this.spring.register(SecurityNoneConfig.class).autowire();
|
||||||
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
|
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
|
||||||
assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class);
|
assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class);
|
||||||
DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains()
|
DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains()
|
||||||
.get(0);
|
.get(0);
|
||||||
assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class);
|
assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(PathPatternRequestMatcher.class);
|
||||||
assertThat(((AntPathRequestMatcher) securityFilterChain.getRequestMatcher()).getPattern())
|
assertThat(securityFilterChain.getRequestMatcher()).isEqualTo(pathPattern("/resources/**"));
|
||||||
.isEqualTo("/resources/**");
|
|
||||||
assertThat(securityFilterChain.getFilters()).isEmpty();
|
assertThat(securityFilterChain.getFilters()).isEmpty();
|
||||||
assertThat(filterChainProxy.getFilterChains().get(1)).isInstanceOf(DefaultSecurityFilterChain.class);
|
assertThat(filterChainProxy.getFilterChains().get(1)).isInstanceOf(DefaultSecurityFilterChain.class);
|
||||||
securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains().get(1);
|
securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains().get(1);
|
||||||
assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class);
|
assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(PathPatternRequestMatcher.class);
|
||||||
assertThat(((AntPathRequestMatcher) securityFilterChain.getRequestMatcher()).getPattern())
|
assertThat(securityFilterChain.getRequestMatcher()).isEqualTo(pathPattern("/public/**"));
|
||||||
.isEqualTo("/public/**");
|
|
||||||
assertThat(securityFilterChain.getFilters()).isEmpty();
|
assertThat(securityFilterChain.getFilters()).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,7 +481,7 @@ public class NamespaceHttpTests {
|
|||||||
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatcher(new AntPathRequestMatcher("/api/**"));
|
.securityMatcher(pathPattern("/api/**"));
|
||||||
return http.build();
|
return http.build();
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
@ -534,8 +533,9 @@ public class NamespaceHttpTests {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
WebSecurityCustomizer webSecurityCustomizer() {
|
WebSecurityCustomizer webSecurityCustomizer() {
|
||||||
|
PathPatternRequestMatcher.Builder builder = PathPatternRequestMatcher.withDefaults();
|
||||||
return (web) -> web.ignoring()
|
return (web) -> web.ignoring()
|
||||||
.requestMatchers(new AntPathRequestMatcher("/resources/**"), new AntPathRequestMatcher("/public/**"));
|
.requestMatchers(builder.matcher("/resources/**"), builder.matcher("/public/**"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@ -31,7 +31,7 @@ import org.springframework.security.web.UnreachableFilterChainException;
|
|||||||
import org.springframework.security.web.access.ExceptionTranslationFilter;
|
import org.springframework.security.web.access.ExceptionTranslationFilter;
|
||||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
||||||
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
|
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatchers;
|
import org.springframework.security.web.util.matcher.RequestMatchers;
|
||||||
@ -49,6 +49,8 @@ public class WebSecurityFilterChainValidatorTests {
|
|||||||
|
|
||||||
private final WebSecurityFilterChainValidator validator = new WebSecurityFilterChainValidator();
|
private final WebSecurityFilterChainValidator validator = new WebSecurityFilterChainValidator();
|
||||||
|
|
||||||
|
private final PathPatternRequestMatcher.Builder builder = PathPatternRequestMatcher.withDefaults();
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private AnonymousAuthenticationFilter authenticationFilter;
|
private AnonymousAuthenticationFilter authenticationFilter;
|
||||||
|
|
||||||
@ -60,7 +62,7 @@ public class WebSecurityFilterChainValidatorTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void validateWhenFilterSecurityInterceptorConfiguredThenValidates() {
|
void validateWhenFilterSecurityInterceptorConfiguredThenValidates() {
|
||||||
SecurityFilterChain chain = new DefaultSecurityFilterChain(AntPathRequestMatcher.antMatcher("/api"),
|
SecurityFilterChain chain = new DefaultSecurityFilterChain(this.builder.matcher("/api"),
|
||||||
this.authenticationFilter, this.exceptionTranslationFilter, this.authorizationInterceptor);
|
this.authenticationFilter, this.exceptionTranslationFilter, this.authorizationInterceptor);
|
||||||
FilterChainProxy proxy = new FilterChainProxy(List.of(chain));
|
FilterChainProxy proxy = new FilterChainProxy(List.of(chain));
|
||||||
|
|
||||||
@ -69,7 +71,7 @@ public class WebSecurityFilterChainValidatorTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void validateWhenAnyRequestMatcherIsPresentThenUnreachableFilterChainException() {
|
void validateWhenAnyRequestMatcherIsPresentThenUnreachableFilterChainException() {
|
||||||
SecurityFilterChain chain1 = new DefaultSecurityFilterChain(AntPathRequestMatcher.antMatcher("/api"),
|
SecurityFilterChain chain1 = new DefaultSecurityFilterChain(this.builder.matcher("/api"),
|
||||||
this.authenticationFilter, this.exceptionTranslationFilter, this.authorizationInterceptor);
|
this.authenticationFilter, this.exceptionTranslationFilter, this.authorizationInterceptor);
|
||||||
SecurityFilterChain chain2 = new DefaultSecurityFilterChain(AnyRequestMatcher.INSTANCE,
|
SecurityFilterChain chain2 = new DefaultSecurityFilterChain(AnyRequestMatcher.INSTANCE,
|
||||||
this.authenticationFilter, this.exceptionTranslationFilter, this.authorizationInterceptor);
|
this.authenticationFilter, this.exceptionTranslationFilter, this.authorizationInterceptor);
|
||||||
@ -84,9 +86,9 @@ public class WebSecurityFilterChainValidatorTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void validateWhenSameRequestMatchersArePresentThenUnreachableFilterChainException() {
|
void validateWhenSameRequestMatchersArePresentThenUnreachableFilterChainException() {
|
||||||
SecurityFilterChain chain1 = new DefaultSecurityFilterChain(AntPathRequestMatcher.antMatcher("/api"),
|
SecurityFilterChain chain1 = new DefaultSecurityFilterChain(this.builder.matcher("/api"),
|
||||||
this.authenticationFilter, this.exceptionTranslationFilter, this.authorizationInterceptor);
|
this.authenticationFilter, this.exceptionTranslationFilter, this.authorizationInterceptor);
|
||||||
SecurityFilterChain chain2 = new DefaultSecurityFilterChain(AntPathRequestMatcher.antMatcher("/api"),
|
SecurityFilterChain chain2 = new DefaultSecurityFilterChain(this.builder.matcher("/api"),
|
||||||
this.authenticationFilter, this.exceptionTranslationFilter, this.authorizationInterceptor);
|
this.authenticationFilter, this.exceptionTranslationFilter, this.authorizationInterceptor);
|
||||||
List<SecurityFilterChain> chains = new ArrayList<>();
|
List<SecurityFilterChain> chains = new ArrayList<>();
|
||||||
chains.add(chain2);
|
chains.add(chain2);
|
||||||
@ -99,10 +101,12 @@ public class WebSecurityFilterChainValidatorTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void validateWhenSameComposedRequestMatchersArePresentThenUnreachableFilterChainException() {
|
void validateWhenSameComposedRequestMatchersArePresentThenUnreachableFilterChainException() {
|
||||||
RequestMatcher matcher1 = RequestMatchers.anyOf(RequestMatchers.allOf(AntPathRequestMatcher.antMatcher("/api"),
|
RequestMatcher matcher1 = RequestMatchers.anyOf(
|
||||||
AntPathRequestMatcher.antMatcher("*.do")), AntPathRequestMatcher.antMatcher("/admin"));
|
RequestMatchers.allOf(this.builder.matcher("/api"), this.builder.matcher("/*.do")),
|
||||||
RequestMatcher matcher2 = RequestMatchers.anyOf(RequestMatchers.allOf(AntPathRequestMatcher.antMatcher("/api"),
|
this.builder.matcher("/admin"));
|
||||||
AntPathRequestMatcher.antMatcher("*.do")), AntPathRequestMatcher.antMatcher("/admin"));
|
RequestMatcher matcher2 = RequestMatchers.anyOf(
|
||||||
|
RequestMatchers.allOf(this.builder.matcher("/api"), this.builder.matcher("/*.do")),
|
||||||
|
this.builder.matcher("/admin"));
|
||||||
SecurityFilterChain chain1 = new DefaultSecurityFilterChain(matcher1, this.authenticationFilter,
|
SecurityFilterChain chain1 = new DefaultSecurityFilterChain(matcher1, this.authenticationFilter,
|
||||||
this.exceptionTranslationFilter, this.authorizationInterceptor);
|
this.exceptionTranslationFilter, this.authorizationInterceptor);
|
||||||
SecurityFilterChain chain2 = new DefaultSecurityFilterChain(matcher2, this.authenticationFilter,
|
SecurityFilterChain chain2 = new DefaultSecurityFilterChain(matcher2, this.authenticationFilter,
|
||||||
|
@ -42,12 +42,11 @@ import org.springframework.security.core.userdetails.UserDetailsService;
|
|||||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.firewall.HttpStatusRequestRejectedHandler;
|
import org.springframework.security.web.firewall.HttpStatusRequestRejectedHandler;
|
||||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.springframework.security.config.Customizer.withDefaults;
|
import static org.springframework.security.config.Customizer.withDefaults;
|
||||||
@ -130,8 +129,8 @@ public class WebSecurityTests {
|
|||||||
static class MvcMatcherConfig {
|
static class MvcMatcherConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
WebSecurityCustomizer webSecurityCustomizer(HandlerMappingIntrospector introspector) {
|
WebSecurityCustomizer webSecurityCustomizer(PathPatternRequestMatcher.Builder builder) {
|
||||||
return (web) -> web.ignoring().requestMatchers(new MvcRequestMatcher(introspector, "/path"));
|
return (web) -> web.ignoring().requestMatchers(builder.matcher("/path"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ -168,9 +167,10 @@ public class WebSecurityTests {
|
|||||||
static class MvcMatcherServletPathConfig {
|
static class MvcMatcherServletPathConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
WebSecurityCustomizer webSecurityCustomizer(HandlerMappingIntrospector introspector) {
|
WebSecurityCustomizer webSecurityCustomizer(PathPatternRequestMatcher.Builder builder) {
|
||||||
MvcRequestMatcher.Builder builder = new MvcRequestMatcher.Builder(introspector).servletPath("/spring");
|
return (web) -> web.ignoring()
|
||||||
return (web) -> web.ignoring().requestMatchers(builder.pattern("/path")).requestMatchers("/notused");
|
.requestMatchers(builder.basePath("/spring").matcher("/path"))
|
||||||
|
.requestMatchers("/notused");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@ -26,20 +26,19 @@ import org.springframework.security.authentication.TestAuthentication;
|
|||||||
import org.springframework.security.config.test.SpringTestContext;
|
import org.springframework.security.config.test.SpringTestContext;
|
||||||
import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners;
|
import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners;
|
||||||
import org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator.HttpServletRequestTransformer;
|
import org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator.HttpServletRequestTransformer;
|
||||||
import org.springframework.security.web.access.HandlerMappingIntrospectorRequestTransformer;
|
|
||||||
import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
|
import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
import org.springframework.test.context.web.WebAppConfiguration;
|
import org.springframework.test.context.web.WebAppConfiguration;
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks that HandlerMappingIntrospectorRequestTransformer is autowired into
|
* Checks that
|
||||||
|
* {@link org.springframework.security.web.access.PathPatternRequestTransformer} is
|
||||||
|
* autowired into
|
||||||
* {@link org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator}.
|
* {@link org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator}.
|
||||||
*
|
*
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
@ -59,20 +58,8 @@ public class AuthorizationManagerWebInvocationPrivilegeEvaluatorConfigTests {
|
|||||||
WebInvocationPrivilegeEvaluator wipe;
|
WebInvocationPrivilegeEvaluator wipe;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void mvcEnabledConfigThenHandlerMappingIntrospectorRequestTransformerBeanExists() {
|
void webAndTransformerThenWIPEDelegatesToTransformer() {
|
||||||
this.spring.register(MvcEnabledConfig.class).autowire();
|
this.spring.register(WebConfig.class, TransformerConfig.class).autowire();
|
||||||
assertThat(this.requestTransformer).isInstanceOf(HandlerMappingIntrospectorRequestTransformer.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void mvcNotEnabledThenNoRequestTransformerBeanExists() {
|
|
||||||
this.spring.register(MvcNotEnabledConfig.class).autowire();
|
|
||||||
assertThat(this.requestTransformer).isNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void mvcNotEnabledAndTransformerThenWIPEDelegatesToTransformer() {
|
|
||||||
this.spring.register(MvcNotEnabledConfig.class, TransformerConfig.class).autowire();
|
|
||||||
|
|
||||||
this.wipe.isAllowed("/uri", TestAuthentication.authenticatedUser());
|
this.wipe.isAllowed("/uri", TestAuthentication.authenticatedUser());
|
||||||
|
|
||||||
@ -90,15 +77,8 @@ public class AuthorizationManagerWebInvocationPrivilegeEvaluatorConfigTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebMvc
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
static class MvcEnabledConfig {
|
static class WebConfig {
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableWebSecurity
|
|
||||||
static class MvcNotEnabledConfig {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,127 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2002-2023 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.config.annotation.web.configuration;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import jakarta.servlet.Filter;
|
|
||||||
import jakarta.servlet.FilterChain;
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.ServletRequest;
|
|
||||||
import jakarta.servlet.ServletResponse;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.security.config.test.SpringTestContext;
|
|
||||||
import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners;
|
|
||||||
import org.springframework.security.test.context.support.WithMockUser;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
|
||||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
|
||||||
import org.springframework.test.context.web.WebAppConfiguration;
|
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
|
||||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector.CachedResult;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
|
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Rob Winch
|
|
||||||
*/
|
|
||||||
@ContextConfiguration
|
|
||||||
@WebAppConfiguration
|
|
||||||
@ExtendWith({ SpringExtension.class })
|
|
||||||
@SecurityTestExecutionListeners
|
|
||||||
class HandlerMappingIntrospectorCacheFilterConfigTests {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
WebApplicationContext context;
|
|
||||||
|
|
||||||
MockMvc mockMvc;
|
|
||||||
|
|
||||||
public final SpringTestContext spring = new SpringTestContext(this);
|
|
||||||
|
|
||||||
@Autowired(required = false)
|
|
||||||
MvcEnabledConfig.CaptureHandlerMappingIntrospectorCache captureCacheFilter;
|
|
||||||
|
|
||||||
@Autowired(required = false)
|
|
||||||
HandlerMappingIntrospector hmi;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@WithMockUser
|
|
||||||
void hmiIsCached() throws Exception {
|
|
||||||
this.spring.register(MvcEnabledConfig.class).autowire();
|
|
||||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
|
||||||
.apply(springSecurity())
|
|
||||||
.addFilter(this.captureCacheFilter)
|
|
||||||
.build();
|
|
||||||
this.mockMvc.perform(get("/"));
|
|
||||||
assertThat(this.captureCacheFilter.cachedResult).isNotNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@WithMockUser
|
|
||||||
void configurationLoadsIfNoHMI() {
|
|
||||||
// no BeanCreationException due to missing HandlerMappingIntrospector
|
|
||||||
this.spring.register(MvcNotEnabledConfig.class).autowire();
|
|
||||||
// ensure assumption of HandlerMappingIntrospector is null is true
|
|
||||||
assertThat(this.hmi).isNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableWebMvc
|
|
||||||
@EnableWebSecurity
|
|
||||||
static class MvcEnabledConfig {
|
|
||||||
|
|
||||||
@Component
|
|
||||||
static class CaptureHandlerMappingIntrospectorCache implements Filter {
|
|
||||||
|
|
||||||
final HandlerMappingIntrospector hmi;
|
|
||||||
|
|
||||||
private CachedResult cachedResult;
|
|
||||||
|
|
||||||
CaptureHandlerMappingIntrospectorCache(HandlerMappingIntrospector hmi) {
|
|
||||||
this.hmi = hmi;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
|
||||||
throws IOException, ServletException {
|
|
||||||
// capture the old cached value to check that caching has already occurred
|
|
||||||
this.cachedResult = this.hmi.setCache((HttpServletRequest) request);
|
|
||||||
chain.doFilter(request, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableWebSecurity
|
|
||||||
static class MvcNotEnabledConfig {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -62,8 +62,6 @@ import org.springframework.security.web.access.PathPatternRequestTransformer;
|
|||||||
import org.springframework.security.web.access.RequestMatcherDelegatingWebInvocationPrivilegeEvaluator;
|
import org.springframework.security.web.access.RequestMatcherDelegatingWebInvocationPrivilegeEvaluator;
|
||||||
import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
|
import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
|
||||||
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
|
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
|
||||||
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@ -78,6 +76,7 @@ import static org.mockito.Mockito.atLeastOnce;
|
|||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
@ -106,14 +105,13 @@ public class WebSecurityConfigurationTests {
|
|||||||
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
|
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
|
||||||
List<SecurityFilterChain> filterChains = filterChainProxy.getFilterChains();
|
List<SecurityFilterChain> filterChains = filterChainProxy.getFilterChains();
|
||||||
assertThat(filterChains).hasSize(4);
|
assertThat(filterChains).hasSize(4);
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/role1/**");
|
||||||
request.setServletPath("/role1/**");
|
|
||||||
assertThat(filterChains.get(0).matches(request)).isTrue();
|
assertThat(filterChains.get(0).matches(request)).isTrue();
|
||||||
request.setServletPath("/role2/**");
|
request = new MockHttpServletRequest("GET", "/role2/**");
|
||||||
assertThat(filterChains.get(1).matches(request)).isTrue();
|
assertThat(filterChains.get(1).matches(request)).isTrue();
|
||||||
request.setServletPath("/role3/**");
|
request = new MockHttpServletRequest("GET", "/role3/**");
|
||||||
assertThat(filterChains.get(2).matches(request)).isTrue();
|
assertThat(filterChains.get(2).matches(request)).isTrue();
|
||||||
request.setServletPath("/**");
|
request = new MockHttpServletRequest("GET", "/**");
|
||||||
assertThat(filterChains.get(3).matches(request)).isTrue();
|
assertThat(filterChains.get(3).matches(request)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,10 +121,9 @@ public class WebSecurityConfigurationTests {
|
|||||||
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
|
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
|
||||||
List<SecurityFilterChain> filterChains = filterChainProxy.getFilterChains();
|
List<SecurityFilterChain> filterChains = filterChainProxy.getFilterChains();
|
||||||
assertThat(filterChains).hasSize(2);
|
assertThat(filterChains).hasSize(2);
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/role1/**");
|
||||||
request.setServletPath("/role1/**");
|
|
||||||
assertThat(filterChains.get(0).matches(request)).isTrue();
|
assertThat(filterChains.get(0).matches(request)).isTrue();
|
||||||
request.setServletPath("/role2/**");
|
request = new MockHttpServletRequest("GET", "/role2/**");
|
||||||
assertThat(filterChains.get(1).matches(request)).isTrue();
|
assertThat(filterChains.get(1).matches(request)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,14 +237,13 @@ public class WebSecurityConfigurationTests {
|
|||||||
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
|
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
|
||||||
List<SecurityFilterChain> filterChains = filterChainProxy.getFilterChains();
|
List<SecurityFilterChain> filterChains = filterChainProxy.getFilterChains();
|
||||||
assertThat(filterChains).hasSize(3);
|
assertThat(filterChains).hasSize(3);
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/ignore1");
|
||||||
request.setServletPath("/ignore1");
|
|
||||||
assertThat(filterChains.get(0).matches(request)).isTrue();
|
assertThat(filterChains.get(0).matches(request)).isTrue();
|
||||||
assertThat(filterChains.get(0).getFilters()).isEmpty();
|
assertThat(filterChains.get(0).getFilters()).isEmpty();
|
||||||
request.setServletPath("/ignore2");
|
request = new MockHttpServletRequest("GET", "/ignore2");
|
||||||
assertThat(filterChains.get(1).matches(request)).isTrue();
|
assertThat(filterChains.get(1).matches(request)).isTrue();
|
||||||
assertThat(filterChains.get(1).getFilters()).isEmpty();
|
assertThat(filterChains.get(1).getFilters()).isEmpty();
|
||||||
request.setServletPath("/test/**");
|
request = new MockHttpServletRequest("GET", "/test/**");
|
||||||
assertThat(filterChains.get(2).matches(request)).isTrue();
|
assertThat(filterChains.get(2).matches(request)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,16 +253,15 @@ public class WebSecurityConfigurationTests {
|
|||||||
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
|
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
|
||||||
List<SecurityFilterChain> filterChains = filterChainProxy.getFilterChains();
|
List<SecurityFilterChain> filterChains = filterChainProxy.getFilterChains();
|
||||||
assertThat(filterChains).hasSize(3);
|
assertThat(filterChains).hasSize(3);
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/ignore1");
|
||||||
request.setServletPath("/ignore1");
|
|
||||||
assertThat(filterChains.get(0).matches(request)).isTrue();
|
assertThat(filterChains.get(0).matches(request)).isTrue();
|
||||||
assertThat(filterChains.get(0).getFilters()).isEmpty();
|
assertThat(filterChains.get(0).getFilters()).isEmpty();
|
||||||
request.setServletPath("/ignore2");
|
request = new MockHttpServletRequest("GET", "/ignore2");
|
||||||
assertThat(filterChains.get(1).matches(request)).isTrue();
|
assertThat(filterChains.get(1).matches(request)).isTrue();
|
||||||
assertThat(filterChains.get(1).getFilters()).isEmpty();
|
assertThat(filterChains.get(1).getFilters()).isEmpty();
|
||||||
request.setServletPath("/role1/**");
|
request = new MockHttpServletRequest("GET", "/role1/**");
|
||||||
assertThat(filterChains.get(2).matches(request)).isTrue();
|
assertThat(filterChains.get(2).matches(request)).isTrue();
|
||||||
request.setServletPath("/test/**");
|
request = new MockHttpServletRequest("GET", "/test/**");
|
||||||
assertThat(filterChains.get(2).matches(request)).isFalse();
|
assertThat(filterChains.get(2).matches(request)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,11 +271,10 @@ public class WebSecurityConfigurationTests {
|
|||||||
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
|
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
|
||||||
List<SecurityFilterChain> filterChains = filterChainProxy.getFilterChains();
|
List<SecurityFilterChain> filterChains = filterChainProxy.getFilterChains();
|
||||||
assertThat(filterChains).hasSize(3);
|
assertThat(filterChains).hasSize(3);
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/ignore1");
|
||||||
request.setServletPath("/ignore1");
|
|
||||||
assertThat(filterChains.get(0).matches(request)).isTrue();
|
assertThat(filterChains.get(0).matches(request)).isTrue();
|
||||||
assertThat(filterChains.get(0).getFilters()).isEmpty();
|
assertThat(filterChains.get(0).getFilters()).isEmpty();
|
||||||
request.setServletPath("/ignore2");
|
request = new MockHttpServletRequest("GET", "/ignore2");
|
||||||
assertThat(filterChains.get(1).matches(request)).isTrue();
|
assertThat(filterChains.get(1).matches(request)).isTrue();
|
||||||
assertThat(filterChains.get(1).getFilters()).isEmpty();
|
assertThat(filterChains.get(1).getFilters()).isEmpty();
|
||||||
}
|
}
|
||||||
@ -420,7 +414,7 @@ public class WebSecurityConfigurationTests {
|
|||||||
SecurityFilterChain filterChain1(HttpSecurity http) throws Exception {
|
SecurityFilterChain filterChain1(HttpSecurity http) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
return http
|
return http
|
||||||
.securityMatcher(new AntPathRequestMatcher("/role1/**"))
|
.securityMatcher(pathPattern("/role1/**"))
|
||||||
.authorizeRequests((authorize) -> authorize
|
.authorizeRequests((authorize) -> authorize
|
||||||
.anyRequest().hasRole("1")
|
.anyRequest().hasRole("1")
|
||||||
)
|
)
|
||||||
@ -433,7 +427,7 @@ public class WebSecurityConfigurationTests {
|
|||||||
SecurityFilterChain filterChain2(HttpSecurity http) throws Exception {
|
SecurityFilterChain filterChain2(HttpSecurity http) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
return http
|
return http
|
||||||
.securityMatcher(new AntPathRequestMatcher("/role2/**"))
|
.securityMatcher(pathPattern("/role2/**"))
|
||||||
.authorizeRequests((authorize) -> authorize
|
.authorizeRequests((authorize) -> authorize
|
||||||
.anyRequest().hasRole("2")
|
.anyRequest().hasRole("2")
|
||||||
)
|
)
|
||||||
@ -446,7 +440,7 @@ public class WebSecurityConfigurationTests {
|
|||||||
SecurityFilterChain filterChain3(HttpSecurity http) throws Exception {
|
SecurityFilterChain filterChain3(HttpSecurity http) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
return http
|
return http
|
||||||
.securityMatcher(new AntPathRequestMatcher("/role3/**"))
|
.securityMatcher(pathPattern("/role3/**"))
|
||||||
.authorizeRequests((authorize) -> authorize
|
.authorizeRequests((authorize) -> authorize
|
||||||
.anyRequest().hasRole("3")
|
.anyRequest().hasRole("3")
|
||||||
)
|
)
|
||||||
@ -477,7 +471,7 @@ public class WebSecurityConfigurationTests {
|
|||||||
SecurityFilterChain securityFilterChain1(HttpSecurity http) throws Exception {
|
SecurityFilterChain securityFilterChain1(HttpSecurity http) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
return http
|
return http
|
||||||
.securityMatcher(new AntPathRequestMatcher("/role1/**"))
|
.securityMatcher(pathPattern("/role1/**"))
|
||||||
.authorizeRequests((authorize) -> authorize
|
.authorizeRequests((authorize) -> authorize
|
||||||
.anyRequest().hasRole("1")
|
.anyRequest().hasRole("1")
|
||||||
)
|
)
|
||||||
@ -734,7 +728,7 @@ public class WebSecurityConfigurationTests {
|
|||||||
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
return http
|
return http
|
||||||
.securityMatcher(new AntPathRequestMatcher("/role1/**"))
|
.securityMatcher(pathPattern("/role1/**"))
|
||||||
.authorizeRequests((authorize) -> authorize
|
.authorizeRequests((authorize) -> authorize
|
||||||
.anyRequest().hasRole("1")
|
.anyRequest().hasRole("1")
|
||||||
)
|
)
|
||||||
@ -773,7 +767,7 @@ public class WebSecurityConfigurationTests {
|
|||||||
public SecurityFilterChain path1(HttpSecurity http) throws Exception {
|
public SecurityFilterChain path1(HttpSecurity http) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/path1/**")))
|
.securityMatchers((requests) -> requests.requestMatchers(pathPattern("/path1/**")))
|
||||||
.authorizeRequests((requests) -> requests.anyRequest().authenticated());
|
.authorizeRequests((requests) -> requests.anyRequest().authenticated());
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
return http.build();
|
return http.build();
|
||||||
@ -797,7 +791,7 @@ public class WebSecurityConfigurationTests {
|
|||||||
public SecurityFilterChain path1(HttpSecurity http) throws Exception {
|
public SecurityFilterChain path1(HttpSecurity http) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/path1/**")))
|
.securityMatchers((requests) -> requests.requestMatchers(pathPattern("/path1/**")))
|
||||||
.authorizeRequests((requests) -> requests.anyRequest().authenticated());
|
.authorizeRequests((requests) -> requests.anyRequest().authenticated());
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
return http.build();
|
return http.build();
|
||||||
@ -822,7 +816,7 @@ public class WebSecurityConfigurationTests {
|
|||||||
public SecurityFilterChain notAuthorized(HttpSecurity http) throws Exception {
|
public SecurityFilterChain notAuthorized(HttpSecurity http) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/user")))
|
.securityMatchers((requests) -> requests.requestMatchers(pathPattern("/user")))
|
||||||
.authorizeRequests((requests) -> requests.anyRequest().hasRole("USER"));
|
.authorizeRequests((requests) -> requests.anyRequest().hasRole("USER"));
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
return http.build();
|
return http.build();
|
||||||
@ -833,7 +827,7 @@ public class WebSecurityConfigurationTests {
|
|||||||
public SecurityFilterChain path1(HttpSecurity http) throws Exception {
|
public SecurityFilterChain path1(HttpSecurity http) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/admin")))
|
.securityMatchers((requests) -> requests.requestMatchers(pathPattern("/admin")))
|
||||||
.authorizeRequests((requests) -> requests.anyRequest().hasRole("ADMIN"));
|
.authorizeRequests((requests) -> requests.anyRequest().hasRole("ADMIN"));
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
return http.build();
|
return http.build();
|
||||||
@ -864,7 +858,7 @@ public class WebSecurityConfigurationTests {
|
|||||||
public SecurityFilterChain notAuthorized(HttpSecurity http) throws Exception {
|
public SecurityFilterChain notAuthorized(HttpSecurity http) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/user")))
|
.securityMatchers((requests) -> requests.requestMatchers(pathPattern("/user")))
|
||||||
.authorizeRequests((requests) -> requests.anyRequest().hasRole("USER"));
|
.authorizeRequests((requests) -> requests.anyRequest().hasRole("USER"));
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
return http.build();
|
return http.build();
|
||||||
@ -875,7 +869,7 @@ public class WebSecurityConfigurationTests {
|
|||||||
public SecurityFilterChain admin(HttpSecurity http) throws Exception {
|
public SecurityFilterChain admin(HttpSecurity http) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/admin")))
|
.securityMatchers((requests) -> requests.requestMatchers(pathPattern("/admin")))
|
||||||
.authorizeRequests((requests) -> requests.anyRequest().hasRole("ADMIN"));
|
.authorizeRequests((requests) -> requests.anyRequest().hasRole("ADMIN"));
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
return http.build();
|
return http.build();
|
||||||
@ -911,7 +905,7 @@ public class WebSecurityConfigurationTests {
|
|||||||
public SecurityFilterChain notAuthorized(HttpSecurity http) throws Exception {
|
public SecurityFilterChain notAuthorized(HttpSecurity http) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatchers((requests) -> requests.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/user")))
|
.securityMatchers((requests) -> requests.requestMatchers(pathPattern("/user")))
|
||||||
.authorizeHttpRequests((authorize) -> authorize.anyRequest().hasRole("USER"));
|
.authorizeHttpRequests((authorize) -> authorize.anyRequest().hasRole("USER"));
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
return http.build();
|
return http.build();
|
||||||
@ -922,7 +916,7 @@ public class WebSecurityConfigurationTests {
|
|||||||
public SecurityFilterChain admin(HttpSecurity http) throws Exception {
|
public SecurityFilterChain admin(HttpSecurity http) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatchers((requests) -> requests.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/admin")))
|
.securityMatchers((requests) -> requests.requestMatchers(pathPattern("/admin")))
|
||||||
.authorizeHttpRequests((authorize) -> authorize.anyRequest().hasRole("ADMIN"));
|
.authorizeHttpRequests((authorize) -> authorize.anyRequest().hasRole("ADMIN"));
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
return http.build();
|
return http.build();
|
||||||
|
@ -22,11 +22,12 @@ import org.junit.jupiter.api.BeforeEach;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
|
||||||
|
|
||||||
public class AbstractConfigAttributeRequestMatcherRegistryTests {
|
public class AbstractConfigAttributeRequestMatcherRegistryTests {
|
||||||
|
|
||||||
@ -55,19 +56,18 @@ public class AbstractConfigAttributeRequestMatcherRegistryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetRequestMatcherIsTypeAntPathRequestMatcher() {
|
public void testGetRequestMatcherIsTypePathPatternRequestMatcher() {
|
||||||
List<RequestMatcher> requestMatchers = this.registry
|
List<RequestMatcher> requestMatchers = this.registry.requestMatchers(pathPattern(HttpMethod.GET, "/a.*"));
|
||||||
.requestMatchers(new AntPathRequestMatcher("/a.*", HttpMethod.GET.name()));
|
|
||||||
for (RequestMatcher requestMatcher : requestMatchers) {
|
for (RequestMatcher requestMatcher : requestMatchers) {
|
||||||
assertThat(requestMatcher).isInstanceOf(AntPathRequestMatcher.class);
|
assertThat(requestMatcher).isInstanceOf(PathPatternRequestMatcher.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRequestMatcherIsTypeAntPathRequestMatcher() {
|
public void testRequestMatcherIsTypePathPatternRequestMatcher() {
|
||||||
List<RequestMatcher> requestMatchers = this.registry.requestMatchers(new AntPathRequestMatcher("/a.*"));
|
List<RequestMatcher> requestMatchers = this.registry.requestMatchers(pathPattern("/a.*"));
|
||||||
for (RequestMatcher requestMatcher : requestMatchers) {
|
for (RequestMatcher requestMatcher : requestMatchers) {
|
||||||
assertThat(requestMatcher).isInstanceOf(AntPathRequestMatcher.class);
|
assertThat(requestMatcher).isInstanceOf(PathPatternRequestMatcher.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,6 @@ import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
|||||||
import org.springframework.security.config.observation.SecurityObservationSettings;
|
import org.springframework.security.config.observation.SecurityObservationSettings;
|
||||||
import org.springframework.security.config.test.SpringTestContext;
|
import org.springframework.security.config.test.SpringTestContext;
|
||||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||||
import org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean;
|
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.authority.AuthorityUtils;
|
import org.springframework.security.core.authority.AuthorityUtils;
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
@ -68,7 +67,6 @@ import org.springframework.security.web.access.expression.WebExpressionAuthoriza
|
|||||||
import org.springframework.security.web.access.intercept.AuthorizationFilter;
|
import org.springframework.security.web.access.intercept.AuthorizationFilter;
|
||||||
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
|
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
|
||||||
import org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager;
|
import org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager;
|
||||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
|
||||||
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
@ -81,7 +79,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.servlet.DispatcherServlet;
|
import org.springframework.web.servlet.DispatcherServlet;
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
@ -148,7 +145,7 @@ public class AuthorizeHttpRequestsConfigurerTests {
|
|||||||
public void configureWhenMvcMatcherAfterAnyRequestThenException() {
|
public void configureWhenMvcMatcherAfterAnyRequestThenException() {
|
||||||
assertThatExceptionOfType(BeanCreationException.class)
|
assertThatExceptionOfType(BeanCreationException.class)
|
||||||
.isThrownBy(() -> this.spring.register(AfterAnyRequestConfig.class).autowire())
|
.isThrownBy(() -> this.spring.register(AfterAnyRequestConfig.class).autowire())
|
||||||
.withMessageContaining("Can't configure mvcMatchers after anyRequest");
|
.withMessageContaining("Can't configure requestMatchers after anyRequest");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -689,7 +686,7 @@ public class AuthorizeHttpRequestsConfigurerTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requestMatchersWhenMultipleDispatcherServletsAndPathBeanThenAllows() throws Exception {
|
public void requestMatchersWhenMultipleDispatcherServletsAndPathBeanThenAllows() throws Exception {
|
||||||
this.spring.register(MvcRequestMatcherBuilderConfig.class, BasicController.class)
|
this.spring.register(PathPatternRequestMatcherBuilderConfig.class, BasicController.class)
|
||||||
.postProcessor((context) -> context.getServletContext()
|
.postProcessor((context) -> context.getServletContext()
|
||||||
.addServlet("otherDispatcherServlet", DispatcherServlet.class)
|
.addServlet("otherDispatcherServlet", DispatcherServlet.class)
|
||||||
.addMapping("/mvc"))
|
.addMapping("/mvc"))
|
||||||
@ -1063,13 +1060,11 @@ public class AuthorizeHttpRequestsConfigurerTests {
|
|||||||
static class ServletPathConfig {
|
static class ServletPathConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector)
|
|
||||||
.servletPath("/spring");
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
return http
|
return http
|
||||||
.authorizeHttpRequests((authorize) -> authorize
|
.authorizeHttpRequests((authorize) -> authorize
|
||||||
.requestMatchers(mvcMatcherBuilder.pattern("/")).hasRole("ADMIN")
|
.requestMatchers(builder.basePath("/spring").matcher("/")).hasRole("ADMIN")
|
||||||
)
|
)
|
||||||
.build();
|
.build();
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
@ -1358,7 +1353,7 @@ public class AuthorizeHttpRequestsConfigurerTests {
|
|||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@EnableWebMvc
|
@EnableWebMvc
|
||||||
static class MvcRequestMatcherBuilderConfig {
|
static class PathPatternRequestMatcherBuilderConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityFilterChain security(HttpSecurity http) throws Exception {
|
SecurityFilterChain security(HttpSecurity http) throws Exception {
|
||||||
@ -1394,11 +1389,6 @@ public class AuthorizeHttpRequestsConfigurerTests {
|
|||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
PathPatternRequestMatcherBuilderFactoryBean pathPatternFactoryBean() {
|
|
||||||
return new PathPatternRequestMatcherBuilderFactoryBean();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@ -42,17 +42,17 @@ import org.springframework.security.web.FilterChainProxy;
|
|||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||||
import org.springframework.security.web.servlet.MockServletContext;
|
import org.springframework.security.web.servlet.MockServletContext;
|
||||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
import org.springframework.web.util.pattern.PathPatternParser;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
import static org.springframework.security.config.Customizer.withDefaults;
|
import static org.springframework.security.config.Customizer.withDefaults;
|
||||||
|
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
@ -126,11 +126,13 @@ public class AuthorizeRequestsTests {
|
|||||||
loadConfig(AntPatchersPathVariables.class);
|
loadConfig(AntPatchersPathVariables.class);
|
||||||
this.request.setRequestURI("/USER/user");
|
this.request.setRequestURI("/USER/user");
|
||||||
this.request.setServletPath("/USER/user");
|
this.request.setServletPath("/USER/user");
|
||||||
|
this.request.setRequestURI("/USER/user");
|
||||||
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
||||||
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
||||||
this.setup();
|
this.setup();
|
||||||
this.request.setRequestURI("/USER/deny");
|
this.request.setRequestURI("/USER/deny");
|
||||||
this.request.setServletPath("/USER/deny");
|
this.request.setServletPath("/USER/deny");
|
||||||
|
this.request.setRequestURI("/USER/deny");
|
||||||
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
||||||
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
|
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
|
||||||
}
|
}
|
||||||
@ -204,7 +206,7 @@ public class AuthorizeRequestsTests {
|
|||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.authorizeRequests((requests) -> requests
|
.authorizeRequests((requests) -> requests
|
||||||
.requestMatchers(new AntPathRequestMatcher("/**", HttpMethod.POST.name())).denyAll());
|
.requestMatchers(pathPattern(HttpMethod.POST, "/**")).denyAll());
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
@ -225,7 +227,7 @@ public class AuthorizeRequestsTests {
|
|||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.authorizeRequests((authorize) -> authorize
|
.authorizeRequests((authorize) -> authorize
|
||||||
.requestMatchers(new AntPathRequestMatcher("/**", HttpMethod.POST.name())).denyAll()
|
.requestMatchers(pathPattern(HttpMethod.POST, "/**")).denyAll()
|
||||||
);
|
);
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
return http.build();
|
return http.build();
|
||||||
@ -244,10 +246,13 @@ public class AuthorizeRequestsTests {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
|
PathPatternParser parser = new PathPatternParser();
|
||||||
|
parser.setCaseSensitive(false);
|
||||||
|
PathPatternRequestMatcher.Builder builder = PathPatternRequestMatcher.withPathPatternParser(parser);
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.authorizeRequests((requests) -> requests
|
.authorizeRequests((requests) -> requests
|
||||||
.requestMatchers(new AntPathRequestMatcher("/user/{user}", null, false)).access("#user == 'user'")
|
.requestMatchers(builder.matcher("/user/{user}")).access("#user == 'user'")
|
||||||
.anyRequest().denyAll());
|
.anyRequest().denyAll());
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
return http.build();
|
return http.build();
|
||||||
@ -266,10 +271,13 @@ public class AuthorizeRequestsTests {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
|
PathPatternParser parser = new PathPatternParser();
|
||||||
|
parser.setCaseSensitive(false);
|
||||||
|
PathPatternRequestMatcher.Builder builder = PathPatternRequestMatcher.withPathPatternParser(parser);
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.authorizeRequests((requests) -> requests
|
.authorizeRequests((requests) -> requests
|
||||||
.requestMatchers(new AntPathRequestMatcher("/user/{userName}", null, false)).access("#userName == 'user'")
|
.requestMatchers(builder.matcher("/user/{userName}")).access("#userName == 'user'")
|
||||||
.anyRequest().denyAll());
|
.anyRequest().denyAll());
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
return http.build();
|
return http.build();
|
||||||
@ -383,14 +391,13 @@ public class AuthorizeRequestsTests {
|
|||||||
static class MvcMatcherServletPathConfig {
|
static class MvcMatcherServletPathConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector)
|
PathPatternRequestMatcher.Builder spring = builder.basePath("/spring");
|
||||||
.servletPath("/spring");
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.httpBasic(withDefaults())
|
.httpBasic(withDefaults())
|
||||||
.authorizeRequests((requests) -> requests
|
.authorizeRequests((requests) -> requests
|
||||||
.requestMatchers(mvcMatcherBuilder.pattern("/path")).denyAll());
|
.requestMatchers(spring.matcher("/path")).denyAll());
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
@ -418,14 +425,13 @@ public class AuthorizeRequestsTests {
|
|||||||
static class MvcMatcherServletPathInLambdaConfig {
|
static class MvcMatcherServletPathInLambdaConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector)
|
PathPatternRequestMatcher.Builder spring = builder.basePath("/spring");
|
||||||
.servletPath("/spring");
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.httpBasic(withDefaults())
|
.httpBasic(withDefaults())
|
||||||
.authorizeRequests((authorize) -> authorize
|
.authorizeRequests((authorize) -> authorize
|
||||||
.requestMatchers(mvcMatcherBuilder.pattern("/path")).denyAll()
|
.requestMatchers(spring.matcher("/path")).denyAll()
|
||||||
);
|
);
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
return http.build();
|
return http.build();
|
||||||
|
@ -28,13 +28,13 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
|
|||||||
import org.springframework.security.config.test.SpringTestContext;
|
import org.springframework.security.config.test.SpringTestContext;
|
||||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
|
|
||||||
|
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
||||||
@ -109,7 +109,7 @@ public class CsrfConfigurerIgnoringRequestMatchersTests {
|
|||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.csrf((csrf) -> csrf
|
.csrf((csrf) -> csrf
|
||||||
.requireCsrfProtectionMatcher(new AntPathRequestMatcher("/path"))
|
.requireCsrfProtectionMatcher(pathPattern("/path"))
|
||||||
.ignoringRequestMatchers(this.requestMatcher));
|
.ignoringRequestMatchers(this.requestMatcher));
|
||||||
return http.build();
|
return http.build();
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
@ -129,7 +129,7 @@ public class CsrfConfigurerIgnoringRequestMatchersTests {
|
|||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.csrf((csrf) -> csrf
|
.csrf((csrf) -> csrf
|
||||||
.requireCsrfProtectionMatcher(new AntPathRequestMatcher("/path"))
|
.requireCsrfProtectionMatcher(pathPattern("/path"))
|
||||||
.ignoringRequestMatchers(this.requestMatcher)
|
.ignoringRequestMatchers(this.requestMatcher)
|
||||||
);
|
);
|
||||||
return http.build();
|
return http.build();
|
||||||
@ -149,7 +149,7 @@ public class CsrfConfigurerIgnoringRequestMatchersTests {
|
|||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.csrf((csrf) -> csrf
|
.csrf((csrf) -> csrf
|
||||||
.ignoringRequestMatchers(new AntPathRequestMatcher("/no-csrf"))
|
.ignoringRequestMatchers(pathPattern("/no-csrf"))
|
||||||
.ignoringRequestMatchers(this.requestMatcher));
|
.ignoringRequestMatchers(this.requestMatcher));
|
||||||
return http.build();
|
return http.build();
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
@ -169,7 +169,7 @@ public class CsrfConfigurerIgnoringRequestMatchersTests {
|
|||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.csrf((csrf) -> csrf
|
.csrf((csrf) -> csrf
|
||||||
.ignoringRequestMatchers(new AntPathRequestMatcher("/no-csrf"))
|
.ignoringRequestMatchers(pathPattern("/no-csrf"))
|
||||||
.ignoringRequestMatchers(this.requestMatcher)
|
.ignoringRequestMatchers(this.requestMatcher)
|
||||||
);
|
);
|
||||||
return http.build();
|
return http.build();
|
||||||
|
@ -57,7 +57,6 @@ import org.springframework.security.web.csrf.XorCsrfTokenRequestAttributeHandler
|
|||||||
import org.springframework.security.web.firewall.StrictHttpFirewall;
|
import org.springframework.security.web.firewall.StrictHttpFirewall;
|
||||||
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
|
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
|
||||||
import org.springframework.security.web.savedrequest.RequestCache;
|
import org.springframework.security.web.savedrequest.RequestCache;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.test.web.servlet.MvcResult;
|
import org.springframework.test.web.servlet.MvcResult;
|
||||||
@ -84,6 +83,7 @@ import static org.springframework.security.test.web.servlet.request.SecurityMock
|
|||||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
|
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
|
||||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
|
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
|
||||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated;
|
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated;
|
||||||
|
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.head;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.head;
|
||||||
@ -906,7 +906,7 @@ public class CsrfConfigurerTests {
|
|||||||
http
|
http
|
||||||
.formLogin(withDefaults())
|
.formLogin(withDefaults())
|
||||||
.logout((logout) -> logout
|
.logout((logout) -> logout
|
||||||
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")));
|
.logoutRequestMatcher(pathPattern("/logout")));
|
||||||
return http.build();
|
return http.build();
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
@ -128,8 +128,7 @@ public class DefaultFiltersTests {
|
|||||||
public void defaultFiltersPermitAll() throws IOException, ServletException {
|
public void defaultFiltersPermitAll() throws IOException, ServletException {
|
||||||
this.spring.register(DefaultFiltersConfigPermitAll.class, UserDetailsServiceConfig.class);
|
this.spring.register(DefaultFiltersConfigPermitAll.class, UserDetailsServiceConfig.class);
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", "");
|
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout");
|
||||||
request.setServletPath("/logout");
|
|
||||||
CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN");
|
CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN");
|
||||||
CsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
|
CsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
|
||||||
repository.saveToken(csrfToken, request, response);
|
repository.saveToken(csrfToken, request, response);
|
||||||
|
@ -32,11 +32,11 @@ import org.springframework.security.test.context.support.WithMockUser;
|
|||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||||
import org.springframework.security.web.access.AccessDeniedHandlerImpl;
|
import org.springframework.security.web.access.AccessDeniedHandlerImpl;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
|
||||||
|
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ public class ExceptionHandlingConfigurerAccessDeniedHandlerTests {
|
|||||||
.exceptionHandling((handling) -> handling
|
.exceptionHandling((handling) -> handling
|
||||||
.defaultAccessDeniedHandlerFor(
|
.defaultAccessDeniedHandlerFor(
|
||||||
this.teapotDeniedHandler,
|
this.teapotDeniedHandler,
|
||||||
new AntPathRequestMatcher("/hello/**"))
|
pathPattern("/hello/**"))
|
||||||
.defaultAccessDeniedHandlerFor(
|
.defaultAccessDeniedHandlerFor(
|
||||||
new AccessDeniedHandlerImpl(),
|
new AccessDeniedHandlerImpl(),
|
||||||
AnyRequestMatcher.INSTANCE));
|
AnyRequestMatcher.INSTANCE));
|
||||||
@ -119,7 +119,7 @@ public class ExceptionHandlingConfigurerAccessDeniedHandlerTests {
|
|||||||
.exceptionHandling((exceptionHandling) -> exceptionHandling
|
.exceptionHandling((exceptionHandling) -> exceptionHandling
|
||||||
.defaultAccessDeniedHandlerFor(
|
.defaultAccessDeniedHandlerFor(
|
||||||
this.teapotDeniedHandler,
|
this.teapotDeniedHandler,
|
||||||
new AntPathRequestMatcher("/hello/**")
|
pathPattern("/hello/**")
|
||||||
)
|
)
|
||||||
.defaultAccessDeniedHandlerFor(
|
.defaultAccessDeniedHandlerFor(
|
||||||
new AccessDeniedHandlerImpl(),
|
new AccessDeniedHandlerImpl(),
|
||||||
@ -148,7 +148,7 @@ public class ExceptionHandlingConfigurerAccessDeniedHandlerTests {
|
|||||||
.exceptionHandling((handling) -> handling
|
.exceptionHandling((handling) -> handling
|
||||||
.defaultAccessDeniedHandlerFor(
|
.defaultAccessDeniedHandlerFor(
|
||||||
this.teapotDeniedHandler,
|
this.teapotDeniedHandler,
|
||||||
new AntPathRequestMatcher("/hello/**")));
|
pathPattern("/hello/**")));
|
||||||
return http.build();
|
return http.build();
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
@ -36,12 +36,11 @@ import org.springframework.security.core.userdetails.UserDetailsService;
|
|||||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||||
import org.springframework.security.web.FilterChainProxy;
|
import org.springframework.security.web.FilterChainProxy;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.springframework.security.config.Customizer.withDefaults;
|
import static org.springframework.security.config.Customizer.withDefaults;
|
||||||
@ -160,14 +159,13 @@ public class HttpSecurityRequestMatchersTests {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||||
SecurityFilterChain first(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
SecurityFilterChain first(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector);
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatchers((requests) -> requests
|
.securityMatchers((requests) -> requests
|
||||||
.requestMatchers(mvcMatcherBuilder.pattern("/test-1"))
|
.requestMatchers(builder.matcher("/test-1"))
|
||||||
.requestMatchers(mvcMatcherBuilder.pattern("/test-2"))
|
.requestMatchers(builder.matcher("/test-2"))
|
||||||
.requestMatchers(mvcMatcherBuilder.pattern("/test-3"))
|
.requestMatchers(builder.matcher("/test-3"))
|
||||||
)
|
)
|
||||||
.authorizeRequests((authorize) -> authorize.anyRequest().denyAll())
|
.authorizeRequests((authorize) -> authorize.anyRequest().denyAll())
|
||||||
.httpBasic(withDefaults());
|
.httpBasic(withDefaults());
|
||||||
@ -176,12 +174,11 @@ public class HttpSecurityRequestMatchersTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityFilterChain second(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
SecurityFilterChain second(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector);
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatchers((requests) -> requests
|
.securityMatchers((requests) -> requests
|
||||||
.requestMatchers(mvcMatcherBuilder.pattern("/test-1"))
|
.requestMatchers(builder.matcher("/test-1"))
|
||||||
)
|
)
|
||||||
.authorizeRequests((authorize) -> authorize
|
.authorizeRequests((authorize) -> authorize
|
||||||
.anyRequest().permitAll()
|
.anyRequest().permitAll()
|
||||||
@ -209,14 +206,13 @@ public class HttpSecurityRequestMatchersTests {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||||
SecurityFilterChain first(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
SecurityFilterChain first(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector);
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatchers((security) -> security
|
.securityMatchers((security) -> security
|
||||||
.requestMatchers(mvcMatcherBuilder.pattern("/test-1"))
|
.requestMatchers(builder.matcher("/test-1"))
|
||||||
.requestMatchers(mvcMatcherBuilder.pattern("/test-2"))
|
.requestMatchers(builder.matcher("/test-2"))
|
||||||
.requestMatchers(mvcMatcherBuilder.pattern("/test-3")))
|
.requestMatchers(builder.matcher("/test-3")))
|
||||||
.authorizeRequests((requests) -> requests
|
.authorizeRequests((requests) -> requests
|
||||||
.anyRequest().denyAll())
|
.anyRequest().denyAll())
|
||||||
.httpBasic(withDefaults());
|
.httpBasic(withDefaults());
|
||||||
@ -225,12 +221,11 @@ public class HttpSecurityRequestMatchersTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityFilterChain second(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
SecurityFilterChain second(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector);
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatchers((security) -> security
|
.securityMatchers((security) -> security
|
||||||
.requestMatchers(mvcMatcherBuilder.pattern("/test-1")))
|
.requestMatchers(builder.matcher("/test-1")))
|
||||||
.authorizeRequests((requests) -> requests
|
.authorizeRequests((requests) -> requests
|
||||||
.anyRequest().permitAll());
|
.anyRequest().permitAll());
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
@ -255,10 +250,10 @@ public class HttpSecurityRequestMatchersTests {
|
|||||||
static class MvcMatcherConfig {
|
static class MvcMatcherConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatcher(new MvcRequestMatcher(introspector, "/path"))
|
.securityMatcher(builder.matcher("/path"))
|
||||||
.httpBasic(withDefaults())
|
.httpBasic(withDefaults())
|
||||||
.authorizeRequests((requests) -> requests
|
.authorizeRequests((requests) -> requests
|
||||||
.anyRequest().denyAll());
|
.anyRequest().denyAll());
|
||||||
@ -289,11 +284,11 @@ public class HttpSecurityRequestMatchersTests {
|
|||||||
static class RequestMatchersMvcMatcherConfig {
|
static class RequestMatchersMvcMatcherConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatchers((security) -> security
|
.securityMatchers((security) -> security
|
||||||
.requestMatchers(new MvcRequestMatcher(introspector, "/path")))
|
.requestMatchers(builder.matcher("/path")))
|
||||||
.httpBasic(withDefaults())
|
.httpBasic(withDefaults())
|
||||||
.authorizeRequests((requests) -> requests
|
.authorizeRequests((requests) -> requests
|
||||||
.anyRequest().denyAll());
|
.anyRequest().denyAll());
|
||||||
@ -324,11 +319,11 @@ public class HttpSecurityRequestMatchersTests {
|
|||||||
static class RequestMatchersMvcMatcherInLambdaConfig {
|
static class RequestMatchersMvcMatcherInLambdaConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatchers((secure) -> secure
|
.securityMatchers((secure) -> secure
|
||||||
.requestMatchers(new MvcRequestMatcher(introspector, "/path"))
|
.requestMatchers(builder.matcher("/path"))
|
||||||
)
|
)
|
||||||
.httpBasic(withDefaults())
|
.httpBasic(withDefaults())
|
||||||
.authorizeRequests((authorize) -> authorize
|
.authorizeRequests((authorize) -> authorize
|
||||||
@ -356,13 +351,11 @@ public class HttpSecurityRequestMatchersTests {
|
|||||||
static class RequestMatchersMvcMatcherServeltPathConfig {
|
static class RequestMatchersMvcMatcherServeltPathConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector);
|
|
||||||
mvcMatcherBuilder.servletPath("/spring");
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatchers((security) -> security
|
.securityMatchers((security) -> security
|
||||||
.requestMatchers(mvcMatcherBuilder.pattern("/path"))
|
.requestMatchers(builder.basePath("/spring").matcher("/path"))
|
||||||
.requestMatchers("/never-match"))
|
.requestMatchers("/never-match"))
|
||||||
.httpBasic(withDefaults())
|
.httpBasic(withDefaults())
|
||||||
.authorizeRequests((requests) -> requests
|
.authorizeRequests((requests) -> requests
|
||||||
@ -394,13 +387,11 @@ public class HttpSecurityRequestMatchersTests {
|
|||||||
static class RequestMatchersMvcMatcherServletPathInLambdaConfig {
|
static class RequestMatchersMvcMatcherServletPathInLambdaConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector);
|
|
||||||
mvcMatcherBuilder.servletPath("/spring");
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatchers((secure) -> secure
|
.securityMatchers((secure) -> secure
|
||||||
.requestMatchers(mvcMatcherBuilder.pattern("/path"))
|
.requestMatchers(builder.basePath("/spring").matcher("/path"))
|
||||||
.requestMatchers("/never-match")
|
.requestMatchers("/never-match")
|
||||||
)
|
)
|
||||||
.httpBasic(withDefaults())
|
.httpBasic(withDefaults())
|
||||||
|
@ -37,7 +37,7 @@ import org.springframework.security.test.support.ClassPathExclusions;
|
|||||||
import org.springframework.security.web.DefaultSecurityFilterChain;
|
import org.springframework.security.web.DefaultSecurityFilterChain;
|
||||||
import org.springframework.security.web.FilterChainProxy;
|
import org.springframework.security.web.FilterChainProxy;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
import org.springframework.test.util.ReflectionTestUtils;
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
@ -101,7 +101,7 @@ public class HttpSecuritySecurityMatchersNoMvcTests {
|
|||||||
.findFirst()
|
.findFirst()
|
||||||
.get();
|
.get();
|
||||||
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
||||||
assertThat(requestMatchers).hasOnlyElementsOfType(AntPathRequestMatcher.class);
|
assertThat(requestMatchers).hasOnlyElementsOfType(PathPatternRequestMatcher.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadConfig(Class<?>... configs) {
|
public void loadConfig(Class<?>... configs) {
|
||||||
|
@ -39,12 +39,11 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
|||||||
import org.springframework.security.web.FilterChainProxy;
|
import org.springframework.security.web.FilterChainProxy;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.servlet.MockServletContext;
|
import org.springframework.security.web.servlet.MockServletContext;
|
||||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.springframework.security.config.Customizer.withDefaults;
|
import static org.springframework.security.config.Customizer.withDefaults;
|
||||||
@ -356,14 +355,13 @@ public class HttpSecuritySecurityMatchersTests {
|
|||||||
static class SecurityMatchersMvcMatcherServletPathConfig {
|
static class SecurityMatchersMvcMatcherServletPathConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityFilterChain appSecurity(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
SecurityFilterChain appSecurity(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector)
|
PathPatternRequestMatcher.Builder spring = builder.basePath("/spring");
|
||||||
.servletPath("/spring");
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatchers((security) -> security
|
.securityMatchers((security) -> security
|
||||||
.requestMatchers(mvcMatcherBuilder.pattern("/path"))
|
.requestMatchers(spring.matcher("/path"))
|
||||||
.requestMatchers(mvcMatcherBuilder.pattern("/never-match"))
|
.requestMatchers(spring.matcher("/never-match"))
|
||||||
)
|
)
|
||||||
.httpBasic(withDefaults())
|
.httpBasic(withDefaults())
|
||||||
.authorizeHttpRequests((authorize) -> authorize
|
.authorizeHttpRequests((authorize) -> authorize
|
||||||
@ -391,14 +389,13 @@ public class HttpSecuritySecurityMatchersTests {
|
|||||||
static class SecurityMatchersMvcMatcherServletPathInLambdaConfig {
|
static class SecurityMatchersMvcMatcherServletPathInLambdaConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityFilterChain appSecurity(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
SecurityFilterChain appSecurity(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector)
|
PathPatternRequestMatcher.Builder spring = builder.basePath("/spring");
|
||||||
.servletPath("/spring");
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatchers((matchers) -> matchers
|
.securityMatchers((matchers) -> matchers
|
||||||
.requestMatchers(mvcMatcherBuilder.pattern("/path"))
|
.requestMatchers(spring.matcher("/path"))
|
||||||
.requestMatchers(mvcMatcherBuilder.pattern("/never-match"))
|
.requestMatchers(spring.matcher("/never-match"))
|
||||||
)
|
)
|
||||||
.httpBasic(withDefaults())
|
.httpBasic(withDefaults())
|
||||||
.authorizeHttpRequests((authorize) -> authorize
|
.authorizeHttpRequests((authorize) -> authorize
|
||||||
|
@ -126,11 +126,6 @@ public class HttpsRedirectConfigurerTests {
|
|||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
PathPatternRequestMatcherBuilderFactoryBean requestMatcherBuilder() {
|
|
||||||
return new PathPatternRequestMatcherBuilderFactoryBean();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@ -43,7 +43,6 @@ import org.springframework.security.web.authentication.RememberMeServices;
|
|||||||
import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices;
|
import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices;
|
||||||
import org.springframework.security.web.authentication.rememberme.PersistentRememberMeToken;
|
import org.springframework.security.web.authentication.rememberme.PersistentRememberMeToken;
|
||||||
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
|
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.test.web.servlet.MvcResult;
|
import org.springframework.test.web.servlet.MvcResult;
|
||||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||||
@ -349,7 +348,7 @@ public class NamespaceRememberMeTests {
|
|||||||
SecurityFilterChain withoutKeyFilterChain(HttpSecurity http) throws Exception {
|
SecurityFilterChain withoutKeyFilterChain(HttpSecurity http) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatcher(new AntPathRequestMatcher("/without-key/**"))
|
.securityMatcher("/without-key/**")
|
||||||
.authorizeHttpRequests((authorize) -> authorize.anyRequest().authenticated())
|
.authorizeHttpRequests((authorize) -> authorize.anyRequest().authenticated())
|
||||||
.formLogin((login) -> login
|
.formLogin((login) -> login
|
||||||
.loginProcessingUrl("/without-key/login"))
|
.loginProcessingUrl("/without-key/login"))
|
||||||
|
@ -34,7 +34,6 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
|||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.test.SpringTestContext;
|
import org.springframework.security.config.test.SpringTestContext;
|
||||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||||
import org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean;
|
|
||||||
import org.springframework.security.core.userdetails.User;
|
import org.springframework.security.core.userdetails.User;
|
||||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||||
import org.springframework.security.test.web.servlet.RequestCacheResultMatcher;
|
import org.springframework.security.test.web.servlet.RequestCacheResultMatcher;
|
||||||
@ -502,11 +501,6 @@ public class RequestCacheConfigurerTests {
|
|||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
static class PathPatternFactoryBeanConfig {
|
static class PathPatternFactoryBeanConfig {
|
||||||
|
|
||||||
@Bean
|
|
||||||
PathPatternRequestMatcherBuilderFactoryBean factoryBean() {
|
|
||||||
return new PathPatternRequestMatcherBuilderFactoryBean();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,9 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
|
|||||||
import org.springframework.security.config.test.SpringTestContext;
|
import org.springframework.security.config.test.SpringTestContext;
|
||||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
|
||||||
|
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
@ -79,9 +79,9 @@ public class RequestMatcherConfigurerTests {
|
|||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatchers((security) -> security
|
.securityMatchers((security) -> security
|
||||||
.requestMatchers(new AntPathRequestMatcher("/api/**")))
|
.requestMatchers(pathPattern("/api/**")))
|
||||||
.securityMatchers((security) -> security
|
.securityMatchers((security) -> security
|
||||||
.requestMatchers(new AntPathRequestMatcher("/oauth/**")))
|
.requestMatchers(pathPattern("/oauth/**")))
|
||||||
.authorizeRequests((requests) -> requests
|
.authorizeRequests((requests) -> requests
|
||||||
.anyRequest().denyAll());
|
.anyRequest().denyAll());
|
||||||
return http.build();
|
return http.build();
|
||||||
@ -99,10 +99,10 @@ public class RequestMatcherConfigurerTests {
|
|||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.securityMatchers((secure) -> secure
|
.securityMatchers((secure) -> secure
|
||||||
.requestMatchers(new AntPathRequestMatcher("/api/**"))
|
.requestMatchers(pathPattern("/api/**"))
|
||||||
)
|
)
|
||||||
.securityMatchers((securityMatchers) -> securityMatchers
|
.securityMatchers((securityMatchers) -> securityMatchers
|
||||||
.requestMatchers(new AntPathRequestMatcher("/oauth/**"))
|
.requestMatchers(pathPattern("/oauth/**"))
|
||||||
)
|
)
|
||||||
.authorizeRequests((authorize) -> authorize
|
.authorizeRequests((authorize) -> authorize
|
||||||
.anyRequest().denyAll()
|
.anyRequest().denyAll()
|
||||||
|
@ -41,12 +41,11 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
|||||||
import org.springframework.security.web.FilterChainProxy;
|
import org.springframework.security.web.FilterChainProxy;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.servlet.MockServletContext;
|
import org.springframework.security.web.servlet.MockServletContext;
|
||||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.springframework.security.config.Customizer.withDefaults;
|
import static org.springframework.security.config.Customizer.withDefaults;
|
||||||
@ -133,12 +132,12 @@ public class UrlAuthorizationConfigurerTests {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityFilterChain filterChain(HttpSecurity http, ApplicationContext context,
|
SecurityFilterChain filterChain(HttpSecurity http, ApplicationContext context,
|
||||||
HandlerMappingIntrospector introspector) throws Exception {
|
PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.httpBasic(withDefaults())
|
.httpBasic(withDefaults())
|
||||||
.apply(new UrlAuthorizationConfigurer(context)).getRegistry()
|
.apply(new UrlAuthorizationConfigurer(context)).getRegistry()
|
||||||
.requestMatchers(new MvcRequestMatcher(introspector, "/path")).hasRole("ADMIN");
|
.requestMatchers(builder.matcher("/path")).hasRole("ADMIN");
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
@ -167,14 +166,13 @@ public class UrlAuthorizationConfigurerTests {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityFilterChain filterChain(HttpSecurity http, ApplicationContext context,
|
SecurityFilterChain filterChain(HttpSecurity http, ApplicationContext context,
|
||||||
HandlerMappingIntrospector introspector) throws Exception {
|
PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||||
MvcRequestMatcher mvcRequestMatcher = new MvcRequestMatcher(introspector, "/path");
|
PathPatternRequestMatcher.Builder spring = builder.basePath("/spring");
|
||||||
mvcRequestMatcher.setServletPath("/spring");
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.httpBasic(withDefaults())
|
.httpBasic(withDefaults())
|
||||||
.apply(new UrlAuthorizationConfigurer(context)).getRegistry()
|
.apply(new UrlAuthorizationConfigurer(context)).getRegistry()
|
||||||
.requestMatchers(mvcRequestMatcher).hasRole("ADMIN");
|
.requestMatchers(builder.matcher("/path")).hasRole("ADMIN");
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
|
@ -53,12 +53,4 @@ class WebMvcSecurityConfigurationRuntimeHintsTests {
|
|||||||
.withMemberCategory(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)).accepts(this.hints);
|
.withMemberCategory(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)).accepts(this.hints);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
void handlerMappingIntrospectorCacheFilterFactoryBeanHasHints() {
|
|
||||||
assertThat(RuntimeHintsPredicates.reflection()
|
|
||||||
.onType(TypeReference
|
|
||||||
.of("org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$HandlerMappingIntrospectorCacheFilterFactoryBean"))
|
|
||||||
.withMemberCategory(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)).accepts(this.hints);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ import org.springframework.security.web.access.intercept.FilterInvocationSecurit
|
|||||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
||||||
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
|
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
|
||||||
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
|
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||||
import org.springframework.test.util.ReflectionTestUtils;
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
|
|
||||||
@ -144,12 +144,13 @@ public class DefaultFilterChainValidatorTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void validateWhenSameRequestMatchersArePresentThenUnreachableFilterChainException() {
|
void validateWhenSameRequestMatchersArePresentThenUnreachableFilterChainException() {
|
||||||
|
PathPatternRequestMatcher.Builder builder = PathPatternRequestMatcher.withDefaults();
|
||||||
AnonymousAuthenticationFilter authenticationFilter = mock(AnonymousAuthenticationFilter.class);
|
AnonymousAuthenticationFilter authenticationFilter = mock(AnonymousAuthenticationFilter.class);
|
||||||
ExceptionTranslationFilter exceptionTranslationFilter = mock(ExceptionTranslationFilter.class);
|
ExceptionTranslationFilter exceptionTranslationFilter = mock(ExceptionTranslationFilter.class);
|
||||||
SecurityFilterChain chain1 = new DefaultSecurityFilterChain(AntPathRequestMatcher.antMatcher("/api"),
|
SecurityFilterChain chain1 = new DefaultSecurityFilterChain(builder.matcher("/api"), authenticationFilter,
|
||||||
authenticationFilter, exceptionTranslationFilter, this.authorizationInterceptor);
|
exceptionTranslationFilter, this.authorizationInterceptor);
|
||||||
SecurityFilterChain chain2 = new DefaultSecurityFilterChain(AntPathRequestMatcher.antMatcher("/api"),
|
SecurityFilterChain chain2 = new DefaultSecurityFilterChain(builder.matcher("/api"), authenticationFilter,
|
||||||
authenticationFilter, exceptionTranslationFilter, this.authorizationInterceptor);
|
exceptionTranslationFilter, this.authorizationInterceptor);
|
||||||
List<SecurityFilterChain> chains = new ArrayList<>();
|
List<SecurityFilterChain> chains = new ArrayList<>();
|
||||||
chains.add(chain2);
|
chains.add(chain2);
|
||||||
chains.add(chain1);
|
chains.add(chain1);
|
||||||
|
@ -92,12 +92,10 @@ public class FilterSecurityMetadataSourceBeanDefinitionParserTests {
|
|||||||
public void interceptUrlsSupportPropertyPlaceholders() {
|
public void interceptUrlsSupportPropertyPlaceholders() {
|
||||||
System.setProperty("secure.url", "/secure");
|
System.setProperty("secure.url", "/secure");
|
||||||
System.setProperty("secure.role", "ROLE_A");
|
System.setProperty("secure.role", "ROLE_A");
|
||||||
setContext(
|
setContext("<b:bean class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer'/>"
|
||||||
"<b:bean class=\"org.springframework.web.servlet.handler.HandlerMappingIntrospector\" name=\"mvcHandlerMappingIntrospector\"/>"
|
+ "<filter-security-metadata-source id='fids' use-expressions='false'>"
|
||||||
+ "<b:bean class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer'/>"
|
+ " <intercept-url pattern='${secure.url}' access='${secure.role}'/>"
|
||||||
+ "<filter-security-metadata-source id='fids' use-expressions='false'>"
|
+ "</filter-security-metadata-source>");
|
||||||
+ " <intercept-url pattern='${secure.url}' access='${secure.role}'/>"
|
|
||||||
+ "</filter-security-metadata-source>");
|
|
||||||
DefaultFilterInvocationSecurityMetadataSource fids = (DefaultFilterInvocationSecurityMetadataSource) this.appContext
|
DefaultFilterInvocationSecurityMetadataSource fids = (DefaultFilterInvocationSecurityMetadataSource) this.appContext
|
||||||
.getBean("fids");
|
.getBean("fids");
|
||||||
Collection<ConfigAttribute> cad = fids.getAttributes(createFilterInvocation("/secure", "GET"));
|
Collection<ConfigAttribute> cad = fids.getAttributes(createFilterInvocation("/secure", "GET"));
|
||||||
@ -107,8 +105,7 @@ public class FilterSecurityMetadataSourceBeanDefinitionParserTests {
|
|||||||
@Test
|
@Test
|
||||||
public void parsingWithinFilterSecurityInterceptorIsSuccessful() {
|
public void parsingWithinFilterSecurityInterceptorIsSuccessful() {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
setContext("<b:bean class=\"org.springframework.web.servlet.handler.HandlerMappingIntrospector\" name=\"mvcHandlerMappingIntrospector\"/>" +
|
setContext("<http auto-config='true' use-expressions='false' use-authorization-manager='false'/>"
|
||||||
"<http auto-config='true' use-expressions='false' use-authorization-manager='false'/>"
|
|
||||||
+ "<b:bean id='fsi' class='org.springframework.security.web.access.intercept.FilterSecurityInterceptor' autowire='byType'>"
|
+ "<b:bean id='fsi' class='org.springframework.security.web.access.intercept.FilterSecurityInterceptor' autowire='byType'>"
|
||||||
+ " <b:property name='securityMetadataSource'>"
|
+ " <b:property name='securityMetadataSource'>"
|
||||||
+ " <filter-security-metadata-source use-expressions='false'>"
|
+ " <filter-security-metadata-source use-expressions='false'>"
|
||||||
|
@ -72,7 +72,7 @@ public class FormLoginConfigTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getProtectedPageWhenFormLoginConfiguredThenRedirectsToDefaultLoginPage() throws Exception {
|
public void getProtectedPageWhenFormLoginConfiguredThenRedirectsToDefaultLoginPage() throws Exception {
|
||||||
this.spring.configLocations(this.xml("WithAntRequestMatcher")).autowire();
|
this.spring.configLocations(this.xml("WithRequestMatcher")).autowire();
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
this.mvc.perform(get("/"))
|
this.mvc.perform(get("/"))
|
||||||
.andExpect(redirectedUrl("http://localhost/login"));
|
.andExpect(redirectedUrl("http://localhost/login"));
|
||||||
|
@ -25,7 +25,6 @@ import org.junit.jupiter.api.Test;
|
|||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.stubbing.Answer;
|
import org.mockito.stubbing.Answer;
|
||||||
|
|
||||||
import org.springframework.beans.factory.BeanCreationException;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
||||||
import org.springframework.mock.web.MockServletContext;
|
import org.springframework.mock.web.MockServletContext;
|
||||||
@ -38,7 +37,6 @@ import org.springframework.web.bind.annotation.GetMapping;
|
|||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.context.ConfigurableWebApplicationContext;
|
|
||||||
import org.springframework.web.util.WebUtils;
|
import org.springframework.web.util.WebUtils;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@ -250,21 +248,6 @@ public class InterceptUrlConfigTests {
|
|||||||
assertThat(this.spring.getContext().getBean(AuthorizationManager.class)).isNotNull();
|
assertThat(this.spring.getContext().getBean(AuthorizationManager.class)).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void requestWhenUsingMvcMatchersThenAuthorizesRequestsAccordingly() throws Exception {
|
|
||||||
this.spring.configLocations(this.xml("MvcMatchers")).autowire();
|
|
||||||
this.mvc.perform(get("/path")).andExpect(status().isUnauthorized());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void requestWhenUsingMvcMatchersAndAuthorizationManagerThenAuthorizesRequestsAccordingly() throws Exception {
|
|
||||||
this.spring.configLocations(this.xml("MvcMatchersAuthorizationManager")).autowire();
|
|
||||||
this.mvc.perform(get("/path")).andExpect(status().isUnauthorized());
|
|
||||||
this.mvc.perform(get("/path.html")).andExpect(status().isUnauthorized());
|
|
||||||
this.mvc.perform(get("/path/")).andExpect(status().isUnauthorized());
|
|
||||||
assertThat(this.spring.getContext().getBean(AuthorizationManager.class)).isNotNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requestWhenUsingMvcMatchersAndPathVariablesThenAuthorizesRequestsAccordingly() throws Exception {
|
public void requestWhenUsingMvcMatchersAndPathVariablesThenAuthorizesRequestsAccordingly() throws Exception {
|
||||||
this.spring.configLocations(this.xml("MvcMatchersPathVariables")).autowire();
|
this.spring.configLocations(this.xml("MvcMatchersPathVariables")).autowire();
|
||||||
@ -293,48 +276,6 @@ public class InterceptUrlConfigTests {
|
|||||||
assertThat(this.spring.getContext().getBean(AuthorizationManager.class)).isNotNull();
|
assertThat(this.spring.getContext().getBean(AuthorizationManager.class)).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void requestWhenUsingMvcMatchersAndServletPathThenAuthorizesRequestsAccordingly() throws Exception {
|
|
||||||
this.spring.configLocations(this.xml("MvcMatchersServletPath")).autowire();
|
|
||||||
MockServletContext servletContext = mockServletContext("/spring");
|
|
||||||
ConfigurableWebApplicationContext context = this.spring.getContext();
|
|
||||||
context.setServletContext(servletContext);
|
|
||||||
// @formatter:off
|
|
||||||
this.mvc.perform(get("/spring/path").servletPath("/spring"))
|
|
||||||
.andExpect(status().isUnauthorized());
|
|
||||||
// @formatter:on
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void requestWhenUsingMvcMatchersAndServletPathAndAuthorizationManagerThenAuthorizesRequestsAccordingly()
|
|
||||||
throws Exception {
|
|
||||||
this.spring.configLocations(this.xml("MvcMatchersServletPathAuthorizationManager")).autowire();
|
|
||||||
MockServletContext servletContext = mockServletContext("/spring");
|
|
||||||
ConfigurableWebApplicationContext context = this.spring.getContext();
|
|
||||||
context.setServletContext(servletContext);
|
|
||||||
// @formatter:off
|
|
||||||
this.mvc.perform(get("/spring/path").servletPath("/spring"))
|
|
||||||
.andExpect(status().isUnauthorized());
|
|
||||||
this.mvc.perform(get("/spring/path.html").servletPath("/spring"))
|
|
||||||
.andExpect(status().isUnauthorized());
|
|
||||||
this.mvc.perform(get("/spring/path/").servletPath("/spring"))
|
|
||||||
.andExpect(status().isUnauthorized());
|
|
||||||
// @formatter:on
|
|
||||||
assertThat(this.spring.getContext().getBean(AuthorizationManager.class)).isNotNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void configureWhenUsingAntMatcherAndServletPathThenThrowsException() {
|
|
||||||
assertThatExceptionOfType(BeanDefinitionParsingException.class)
|
|
||||||
.isThrownBy(() -> this.spring.configLocations(this.xml("AntMatcherServletPath")).autowire());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void configureWhenUsingAntMatcherAndServletPathAndAuthorizationManagerThenThrowsException() {
|
|
||||||
assertThatExceptionOfType(BeanDefinitionParsingException.class).isThrownBy(
|
|
||||||
() -> this.spring.configLocations(this.xml("AntMatcherServletPathAuthorizationManager")).autowire());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void configureWhenUsingRegexMatcherAndServletPathThenThrowsException() {
|
public void configureWhenUsingRegexMatcherAndServletPathThenThrowsException() {
|
||||||
assertThatExceptionOfType(BeanDefinitionParsingException.class)
|
assertThatExceptionOfType(BeanDefinitionParsingException.class)
|
||||||
@ -366,12 +307,6 @@ public class InterceptUrlConfigTests {
|
|||||||
.isThrownBy(() -> this.spring.configLocations(this.xml("DefaultMatcherServletPath")).autowire());
|
.isThrownBy(() -> this.spring.configLocations(this.xml("DefaultMatcherServletPath")).autowire());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void configureWhenUsingDefaultMatcherAndNoIntrospectorBeanThenException() {
|
|
||||||
assertThatExceptionOfType(BeanCreationException.class)
|
|
||||||
.isThrownBy(() -> this.spring.configLocations(this.xml("DefaultMatcherNoIntrospectorBean")).autowire());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void configureWhenUsingDefaultMatcherAndServletPathAndAuthorizationManagerThenNoException() {
|
public void configureWhenUsingDefaultMatcherAndServletPathAndAuthorizationManagerThenNoException() {
|
||||||
assertThatNoException()
|
assertThatNoException()
|
||||||
|
@ -22,7 +22,8 @@ import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
|
|||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer;
|
import org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer;
|
||||||
import org.springframework.security.web.DefaultSecurityFilterChain;
|
import org.springframework.security.web.DefaultSecurityFilterChain;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
|
import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.pathPattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
@ -44,7 +45,7 @@ public class CustomConfigurer extends SecurityConfigurerAdapter<DefaultSecurityF
|
|||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.authorizeRequests((requests) -> requests
|
.authorizeRequests((requests) -> requests
|
||||||
.requestMatchers(new AntPathRequestMatcher(this.permitAllPattern)).permitAll()
|
.requestMatchers(pathPattern(this.permitAllPattern)).permitAll()
|
||||||
.anyRequest().authenticated());
|
.anyRequest().authenticated());
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
if (http.getConfigurer(FormLoginConfigurer.class) == null) {
|
if (http.getConfigurer(FormLoginConfigurer.class) == null) {
|
||||||
|
@ -38,12 +38,8 @@ import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequ
|
|||||||
import org.springframework.security.web.SecurityFilterChain
|
import org.springframework.security.web.SecurityFilterChain
|
||||||
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy
|
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy
|
||||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy
|
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy
|
||||||
import org.springframework.security.web.csrf.CsrfTokenRepository
|
import org.springframework.security.web.csrf.*
|
||||||
import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher
|
||||||
import org.springframework.security.web.csrf.CsrfTokenRequestHandler
|
|
||||||
import org.springframework.security.web.csrf.DefaultCsrfToken
|
|
||||||
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository
|
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher
|
|
||||||
import org.springframework.test.web.servlet.MockMvc
|
import org.springframework.test.web.servlet.MockMvc
|
||||||
import org.springframework.test.web.servlet.get
|
import org.springframework.test.web.servlet.get
|
||||||
import org.springframework.test.web.servlet.post
|
import org.springframework.test.web.servlet.post
|
||||||
@ -176,7 +172,7 @@ class CsrfDslTests {
|
|||||||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||||
http {
|
http {
|
||||||
csrf {
|
csrf {
|
||||||
requireCsrfProtectionMatcher = AntPathRequestMatcher("/test1")
|
requireCsrfProtectionMatcher = PathPatternRequestMatcher.pathPattern("/test1")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return http.build()
|
return http.build()
|
||||||
@ -247,8 +243,8 @@ class CsrfDslTests {
|
|||||||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||||
http {
|
http {
|
||||||
csrf {
|
csrf {
|
||||||
requireCsrfProtectionMatcher = AntPathRequestMatcher("/**")
|
requireCsrfProtectionMatcher = PathPatternRequestMatcher.pathPattern("/**")
|
||||||
ignoringRequestMatchers(AntPathRequestMatcher("/test2"))
|
ignoringRequestMatchers(PathPatternRequestMatcher.pathPattern("/test2"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return http.build()
|
return http.build()
|
||||||
@ -279,7 +275,7 @@ class CsrfDslTests {
|
|||||||
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
|
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
|
||||||
http {
|
http {
|
||||||
csrf {
|
csrf {
|
||||||
requireCsrfProtectionMatcher = AntPathRequestMatcher("/**")
|
requireCsrfProtectionMatcher = PathPatternRequestMatcher.pathPattern("/**")
|
||||||
ignoringRequestMatchers("/test2")
|
ignoringRequestMatchers("/test2")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequ
|
|||||||
import org.springframework.security.web.SecurityFilterChain
|
import org.springframework.security.web.SecurityFilterChain
|
||||||
import org.springframework.security.web.access.AccessDeniedHandlerImpl
|
import org.springframework.security.web.access.AccessDeniedHandlerImpl
|
||||||
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint
|
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher
|
||||||
import org.springframework.test.web.servlet.MockMvc
|
import org.springframework.test.web.servlet.MockMvc
|
||||||
import org.springframework.test.web.servlet.get
|
import org.springframework.test.web.servlet.get
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc
|
||||||
@ -195,6 +195,7 @@ class ExceptionHandlingDslTests {
|
|||||||
customAccessDeniedHandler1.setErrorPage("/access-denied1")
|
customAccessDeniedHandler1.setErrorPage("/access-denied1")
|
||||||
val customAccessDeniedHandler2 = AccessDeniedHandlerImpl()
|
val customAccessDeniedHandler2 = AccessDeniedHandlerImpl()
|
||||||
customAccessDeniedHandler2.setErrorPage("/access-denied2")
|
customAccessDeniedHandler2.setErrorPage("/access-denied2")
|
||||||
|
val builder = PathPatternRequestMatcher.withDefaults()
|
||||||
http {
|
http {
|
||||||
authorizeRequests {
|
authorizeRequests {
|
||||||
authorize("/admin1", hasAuthority("ROLE_ADMIN"))
|
authorize("/admin1", hasAuthority("ROLE_ADMIN"))
|
||||||
@ -202,8 +203,8 @@ class ExceptionHandlingDslTests {
|
|||||||
authorize(anyRequest, authenticated)
|
authorize(anyRequest, authenticated)
|
||||||
}
|
}
|
||||||
exceptionHandling {
|
exceptionHandling {
|
||||||
defaultAccessDeniedHandlerFor(customAccessDeniedHandler1, AntPathRequestMatcher("/admin1"))
|
defaultAccessDeniedHandlerFor(customAccessDeniedHandler1, builder.matcher("/admin1"))
|
||||||
defaultAccessDeniedHandlerFor(customAccessDeniedHandler2, AntPathRequestMatcher("/admin2"))
|
defaultAccessDeniedHandlerFor(customAccessDeniedHandler2, builder.matcher("/admin2"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return http.build()
|
return http.build()
|
||||||
@ -264,13 +265,14 @@ class ExceptionHandlingDslTests {
|
|||||||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||||
val customAuthenticationEntryPoint1 = LoginUrlAuthenticationEntryPoint("/custom-login1")
|
val customAuthenticationEntryPoint1 = LoginUrlAuthenticationEntryPoint("/custom-login1")
|
||||||
val customAuthenticationEntryPoint2 = LoginUrlAuthenticationEntryPoint("/custom-login2")
|
val customAuthenticationEntryPoint2 = LoginUrlAuthenticationEntryPoint("/custom-login2")
|
||||||
|
val builder = PathPatternRequestMatcher.withDefaults();
|
||||||
http {
|
http {
|
||||||
authorizeRequests {
|
authorizeRequests {
|
||||||
authorize(anyRequest, authenticated)
|
authorize(anyRequest, authenticated)
|
||||||
}
|
}
|
||||||
exceptionHandling {
|
exceptionHandling {
|
||||||
defaultAuthenticationEntryPointFor(customAuthenticationEntryPoint1, AntPathRequestMatcher("/secured1"))
|
defaultAuthenticationEntryPointFor(customAuthenticationEntryPoint1, builder.matcher("/secured1"))
|
||||||
defaultAuthenticationEntryPointFor(customAuthenticationEntryPoint2, AntPathRequestMatcher("/secured2"))
|
defaultAuthenticationEntryPointFor(customAuthenticationEntryPoint2, builder.matcher("/secured2"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return http.build()
|
return http.build()
|
||||||
|
@ -40,7 +40,7 @@ import org.springframework.security.web.SecurityFilterChain
|
|||||||
import org.springframework.security.web.authentication.logout.LogoutHandler
|
import org.springframework.security.web.authentication.logout.LogoutHandler
|
||||||
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler
|
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler
|
||||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository
|
import org.springframework.security.web.context.HttpSessionSecurityContextRepository
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher
|
||||||
import org.springframework.test.web.servlet.MockMvc
|
import org.springframework.test.web.servlet.MockMvc
|
||||||
import org.springframework.test.web.servlet.post
|
import org.springframework.test.web.servlet.post
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ class LogoutDslTests {
|
|||||||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||||
http {
|
http {
|
||||||
logout {
|
logout {
|
||||||
logoutRequestMatcher = AntPathRequestMatcher("/custom/logout")
|
logoutRequestMatcher = PathPatternRequestMatcher.pathPattern("/custom/logout")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return http.build()
|
return http.build()
|
||||||
@ -307,8 +307,9 @@ class LogoutDslTests {
|
|||||||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||||
http {
|
http {
|
||||||
logout {
|
logout {
|
||||||
logoutRequestMatcher = AntPathRequestMatcher("/logout/**")
|
logoutRequestMatcher = PathPatternRequestMatcher.pathPattern("/logout/**")
|
||||||
defaultLogoutSuccessHandlerFor(SimpleUrlLogoutSuccessHandler(), AntPathRequestMatcher("/logout/custom"))
|
defaultLogoutSuccessHandlerFor(SimpleUrlLogoutSuccessHandler(),
|
||||||
|
PathPatternRequestMatcher.pathPattern("/logout/custom"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return http.build()
|
return http.build()
|
||||||
|
@ -51,7 +51,6 @@ import org.springframework.security.web.authentication.RememberMeServices
|
|||||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler
|
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler
|
||||||
import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices
|
import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices
|
||||||
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository
|
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher
|
|
||||||
import org.springframework.test.web.servlet.MockHttpServletRequestDsl
|
import org.springframework.test.web.servlet.MockHttpServletRequestDsl
|
||||||
import org.springframework.test.web.servlet.MockMvc
|
import org.springframework.test.web.servlet.MockMvc
|
||||||
import org.springframework.test.web.servlet.get
|
import org.springframework.test.web.servlet.get
|
||||||
@ -472,7 +471,7 @@ internal class RememberMeDslTests {
|
|||||||
@Order(0)
|
@Order(0)
|
||||||
open fun securityFilterChainWithoutKey(http: HttpSecurity): SecurityFilterChain {
|
open fun securityFilterChainWithoutKey(http: HttpSecurity): SecurityFilterChain {
|
||||||
http {
|
http {
|
||||||
securityMatcher(AntPathRequestMatcher("/without-key/**"))
|
securityMatcher("/without-key/**")
|
||||||
formLogin {
|
formLogin {
|
||||||
loginProcessingUrl = "/without-key/login"
|
loginProcessingUrl = "/without-key/login"
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ import org.springframework.security.config.test.SpringTestContext
|
|||||||
import org.springframework.security.config.test.SpringTestContextExtension
|
import org.springframework.security.config.test.SpringTestContextExtension
|
||||||
import org.springframework.security.web.SecurityFilterChain
|
import org.springframework.security.web.SecurityFilterChain
|
||||||
import org.springframework.security.web.server.header.StrictTransportSecurityServerHttpHeadersWriter
|
import org.springframework.security.web.server.header.StrictTransportSecurityServerHttpHeadersWriter
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher
|
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher
|
||||||
import org.springframework.test.web.servlet.MockMvc
|
import org.springframework.test.web.servlet.MockMvc
|
||||||
import org.springframework.test.web.servlet.get
|
import org.springframework.test.web.servlet.get
|
||||||
|
|
||||||
@ -148,7 +148,7 @@ class HttpStrictTransportSecurityDslTests {
|
|||||||
headers {
|
headers {
|
||||||
defaultsDisabled = true
|
defaultsDisabled = true
|
||||||
httpStrictTransportSecurity {
|
httpStrictTransportSecurity {
|
||||||
requestMatcher = AntPathRequestMatcher("/secure/**")
|
requestMatcher = PathPatternRequestMatcher.pathPattern("/secure/**")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,16 +15,12 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns:context="http://www.springframework.org/schema/context"
|
|
||||||
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"
|
|
||||||
xmlns:security="http://www.springframework.org/schema/security"
|
xmlns:security="http://www.springframework.org/schema/security"
|
||||||
xsi:schemaLocation="
|
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
|
||||||
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
|
|
||||||
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
|
|
||||||
http://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx.xsd
|
|
||||||
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util-3.1.xsd
|
http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd">
|
||||||
http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd
|
|
||||||
">
|
|
||||||
|
|
||||||
<security:http pattern="/foo/**">
|
<security:http pattern="/foo/**">
|
||||||
<security:intercept-url pattern="/**" access="hasRole('FOO')" />
|
<security:intercept-url pattern="/**" access="hasRole('FOO')" />
|
||||||
@ -44,6 +40,4 @@ http://www.springframework.org/schema/security https://www.springframework.org/s
|
|||||||
</security:authentication-provider>
|
</security:authentication-provider>
|
||||||
</security:authentication-manager>
|
</security:authentication-manager>
|
||||||
|
|
||||||
<import resource="handlermappingintrospector.xml"/>
|
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
</http>
|
</http>
|
||||||
|
|
||||||
<b:import resource="CsrfConfigTests-shared-userservice.xml"/>
|
<b:import resource="CsrfConfigTests-shared-userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
|
|
||||||
<b:bean id="firewall" class="org.springframework.security.web.firewall.StrictHttpFirewall"
|
<b:bean id="firewall" class="org.springframework.security.web.firewall.StrictHttpFirewall"
|
||||||
p:unsafeAllowAnyHttpMethod="true"/>
|
p:unsafeAllowAnyHttpMethod="true"/>
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
http://www.springframework.org/schema/beans
|
http://www.springframework.org/schema/beans
|
||||||
https://www.springframework.org/schema/beans/spring-beans.xsd">
|
https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||||
|
|
||||||
<http auto-config="true" use-expressions="false" request-matcher="ant" use-authorization-manager="false">
|
<http auto-config="true" use-expressions="false" use-authorization-manager="false">
|
||||||
<intercept-url pattern="/**" access="ROLE_USER"/>
|
<intercept-url pattern="/**" access="ROLE_USER"/>
|
||||||
<form-login/>
|
<form-login/>
|
||||||
</http>
|
</http>
|
@ -24,7 +24,7 @@
|
|||||||
http://www.springframework.org/schema/beans
|
http://www.springframework.org/schema/beans
|
||||||
https://www.springframework.org/schema/beans/spring-beans.xsd">
|
https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||||
|
|
||||||
<http auto-config="true" use-expressions="false" request-matcher="ant" use-authorization-manager="false">
|
<http auto-config="true" use-expressions="false" use-authorization-manager="false">
|
||||||
<intercept-url pattern="/**" access="ROLE_USER"/>
|
<intercept-url pattern="/**" access="ROLE_USER"/>
|
||||||
<form-login authentication-success-handler-ref="fsh" authentication-failure-handler-ref="fsh"/>
|
<form-login authentication-success-handler-ref="fsh" authentication-failure-handler-ref="fsh"/>
|
||||||
</http>
|
</http>
|
||||||
|
@ -16,8 +16,10 @@
|
|||||||
<user name="user" password="password" authorities="ROLE_USER"/>
|
<user name="user" password="password" authorities="ROLE_USER"/>
|
||||||
</user-service>
|
</user-service>
|
||||||
|
|
||||||
<b:bean id="matcherRef" class="org.springframework.security.web.util.matcher.AntPathRequestMatcher"
|
<b:bean id="mvcPatternParser" class="org.springframework.web.util.pattern.PathPatternParser">
|
||||||
c:pattern="/foo"
|
<b:property name="caseSensitive" value="false"/>
|
||||||
c:httpMethod="GET"
|
</b:bean>
|
||||||
c:caseSensitive="false"/>
|
|
||||||
|
<b:bean id="matcherRef" class="org.springframework.security.config.http.PathPatternRequestMatcherFactoryBean"
|
||||||
|
c:pattern="/foo" c:method="GET"/>
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
<b:constructor-arg value="ERROR"/>
|
<b:constructor-arg value="ERROR"/>
|
||||||
</b:bean>
|
</b:bean>
|
||||||
|
|
||||||
<b:bean name="errorPathRequestMatcher" class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
|
<b:bean name="errorPathRequestMatcher" class="org.springframework.security.config.http.PathPatternRequestMatcherFactoryBean">
|
||||||
<b:constructor-arg value="/error"/>
|
<b:constructor-arg value="/error"/>
|
||||||
</b:bean>
|
</b:bean>
|
||||||
|
|
||||||
|
@ -33,5 +33,4 @@
|
|||||||
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
||||||
|
|
||||||
<b:import resource="userservice.xml"/>
|
<b:import resource="userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -33,5 +33,4 @@
|
|||||||
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
||||||
|
|
||||||
<b:import resource="userservice.xml"/>
|
<b:import resource="userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -30,5 +30,4 @@
|
|||||||
</http>
|
</http>
|
||||||
|
|
||||||
<b:import resource="userservice.xml"/>
|
<b:import resource="userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -30,5 +30,4 @@
|
|||||||
</http>
|
</http>
|
||||||
|
|
||||||
<b:import resource="userservice.xml"/>
|
<b:import resource="userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
<b:constructor-arg value="ERROR"/>
|
<b:constructor-arg value="ERROR"/>
|
||||||
</b:bean>
|
</b:bean>
|
||||||
|
|
||||||
<b:bean name="errorPathRequestMatcher" class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
|
<b:bean name="errorPathRequestMatcher" class="org.springframework.security.config.http.PathPatternRequestMatcherFactoryBean">
|
||||||
<b:constructor-arg value="/error"/>
|
<b:constructor-arg value="/error"/>
|
||||||
</b:bean>
|
</b:bean>
|
||||||
|
|
||||||
|
@ -33,5 +33,4 @@
|
|||||||
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
||||||
|
|
||||||
<b:import resource="userservice.xml"/>
|
<b:import resource="userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -33,5 +33,4 @@
|
|||||||
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
||||||
|
|
||||||
<b:import resource="userservice.xml"/>
|
<b:import resource="userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -33,5 +33,4 @@
|
|||||||
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
||||||
|
|
||||||
<b:import resource="userservice.xml"/>
|
<b:import resource="userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -33,5 +33,4 @@
|
|||||||
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
||||||
|
|
||||||
<b:import resource="userservice.xml"/>
|
<b:import resource="userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -34,5 +34,4 @@
|
|||||||
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
||||||
|
|
||||||
<b:import resource="userservice.xml"/>
|
<b:import resource="userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -34,5 +34,4 @@
|
|||||||
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
||||||
|
|
||||||
<b:import resource="userservice.xml"/>
|
<b:import resource="userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -34,5 +34,4 @@
|
|||||||
<b:bean name="id" class="org.springframework.security.config.http.InterceptUrlConfigTests.Id"/>
|
<b:bean name="id" class="org.springframework.security.config.http.InterceptUrlConfigTests.Id"/>
|
||||||
|
|
||||||
<b:import resource="userservice.xml"/>
|
<b:import resource="userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -34,5 +34,4 @@
|
|||||||
<b:bean name="id" class="org.springframework.security.config.http.InterceptUrlConfigTests.Id"/>
|
<b:bean name="id" class="org.springframework.security.config.http.InterceptUrlConfigTests.Id"/>
|
||||||
|
|
||||||
<b:import resource="userservice.xml"/>
|
<b:import resource="userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -32,5 +32,4 @@
|
|||||||
</http>
|
</http>
|
||||||
|
|
||||||
<b:import resource="userservice.xml"/>
|
<b:import resource="userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -31,5 +31,4 @@
|
|||||||
</http>
|
</http>
|
||||||
|
|
||||||
<b:import resource="userservice.xml"/>
|
<b:import resource="userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -34,5 +34,4 @@
|
|||||||
</b:bean>
|
</b:bean>
|
||||||
|
|
||||||
<b:import resource="userservice.xml"/>
|
<b:import resource="userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
<http-basic/>
|
<http-basic/>
|
||||||
</http>
|
</http>
|
||||||
|
|
||||||
<b:bean name="matcher" class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
|
<b:bean name="matcher" class="org.springframework.security.config.http.PathPatternRequestMatcherFactoryBean">
|
||||||
<b:constructor-arg value="/unprotected"/>
|
<b:constructor-arg value="/unprotected"/>
|
||||||
</b:bean>
|
</b:bean>
|
||||||
|
|
||||||
|
@ -29,5 +29,4 @@
|
|||||||
<http pattern="/unprotected" security="none"/>
|
<http pattern="/unprotected" security="none"/>
|
||||||
|
|
||||||
<b:import resource="userservice.xml"/>
|
<b:import resource="userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -31,5 +31,4 @@
|
|||||||
</http>
|
</http>
|
||||||
|
|
||||||
<b:import resource="userservice.xml"/>
|
<b:import resource="userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -31,5 +31,4 @@
|
|||||||
</http>
|
</http>
|
||||||
|
|
||||||
<b:import resource="userservice.xml"/>
|
<b:import resource="userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -30,5 +30,4 @@
|
|||||||
</http>
|
</http>
|
||||||
|
|
||||||
<b:import resource="userservice.xml"/>
|
<b:import resource="userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -30,5 +30,4 @@
|
|||||||
</http>
|
</http>
|
||||||
|
|
||||||
<b:import resource="userservice.xml"/>
|
<b:import resource="userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -35,5 +35,4 @@
|
|||||||
<b:bean name="basicController" class="org.springframework.security.config.http.MultiHttpBlockConfigTests.BasicController"/>
|
<b:bean name="basicController" class="org.springframework.security.config.http.MultiHttpBlockConfigTests.BasicController"/>
|
||||||
|
|
||||||
<b:import resource="userservice.xml"/>
|
<b:import resource="userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -33,5 +33,4 @@
|
|||||||
</http>
|
</http>
|
||||||
|
|
||||||
<b:import resource="userservice.xml"/>
|
<b:import resource="userservice.xml"/>
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
@ -50,5 +50,4 @@
|
|||||||
</authentication-provider>
|
</authentication-provider>
|
||||||
</authentication-manager>
|
</authentication-manager>
|
||||||
|
|
||||||
<b:import resource="handlermappingintrospector.xml"/>
|
|
||||||
</b:beans>
|
</b:beans>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user