Prgress
This commit is contained in:
parent
75f30d1701
commit
ef50ff29ad
|
@ -52,7 +52,6 @@ import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
|
|||
import org.springframework.security.web.savedrequest.RequestCache;
|
||||
import org.springframework.security.web.savedrequest.SavedRequest;
|
||||
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.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
@ -335,7 +334,7 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
|
|||
}
|
||||
|
||||
public final void setProxyReceptorUrl(final String proxyReceptorUrl) {
|
||||
this.proxyReceptorMatcher = new AntPathRequestMatcher("/**" + proxyReceptorUrl);
|
||||
this.proxyReceptorMatcher = PathPatternRequestMatcher.withDefaults().matcher(proxyReceptorUrl);
|
||||
}
|
||||
|
||||
public final void setProxyGrantingTicketStorage(final ProxyGrantingTicketStorage proxyGrantingTicketStorage) {
|
||||
|
|
|
@ -18,41 +18,20 @@ package org.springframework.security.config.annotation.web;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
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.ServletContext;
|
||||
import jakarta.servlet.ServletRegistration;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.apache.commons.logging.Log;
|
||||
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.core.ResolvableType;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.security.config.ObjectPostProcessor;
|
||||
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.servlet.util.matcher.PathPatternRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||
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.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
|
||||
|
@ -65,23 +44,12 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|||
*/
|
||||
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 ApplicationContext context;
|
||||
|
||||
private boolean anyRequestConfigured = false;
|
||||
|
||||
static {
|
||||
mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR,
|
||||
AbstractRequestMatcherRegistry.class.getClassLoader());
|
||||
}
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
protected final void setApplicationContext(ApplicationContext context) {
|
||||
|
@ -107,40 +75,6 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||
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
|
||||
* {@link org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher}
|
||||
|
@ -184,12 +118,9 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||
|
||||
/**
|
||||
* <p>
|
||||
* If the {@link HandlerMappingIntrospector} is available in the classpath, maps to an
|
||||
* {@link MvcRequestMatcher} that also specifies a specific {@link HttpMethod} to
|
||||
* match on. 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}.
|
||||
* Match when the {@link HttpMethod} is {@code method} and when the request URI
|
||||
* matches one of {@code patterns}. See
|
||||
* {@link org.springframework.web.util.pattern.PathPattern} for matching rules.
|
||||
* </p>
|
||||
* <p>
|
||||
* If a specific {@link RequestMatcher} must be specified, use
|
||||
|
@ -197,8 +128,7 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||
* </p>
|
||||
* @param method the {@link HttpMethod} to use or {@code null} for any
|
||||
* {@link HttpMethod}.
|
||||
* @param patterns the patterns to match on. The rules for matching are defined by
|
||||
* Spring MVC if {@link MvcRequestMatcher} is used
|
||||
* @param patterns the patterns to match on
|
||||
* @return the object that is chained after creating the {@link RequestMatcher}.
|
||||
* @since 5.8
|
||||
*/
|
||||
|
@ -209,27 +139,13 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||
+ "leading slash in all your request matcher patterns. In future versions of "
|
||||
+ "Spring Security, leaving out the leading slash will result in an exception.");
|
||||
}
|
||||
if (!mvcPresent) {
|
||||
return requestMatchers(RequestMatchers.antMatchersAsArray(method, patterns));
|
||||
}
|
||||
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));
|
||||
}
|
||||
Assert.state(!this.anyRequestConfigured, "Can't configure requestMatchers after anyRequest");
|
||||
PathPatternRequestMatcher.Builder builder = this.context
|
||||
.getBeanProvider(PathPatternRequestMatcher.Builder.class)
|
||||
.getIfUnique(PathPatternRequestMatcher::withDefaults);
|
||||
List<RequestMatcher> matchers = new ArrayList<>();
|
||||
for (String pattern : patterns) {
|
||||
if (RequestMatcherFactory.usesPathPatterns()) {
|
||||
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));
|
||||
}
|
||||
matchers.add(builder.matcher(method, pattern));
|
||||
}
|
||||
return requestMatchers(matchers.toArray(new RequestMatcher[0]));
|
||||
}
|
||||
|
@ -243,64 +159,16 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||
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>
|
||||
* If the {@link HandlerMappingIntrospector} is available in the classpath, maps to an
|
||||
* {@link MvcRequestMatcher} that does not care which {@link HttpMethod} is used. 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}.
|
||||
* Match when the request URI matches one of {@code patterns}. See
|
||||
* {@link org.springframework.web.util.pattern.PathPattern} for matching rules.
|
||||
* </p>
|
||||
* <p>
|
||||
* If a specific {@link RequestMatcher} must be specified, use
|
||||
* {@link #requestMatchers(RequestMatcher...)} instead
|
||||
* </p>
|
||||
* @param patterns the patterns to match on. The rules for matching are defined by
|
||||
* Spring MVC if {@link MvcRequestMatcher} is used
|
||||
* @param patterns the patterns to match on
|
||||
* @return the object that is chained after creating the {@link RequestMatcher}.
|
||||
* @since 5.8
|
||||
*/
|
||||
|
@ -310,12 +178,7 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||
|
||||
/**
|
||||
* <p>
|
||||
* If the {@link HandlerMappingIntrospector} is available in the classpath, maps to an
|
||||
* {@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}.
|
||||
* Match when the {@link HttpMethod} is {@code method}
|
||||
* </p>
|
||||
* <p>
|
||||
* If a specific {@link RequestMatcher} must be specified, use
|
||||
|
@ -339,182 +202,4 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||
*/
|
||||
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 + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ 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;
|
||||
|
||||
/**
|
||||
|
@ -34,11 +33,8 @@ 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;
|
||||
builder = context.getBeanProvider(PathPatternRequestMatcher.Builder.class)
|
||||
.getIfUnique(PathPatternRequestMatcher::withDefaults);
|
||||
}
|
||||
|
||||
public static RequestMatcher matcher(String path) {
|
||||
|
@ -46,10 +42,7 @@ public final class RequestMatcherFactory {
|
|||
}
|
||||
|
||||
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);
|
||||
return builder.matcher(method, path);
|
||||
}
|
||||
|
||||
private RequestMatcherFactory() {
|
||||
|
|
|
@ -28,7 +28,6 @@ import jakarta.servlet.ServletRequest;
|
|||
import jakarta.servlet.ServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
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.web.AbstractRequestMatcherRegistry;
|
||||
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.WebSecurityConfiguration;
|
||||
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.context.AbstractSecurityWebApplicationInitializer;
|
||||
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.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
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
|
||||
|
@ -153,12 +148,6 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|||
public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<DefaultSecurityFilterChain, 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 List<OrderedFilter> filters = new ArrayList<>();
|
||||
|
@ -169,10 +158,6 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
|||
|
||||
private AuthenticationManager authenticationManager;
|
||||
|
||||
static {
|
||||
mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, HttpSecurity.class.getClassLoader());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
* @param objectPostProcessor the {@link ObjectPostProcessor} that should be used
|
||||
|
@ -320,9 +305,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
|||
/**
|
||||
* 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
|
||||
* defined, then that {@link CorsConfiguration} is used. Otherwise, if Spring MVC is
|
||||
* on the classpath a {@link HandlerMappingIntrospector} is used. You can enable CORS
|
||||
* using:
|
||||
* defined, then that {@link CorsConfiguration} is used. You can enable CORS using:
|
||||
*
|
||||
* <pre>
|
||||
* @Configuration
|
||||
|
@ -2202,10 +2185,8 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
|||
|
||||
/**
|
||||
* Allows configuring the {@link HttpSecurity} to only be invoked when matching the
|
||||
* provided pattern. This method creates a {@link MvcRequestMatcher} if Spring MVC is
|
||||
* in the classpath or creates an {@link AntPathRequestMatcher} if not. If more
|
||||
* advanced configuration is necessary, consider using
|
||||
* {@link #securityMatchers(Customizer)} or {@link #securityMatcher(RequestMatcher)}.
|
||||
* provided set of {@code patterns}. See
|
||||
* {@link org.springframework.web.util.pattern.PathPattern} for matching rules
|
||||
*
|
||||
* <p>
|
||||
* Invoking {@link #securityMatcher(String...)} will override previous invocations of
|
||||
|
@ -2215,19 +2196,16 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
|||
* </p>
|
||||
* @param patterns the pattern to match on (i.e. "/admin/**")
|
||||
* @return the {@link HttpSecurity} for further customizations
|
||||
* @see AntPathRequestMatcher
|
||||
* @see MvcRequestMatcher
|
||||
* @see org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher
|
||||
* @see org.springframework.web.util.pattern.PathPattern
|
||||
*/
|
||||
public HttpSecurity securityMatcher(String... patterns) {
|
||||
List<RequestMatcher> matchers = new ArrayList<>();
|
||||
PathPatternRequestMatcher.Builder builder = getContext()
|
||||
.getBeanProvider(PathPatternRequestMatcher.Builder.class)
|
||||
.getIfUnique(PathPatternRequestMatcher::withDefaults);
|
||||
for (String pattern : patterns) {
|
||||
if (RequestMatcherFactory.usesPathPatterns()) {
|
||||
matchers.add(RequestMatcherFactory.matcher(pattern));
|
||||
}
|
||||
else {
|
||||
RequestMatcher matcher = mvcPresent ? createMvcMatcher(pattern) : createAntMatcher(pattern);
|
||||
matchers.add(matcher);
|
||||
}
|
||||
matchers.add(builder.matcher(pattern));
|
||||
}
|
||||
this.requestMatcher = new OrRequestMatcher(matchers);
|
||||
return this;
|
||||
|
@ -2258,26 +2236,6 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
|||
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,
|
||||
* 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.HttpServletRequestTransformer;
|
||||
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.WebInvocationPrivilegeEvaluator;
|
||||
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
|
||||
|
@ -430,7 +431,7 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder<Filter,
|
|||
this.filterChainDecoratorPostProcessor = postProcessor.getIfUnique(ObjectPostProcessor::identity);
|
||||
Class<HttpServletRequestTransformer> requestTransformerClass = HttpServletRequestTransformer.class;
|
||||
this.privilegeEvaluatorRequestTransformer = applicationContext.getBeanProvider(requestTransformerClass)
|
||||
.getIfUnique();
|
||||
.getIfUnique(PathPatternRequestTransformer::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -26,15 +26,7 @@ import jakarta.servlet.ServletRequest;
|
|||
import jakarta.servlet.ServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
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.ApplicationContextAware;
|
||||
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.web.FilterChainProxy;
|
||||
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.firewall.HttpFirewall;
|
||||
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.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
||||
import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
||||
|
||||
/**
|
||||
|
@ -76,10 +65,6 @@ import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
|||
*/
|
||||
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 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
|
||||
* delegates to {@link CompositeFilter} for
|
||||
|
|
|
@ -69,7 +69,6 @@ import org.springframework.security.web.firewall.HttpFirewall;
|
|||
import org.springframework.security.web.firewall.RequestRejectedHandler;
|
||||
import org.springframework.web.filter.CompositeFilter;
|
||||
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
|
||||
|
@ -209,12 +208,11 @@ public class WebSecurityConfiguration implements ImportAware {
|
|||
/**
|
||||
* Used to ensure Spring MVC request matching is cached.
|
||||
*
|
||||
* Creates a {@link BeanDefinitionRegistryPostProcessor} that detects if a bean named
|
||||
* HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME is defined. If so, it moves the
|
||||
* Creates a {@link BeanDefinitionRegistryPostProcessor} that moves the
|
||||
* AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME to another bean name
|
||||
* and then adds a {@link CompositeFilter} that contains
|
||||
* {@link HandlerMappingIntrospector#createCacheFilter()} and the original
|
||||
* FilterChainProxy under the original Bean name.
|
||||
* {@link ServletRequestPathFilter} and the original FilterChainProxy under the
|
||||
* original Bean name.
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
|
|
|
@ -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.builders.HttpSecurity;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
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
|
||||
* corsFilter is provided, that {@link CorsFilter} is used. Else if
|
||||
* 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.
|
||||
* @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 HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector";
|
||||
|
||||
private static final boolean mvcPresent;
|
||||
|
||||
private CorsConfigurationSource configurationSource;
|
||||
|
||||
static {
|
||||
mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, CorsConfigurer.class.getClassLoader());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
|
@ -91,10 +79,7 @@ public class CorsConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractHt
|
|||
CorsConfigurationSource.class);
|
||||
return new CorsFilter(configurationSource);
|
||||
}
|
||||
if (mvcPresent) {
|
||||
return MvcCorsFilter.getMvcCorsFilter(context);
|
||||
}
|
||||
return null;
|
||||
return MvcCorsFilter.getMvcCorsFilter(context);
|
||||
}
|
||||
|
||||
static class MvcCorsFilter {
|
||||
|
|
|
@ -31,7 +31,6 @@ import org.springframework.security.web.savedrequest.NullRequestCache;
|
|||
import org.springframework.security.web.savedrequest.RequestCache;
|
||||
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
|
||||
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.NegatedRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;
|
||||
|
@ -174,12 +173,7 @@ public final class RequestCacheConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
}
|
||||
|
||||
private RequestMatcher getFaviconRequestMatcher() {
|
||||
if (RequestMatcherFactory.usesPathPatterns()) {
|
||||
return RequestMatcherFactory.matcher("/favicon.*");
|
||||
}
|
||||
else {
|
||||
return new AntPathRequestMatcher("/**/favicon.*");
|
||||
}
|
||||
return RequestMatcherFactory.matcher("/favicon.*");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,10 +35,6 @@ class WebMvcSecurityConfigurationRuntimeHints implements RuntimeHintsRegistrar {
|
|||
.registerType(TypeReference
|
||||
.of("org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$CompositeFilterChainProxy"),
|
||||
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)) {
|
||||
servletPath = null;
|
||||
}
|
||||
else if (!MatcherType.mvc.equals(matcherType)) {
|
||||
else if (!MatcherType.path.equals(matcherType)) {
|
||||
parserContext.getReaderContext()
|
||||
.error(ATT_SERVLET_PATH + " is not applicable for request-matcher: '" + matcherType.name() + "'",
|
||||
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.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
|
||||
|
@ -40,15 +39,6 @@ public class CorsBeanDefinitionParser {
|
|||
|
||||
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) {
|
||||
if (element == null) {
|
||||
return null;
|
||||
|
@ -71,10 +61,7 @@ public class CorsBeanDefinitionParser {
|
|||
if (StringUtils.hasText(configurationSourceRef)) {
|
||||
return new RuntimeBeanReference(configurationSourceRef);
|
||||
}
|
||||
if (!mvcPresent) {
|
||||
return null;
|
||||
}
|
||||
return new RootBeanDefinition(HandlerMappingIntrospectorFactoryBean.class);
|
||||
return new RootBeanDefinition(CorsConfigurationSourceFactoryBean.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,38 +22,37 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
|||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
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}.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 4.1.1
|
||||
*/
|
||||
class HandlerMappingIntrospectorFactoryBean
|
||||
implements FactoryBean<HandlerMappingIntrospector>, ApplicationContextAware {
|
||||
class CorsConfigurationSourceFactoryBean implements FactoryBean<CorsConfigurationSource>, ApplicationContextAware {
|
||||
|
||||
private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector";
|
||||
|
||||
private ApplicationContext context;
|
||||
|
||||
@Override
|
||||
public HandlerMappingIntrospector getObject() {
|
||||
public CorsConfigurationSource getObject() {
|
||||
if (!this.context.containsBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) {
|
||||
throw new NoSuchBeanDefinitionException(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME,
|
||||
"A Bean named " + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME + " of type "
|
||||
+ HandlerMappingIntrospector.class.getName()
|
||||
+ " is required to use MvcRequestMatcher. Please ensure Spring Security & Spring "
|
||||
+ CorsConfigurationSource.class.getName()
|
||||
+ " is required to use <cors>. Please ensure Spring Security & Spring "
|
||||
+ "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
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return HandlerMappingIntrospector.class;
|
||||
return CorsConfigurationSource.class;
|
||||
}
|
||||
|
||||
@Override
|
|
@ -40,7 +40,9 @@ import org.springframework.security.web.FilterChainProxy;
|
|||
import org.springframework.security.web.FilterInvocation;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
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.PathPatternRequestTransformer;
|
||||
import org.springframework.security.web.access.intercept.AuthorizationFilter;
|
||||
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
|
||||
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 AuthorizationManagerWebInvocationPrivilegeEvaluator.HttpServletRequestTransformer requestTransformer = new PathPatternRequestTransformer();
|
||||
|
||||
@Override
|
||||
public void validate(FilterChainProxy fcp) {
|
||||
for (SecurityFilterChain filterChain : fcp.getFilterChains()) {
|
||||
|
@ -188,7 +192,8 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
|
|||
String loginPage = ((LoginUrlAuthenticationEntryPoint) exceptions.getAuthenticationEntryPoint())
|
||||
.getLoginFormUrl();
|
||||
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;
|
||||
try {
|
||||
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);
|
||||
if (authorizationInterceptor != null) {
|
||||
FilterInvocationSecurityMetadataSource fids = authorizationInterceptor.getSecurityMetadataSource();
|
||||
|
@ -257,7 +262,7 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
|
|||
AuthorizationManager<HttpServletRequest> authorizationManager = authorizationFilter
|
||||
.getAuthorizationManager();
|
||||
try {
|
||||
AuthorizationResult result = authorizationManager.authorize(() -> TEST, loginRequest.getHttpRequest());
|
||||
AuthorizationResult result = authorizationManager.authorize(() -> TEST, loginRequest);
|
||||
return result != null && result.isGranted();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
|
@ -267,7 +272,7 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
|
|||
return false;
|
||||
}
|
||||
|
||||
private Supplier<Boolean> deriveAnonymousCheck(List<Filter> filters, FilterInvocation loginRequest,
|
||||
private Supplier<Boolean> deriveAnonymousCheck(List<Filter> filters, HttpServletRequest loginRequest,
|
||||
AnonymousAuthenticationToken token) {
|
||||
FilterSecurityInterceptor authorizationInterceptor = getFilter(FilterSecurityInterceptor.class, filters);
|
||||
if (authorizationInterceptor != null) {
|
||||
|
@ -288,7 +293,7 @@ public class DefaultFilterChainValidator implements FilterChainProxy.FilterChain
|
|||
return () -> {
|
||||
AuthorizationManager<HttpServletRequest> authorizationManager = authorizationFilter
|
||||
.getAuthorizationManager();
|
||||
AuthorizationResult result = authorizationManager.authorize(() -> token, loginRequest.getHttpRequest());
|
||||
AuthorizationResult result = authorizationManager.authorize(() -> token, loginRequest);
|
||||
return result != null && result.isGranted();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -159,7 +159,7 @@ public class FilterInvocationSecurityMetadataSourceParser implements BeanDefinit
|
|||
if (!StringUtils.hasText(servletPath)) {
|
||||
servletPath = null;
|
||||
}
|
||||
else if (!MatcherType.mvc.equals(matcherType)) {
|
||||
else if (!MatcherType.path.equals(matcherType)) {
|
||||
parserContext.getReaderContext()
|
||||
.error(ATT_SERVLET_PATH + " is not applicable for request-matcher: '" + matcherType.name() + "'",
|
||||
urlElt);
|
||||
|
|
|
@ -50,7 +50,6 @@ import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
|||
import org.springframework.security.core.session.SessionRegistryImpl;
|
||||
import org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator;
|
||||
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.channel.ChannelDecisionManagerImpl;
|
||||
import org.springframework.security.web.access.channel.ChannelProcessingFilter;
|
||||
|
@ -88,7 +87,6 @@ import org.springframework.util.Assert;
|
|||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
||||
|
||||
/**
|
||||
* Stateful class which helps HttpSecurityBDP to create the configuration for the
|
||||
|
@ -100,11 +98,6 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
|||
*/
|
||||
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_SESSION_FIXATION_PROTECTION = "session-fixation-protection";
|
||||
|
@ -793,10 +786,8 @@ class HttpConfigurationBuilder {
|
|||
BeanDefinitionBuilder wipeBldr = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(AuthorizationManagerWebInvocationPrivilegeEvaluator.class)
|
||||
.addConstructorArgReference(authorizationFilterParser.getAuthorizationManagerRef());
|
||||
if (mvcPresent) {
|
||||
wipeBldr.addPropertyValue("requestTransformer",
|
||||
new RootBeanDefinition(HandlerMappingIntrospectorRequestTransformerFactoryBean.class));
|
||||
}
|
||||
wipeBldr.addPropertyValue("requestTransformer",
|
||||
new RootBeanDefinition(PathPatternRequestTransformerFactoryBean.class));
|
||||
BeanDefinition wipe = wipeBldr.getBeanDefinition();
|
||||
this.pc.registerBeanComponent(
|
||||
new BeanComponentDefinition(wipe, this.pc.getReaderContext().generateBeanName(wipe)));
|
||||
|
@ -966,7 +957,7 @@ class HttpConfigurationBuilder {
|
|||
return BeanDefinitionBuilder.rootBeanDefinition(ObservationRegistryFactory.class).getBeanDefinition();
|
||||
}
|
||||
|
||||
static class HandlerMappingIntrospectorRequestTransformerFactoryBean
|
||||
static class PathPatternRequestTransformerFactoryBean
|
||||
implements FactoryBean<AuthorizationManagerWebInvocationPrivilegeEvaluator.HttpServletRequestTransformer>,
|
||||
ApplicationContextAware {
|
||||
|
||||
|
@ -982,10 +973,7 @@ class HttpConfigurationBuilder {
|
|||
if (requestTransformer != null) {
|
||||
return requestTransformer;
|
||||
}
|
||||
HandlerMappingIntrospector hmi = this.applicationContext.getBeanProvider(HandlerMappingIntrospector.class)
|
||||
.getIfAvailable();
|
||||
return (hmi != null) ? new HandlerMappingIntrospectorRequestTransformer(hmi)
|
||||
: new PathPatternRequestTransformer();
|
||||
return new PathPatternRequestTransformer();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -22,13 +22,10 @@ import org.springframework.beans.factory.config.BeanDefinition;
|
|||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
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.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.RegexRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
|
@ -39,21 +36,12 @@ import org.springframework.util.StringUtils;
|
|||
*/
|
||||
public enum MatcherType {
|
||||
|
||||
ant(AntPathRequestMatcher.class), regex(RegexRequestMatcher.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;
|
||||
path(PathPatternRequestMatcher.class), regex(RegexRequestMatcher.class), ciRegex(RegexRequestMatcher.class);
|
||||
|
||||
private static final String ATT_MATCHER_TYPE = "request-matcher";
|
||||
|
||||
final Class<? extends RequestMatcher> type;
|
||||
|
||||
static {
|
||||
mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR, MatcherType.class.getClassLoader());
|
||||
}
|
||||
|
||||
MatcherType(Class<? extends RequestMatcher> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
@ -66,18 +54,17 @@ public enum MatcherType {
|
|||
if (("/**".equals(path) || "**".equals(path)) && method == null) {
|
||||
return new RootBeanDefinition(AnyRequestMatcher.class);
|
||||
}
|
||||
BeanDefinitionBuilder matcherBldr = BeanDefinitionBuilder.rootBeanDefinition(this.type);
|
||||
if (this == mvc) {
|
||||
matcherBldr.addConstructorArgValue(new RootBeanDefinition(HandlerMappingIntrospectorFactoryBean.class));
|
||||
}
|
||||
matcherBldr.addConstructorArgValue(path);
|
||||
if (this == mvc) {
|
||||
matcherBldr.addPropertyValue("method", (StringUtils.hasText(method) ? HttpMethod.valueOf(method) : null));
|
||||
matcherBldr.addPropertyValue("servletPath", servletPath);
|
||||
BeanDefinitionBuilder matcherBldr;
|
||||
if (this == MatcherType.path) {
|
||||
matcherBldr = BeanDefinitionBuilder.rootBeanDefinition(PathPatternRequestMatcherFactoryBean.class);
|
||||
matcherBldr.addConstructorArgValue(path);
|
||||
matcherBldr.addPropertyValue("basePath", servletPath);
|
||||
}
|
||||
else {
|
||||
matcherBldr.addConstructorArgValue(method);
|
||||
matcherBldr = BeanDefinitionBuilder.rootBeanDefinition(this.type);
|
||||
matcherBldr.addConstructorArgValue(path);
|
||||
}
|
||||
matcherBldr.addConstructorArgValue(method);
|
||||
if (this == ciRegex) {
|
||||
matcherBldr.addConstructorArgValue(true);
|
||||
}
|
||||
|
@ -89,14 +76,10 @@ public enum MatcherType {
|
|||
return valueOf(elt.getAttribute(ATT_MATCHER_TYPE));
|
||||
}
|
||||
|
||||
return ant;
|
||||
return path;
|
||||
}
|
||||
|
||||
static MatcherType fromElementOrMvc(Element elt) {
|
||||
String matcherTypeName = elt.getAttribute(ATT_MATCHER_TYPE);
|
||||
if (!StringUtils.hasText(matcherTypeName) && mvcPresent) {
|
||||
return MatcherType.mvc;
|
||||
}
|
||||
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.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;
|
||||
|
||||
@Deprecated
|
||||
|
@ -45,10 +44,7 @@ public final class RequestMatcherFactoryBean implements FactoryBean<RequestMatch
|
|||
|
||||
@Override
|
||||
public RequestMatcher getObject() throws Exception {
|
||||
if (this.builder != null) {
|
||||
return this.builder.matcher(this.method, this.path);
|
||||
}
|
||||
return new AntPathRequestMatcher(this.path, (this.method != null) ? this.method.name() : null);
|
||||
return this.builder.matcher(this.method, this.path);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -58,7 +54,8 @@ public final class RequestMatcherFactoryBean implements FactoryBean<RequestMatch
|
|||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
||||
this.builder = context.getBeanProvider(PathPatternRequestMatcher.Builder.class).getIfUnique();
|
||||
this.builder = context.getBeanProvider(PathPatternRequestMatcher.Builder.class)
|
||||
.getIfUnique(PathPatternRequestMatcher::withDefaults);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -58,6 +58,6 @@ abstract class AbstractRequestMatcherDsl {
|
|||
protected abstract class AuthorizationManagerRule(open val rule: AuthorizationManager<RequestAuthorizationContext>)
|
||||
|
||||
protected enum class PatternType {
|
||||
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.intercept.AuthorizationFilter
|
||||
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.RequestMatcher
|
||||
import org.springframework.util.ClassUtils
|
||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector
|
||||
import java.util.function.Supplier
|
||||
|
||||
/**
|
||||
|
@ -69,12 +67,7 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl {
|
|||
private val rolePrefix: String
|
||||
private val roleHierarchy: RoleHierarchy
|
||||
|
||||
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,
|
||||
AuthorizeHttpRequestsDsl::class.java.classLoader)
|
||||
private val PATTERN_TYPE = if (MVC_PRESENT) PatternType.MVC else PatternType.ANT
|
||||
private val PATTERN_TYPE = PatternType.PATH
|
||||
|
||||
/**
|
||||
* Adds a request authorization rule.
|
||||
|
@ -288,17 +281,13 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl {
|
|||
when (rule) {
|
||||
is MatcherAuthorizationManagerRule -> requests.requestMatchers(rule.matcher).access(rule.rule)
|
||||
is PatternAuthorizationManagerRule -> {
|
||||
when (rule.patternType) {
|
||||
PatternType.ANT -> requests.requestMatchers(rule.httpMethod, rule.pattern).access(rule.rule)
|
||||
PatternType.MVC -> {
|
||||
val introspector = requests.applicationContext.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, HandlerMappingIntrospector::class.java)
|
||||
val mvcMatcher = MvcRequestMatcher.Builder(introspector)
|
||||
.servletPath(rule.servletPath)
|
||||
.pattern(rule.pattern)
|
||||
mvcMatcher.setMethod(rule.httpMethod)
|
||||
requests.requestMatchers(mvcMatcher).access(rule.rule)
|
||||
}
|
||||
var builder = requests.applicationContext.getBeanProvider(
|
||||
PathPatternRequestMatcher.Builder::class.java)
|
||||
.getIfUnique(PathPatternRequestMatcher::withDefaults)
|
||||
if (rule.servletPath != null) {
|
||||
builder = builder.basePath(rule.servletPath)
|
||||
}
|
||||
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.security.config.annotation.web.builders.HttpSecurity
|
||||
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.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.
|
||||
|
@ -33,13 +31,7 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector
|
|||
*/
|
||||
class AuthorizeRequestsDsl : AbstractRequestMatcherDsl() {
|
||||
private val authorizationRules = mutableListOf<AuthorizationRule>()
|
||||
|
||||
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
|
||||
private val PATTERN_TYPE = PatternType.PATH;
|
||||
|
||||
/**
|
||||
* Adds a request authorization rule.
|
||||
|
@ -226,17 +218,13 @@ class AuthorizeRequestsDsl : AbstractRequestMatcherDsl() {
|
|||
when (rule) {
|
||||
is MatcherAuthorizationRule -> requests.requestMatchers(rule.matcher).access(rule.rule)
|
||||
is PatternAuthorizationRule -> {
|
||||
when (rule.patternType) {
|
||||
PatternType.ANT -> requests.requestMatchers(rule.httpMethod, rule.pattern).access(rule.rule)
|
||||
PatternType.MVC -> {
|
||||
val introspector = requests.applicationContext.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, HandlerMappingIntrospector::class.java)
|
||||
val mvcMatcher = MvcRequestMatcher.Builder(introspector)
|
||||
.servletPath(rule.servletPath)
|
||||
.pattern(rule.pattern)
|
||||
mvcMatcher.setMethod(rule.httpMethod)
|
||||
requests.requestMatchers(mvcMatcher).access(rule.rule)
|
||||
}
|
||||
var builder = requests.applicationContext.getBeanProvider(
|
||||
PathPatternRequestMatcher.Builder::class.java)
|
||||
.getIfUnique(PathPatternRequestMatcher::withDefaults);
|
||||
if (rule.servletPath != null) {
|
||||
builder = builder.basePath(rule.servletPath)
|
||||
}
|
||||
requests.requestMatchers(builder.matcher(rule.httpMethod, rule.pattern)).access(rule.rule)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,6 @@ operator fun HttpSecurity.invoke(httpConfiguration: HttpSecurityDsl.() -> Unit)
|
|||
*/
|
||||
@SecurityMarker
|
||||
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
|
||||
val context: ApplicationContext = http.getSharedObject(ApplicationContext::class.java)
|
||||
|
|
|
@ -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.web.access.channel.ChannelDecisionManagerImpl
|
||||
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.RequestMatcher
|
||||
import org.springframework.util.ClassUtils
|
||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure [HttpSecurity] channel security using idiomatic
|
||||
|
@ -38,12 +36,7 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector
|
|||
class RequiresChannelDsl : AbstractRequestMatcherDsl() {
|
||||
private val channelSecurityRules = mutableListOf<AuthorizationRule>()
|
||||
|
||||
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,
|
||||
RequiresChannelDsl::class.java.classLoader)
|
||||
private val PATTERN_TYPE = if (MVC_PRESENT) PatternType.MVC else PatternType.ANT
|
||||
private val PATTERN_TYPE = PatternType.PATH
|
||||
|
||||
var channelProcessors: List<ChannelProcessor>? = null
|
||||
|
||||
|
@ -121,17 +114,13 @@ class RequiresChannelDsl : AbstractRequestMatcherDsl() {
|
|||
when (rule) {
|
||||
is MatcherAuthorizationRule -> channelSecurity.requestMatchers(rule.matcher).requires(rule.rule)
|
||||
is PatternAuthorizationRule -> {
|
||||
when (rule.patternType) {
|
||||
PatternType.ANT -> channelSecurity.requestMatchers(rule.pattern).requires(rule.rule)
|
||||
PatternType.MVC -> {
|
||||
val introspector = channelSecurity.applicationContext.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, HandlerMappingIntrospector::class.java)
|
||||
val mvcMatcher = MvcRequestMatcher.Builder(introspector)
|
||||
.servletPath(rule.servletPath)
|
||||
.pattern(rule.pattern)
|
||||
mvcMatcher.setMethod(rule.httpMethod)
|
||||
channelSecurity.requestMatchers(mvcMatcher).requires(rule.rule)
|
||||
}
|
||||
var builder = channelSecurity.applicationContext.getBeanProvider(
|
||||
PathPatternRequestMatcher.Builder::class.java)
|
||||
.getIfUnique(PathPatternRequestMatcher::withDefaults);
|
||||
if (rule.servletPath != null) {
|
||||
builder = builder.basePath(rule.servletPath)
|
||||
}
|
||||
channelSecurity.requestMatchers(builder.matcher(rule.httpMethod, rule.pattern)).requires(rule.rule)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1183,7 +1183,7 @@ hsts-options.attlist &=
|
|||
attribute preload {xsd:boolean}?
|
||||
|
||||
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
|
||||
element cors { cors-options.attlist }
|
||||
cors-options.attlist &=
|
||||
ref?
|
||||
|
|
|
@ -3317,8 +3317,7 @@
|
|||
</xs:attributeGroup>
|
||||
<xs:element name="cors">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Element for configuration of CorsFilter. If no CorsFilter or CorsConfigurationSource is
|
||||
specified a HandlerMappingIntrospector is used as the CorsConfigurationSource
|
||||
<xs:documentation>Element for configuration of CorsFilter. A CorsConfigurationSource must be specified
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<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.RequestMatcher;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.web.util.pattern.PathPattern;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
|
@ -120,7 +121,7 @@ public class FilterChainProxyConfigTests {
|
|||
|
||||
private String getPattern(SecurityFilterChain chain) {
|
||||
RequestMatcher requestMatcher = ((DefaultSecurityFilterChain) chain).getRequestMatcher();
|
||||
return (String) ReflectionTestUtils.getField(requestMatcher, "pattern");
|
||||
return ((PathPattern) ReflectionTestUtils.getField(requestMatcher, "pattern")).getPatternString();
|
||||
}
|
||||
|
||||
private void checkPathAndFilterOrder(FilterChainProxy filterChainProxy) {
|
||||
|
|
|
@ -32,7 +32,7 @@ import org.springframework.security.core.Authentication;
|
|||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
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.util.Assert;
|
||||
|
||||
/**
|
||||
|
@ -52,7 +52,7 @@ public class SecurityConfig {
|
|||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests((requests) -> requests
|
||||
.requestMatchers(new AntPathRequestMatcher("/*")).permitAll())
|
||||
.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/*")).permitAll())
|
||||
.authenticationProvider(authenticationProvider());
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
|
|
|
@ -24,12 +24,11 @@ import org.springframework.context.annotation.Configuration;
|
|||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
||||
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.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
|
@ -88,7 +87,7 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests {
|
|||
http
|
||||
.authorizeRequests((requests) -> requests
|
||||
.anyRequest().authenticated()
|
||||
.requestMatchers(new AntPathRequestMatcher("/demo/**")).permitAll());
|
||||
.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/demo/**")).permitAll());
|
||||
return http.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
@ -100,12 +99,17 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests {
|
|||
static class MvcMatchersAfterAnyRequestConfig {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
||||
PathPatternRequestMatcherBuilderFactoryBean pathPattern() {
|
||||
return new PathPatternRequestMatcherBuilderFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests((requests) -> requests
|
||||
.anyRequest().authenticated()
|
||||
.requestMatchers(new MvcRequestMatcher(introspector, "/demo/**")).permitAll());
|
||||
.requestMatchers(builder.matcher("/demo/**")).permitAll());
|
||||
return http.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
@ -156,7 +160,7 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests {
|
|||
http
|
||||
.authorizeRequests((requests) -> requests
|
||||
.anyRequest().authenticated()
|
||||
.requestMatchers(new AntPathRequestMatcher("/**")).permitAll());
|
||||
.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/**")).permitAll());
|
||||
return http.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
|
|
@ -21,9 +21,10 @@ import java.util.List;
|
|||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.http.HttpMethod;
|
||||
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 static org.assertj.core.api.Assertions.assertThat;
|
||||
|
@ -41,22 +42,25 @@ public class AbstractRequestMatcherRegistryNoMvcTests {
|
|||
@BeforeEach
|
||||
public void setUp() {
|
||||
this.matcherRegistry = new TestRequestMatcherRegistry();
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
context.refresh();
|
||||
this.matcherRegistry.setApplicationContext(context);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestMatchersWhenPatternAndMvcNotPresentThenReturnAntPathRequestMatcherType() {
|
||||
public void requestMatchersWhenPatternAndMvcNotPresentThenReturnPathPatternRequestMatcherType() {
|
||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers("/path");
|
||||
assertThat(requestMatchers).isNotEmpty();
|
||||
assertThat(requestMatchers).hasSize(1);
|
||||
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(AntPathRequestMatcher.class);
|
||||
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestMatchersWhenHttpMethodAndPatternAndMvcNotPresentThenReturnAntPathRequestMatcherType() {
|
||||
public void requestMatchersWhenHttpMethodAndPatternAndMvcNotPresentThenReturnPathPatternRequestMatcherType() {
|
||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers(HttpMethod.GET, "/path");
|
||||
assertThat(requestMatchers).isNotEmpty();
|
||||
assertThat(requestMatchers).hasSize(1);
|
||||
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(AntPathRequestMatcher.class);
|
||||
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -64,7 +68,7 @@ public class AbstractRequestMatcherRegistryNoMvcTests {
|
|||
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers(HttpMethod.GET);
|
||||
assertThat(requestMatchers).isNotEmpty();
|
||||
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>> {
|
||||
|
|
|
@ -16,47 +16,30 @@
|
|||
|
||||
package org.springframework.security.config.annotation.web;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jakarta.servlet.DispatcherType;
|
||||
import jakarta.servlet.Servlet;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
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.test.SpringTestContext;
|
||||
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.servlet.util.matcher.PathPatternRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
||||
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.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
||||
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.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
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}.
|
||||
|
@ -86,9 +69,13 @@ public class AbstractRequestMatcherRegistryTests {
|
|||
ObjectProvider<ObjectPostProcessor<Object>> given = this.context.getBeanProvider(type);
|
||||
given(given).willReturn(postProcessors);
|
||||
given(postProcessors.getObject()).willReturn(NO_OP_OBJECT_POST_PROCESSOR);
|
||||
given(this.context.getServletContext()).willReturn(MockServletContext.mvc());
|
||||
given(this.context.getBeanProvider(any(Class.class))).willReturn(new ObjectProvider<>() {
|
||||
@Override
|
||||
public Stream<Object> stream() {
|
||||
return Stream.of();
|
||||
}
|
||||
});
|
||||
this.matcherRegistry.setApplicationContext(this.context);
|
||||
mockMvcIntrospector(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -110,24 +97,25 @@ public class AbstractRequestMatcherRegistryTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void antMatchersWhenHttpMethodAndPatternParamsThenReturnAntPathRequestMatcherType() {
|
||||
public void pathPatternWhenHttpMethodAndPatternParamsThenReturnPathPatternRequestMatcherType() {
|
||||
List<RequestMatcher> requestMatchers = this.matcherRegistry
|
||||
.requestMatchers(new AntPathRequestMatcher("/a.*", HttpMethod.GET.name()));
|
||||
.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.GET, "/a.*"));
|
||||
assertThat(requestMatchers).isNotEmpty();
|
||||
assertThat(requestMatchers).hasSize(1);
|
||||
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(AntPathRequestMatcher.class);
|
||||
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void antMatchersWhenPatternParamThenReturnAntPathRequestMatcherType() {
|
||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers(new AntPathRequestMatcher("/a.*"));
|
||||
public void pathPatternWhenPatternParamThenReturnPathPatternRequestMatcherType() {
|
||||
List<RequestMatcher> requestMatchers = this.matcherRegistry
|
||||
.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/a.*"));
|
||||
assertThat(requestMatchers).isNotEmpty();
|
||||
assertThat(requestMatchers).hasSize(1);
|
||||
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(AntPathRequestMatcher.class);
|
||||
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dispatcherTypeMatchersWhenHttpMethodAndPatternParamsThenReturnAntPathRequestMatcherType() {
|
||||
public void dispatcherTypeMatchersWhenHttpMethodAndPatternParamsThenReturnPathPatternRequestMatcherType() {
|
||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.dispatcherTypeMatchers(HttpMethod.GET,
|
||||
DispatcherType.ASYNC);
|
||||
assertThat(requestMatchers).isNotEmpty();
|
||||
|
@ -136,7 +124,7 @@ public class AbstractRequestMatcherRegistryTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void dispatcherMatchersWhenPatternParamThenReturnAntPathRequestMatcherType() {
|
||||
public void dispatcherMatchersWhenPatternParamThenReturnPathPatternRequestMatcherType() {
|
||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.dispatcherTypeMatchers(DispatcherType.INCLUDE);
|
||||
assertThat(requestMatchers).isNotEmpty();
|
||||
assertThat(requestMatchers).hasSize(1);
|
||||
|
@ -144,252 +132,36 @@ public class AbstractRequestMatcherRegistryTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void requestMatchersWhenPatternAndMvcPresentThenReturnMvcRequestMatcherType() {
|
||||
public void requestMatchersWhenPatternAndMvcPresentThenReturnPathPatternRequestMatcherType() {
|
||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers("/path");
|
||||
assertThat(requestMatchers).isNotEmpty();
|
||||
assertThat(requestMatchers).hasSize(1);
|
||||
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(MvcRequestMatcher.class);
|
||||
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestMatchersWhenHttpMethodAndPatternAndMvcPresentThenReturnMvcRequestMatcherType() {
|
||||
public void requestMatchersWhenHttpMethodAndPatternAndMvcPresentThenReturnPathPatternRequestMatcherType() {
|
||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers(HttpMethod.GET, "/path");
|
||||
assertThat(requestMatchers).isNotEmpty();
|
||||
assertThat(requestMatchers).hasSize(1);
|
||||
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(MvcRequestMatcher.class);
|
||||
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestMatchersWhenHttpMethodAndMvcPresentThenReturnMvcRequestMatcherType() {
|
||||
public void requestMatchersWhenHttpMethodAndMvcPresentThenReturnPathPatternRequestMatcherType() {
|
||||
List<RequestMatcher> requestMatchers = this.matcherRegistry.requestMatchers(HttpMethod.GET);
|
||||
assertThat(requestMatchers).isNotEmpty();
|
||||
assertThat(requestMatchers).hasSize(1);
|
||||
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(MvcRequestMatcher.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);
|
||||
assertThat(requestMatchers.get(0)).isExactlyInstanceOf(PathPatternRequestMatcher.class);
|
||||
}
|
||||
|
||||
private static class TestRequestMatcherRegistry extends AbstractRequestMatcherRegistry<List<RequestMatcher>> {
|
||||
|
||||
@Override
|
||||
public List<RequestMatcher> requestMatchers(RequestMatcher... requestMatchers) {
|
||||
return unwrap(super.requestMatchers(requestMatchers));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<RequestMatcher> chainRequestMatchers(List<RequestMatcher> 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
|
||||
|
|
|
@ -39,7 +39,7 @@ import org.springframework.security.core.userdetails.PasswordEncodedUser;
|
|||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
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.test.web.servlet.MockMvc;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
@ -150,8 +150,8 @@ public class HttpConfigurationTests {
|
|||
// @formatter:off
|
||||
http
|
||||
.securityMatchers((security) -> security
|
||||
.requestMatchers(new AntPathRequestMatcher("/api/**"))
|
||||
.requestMatchers(new AntPathRequestMatcher("/oauth/**")))
|
||||
.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/api/**"))
|
||||
.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/oauth/**")))
|
||||
.authorizeRequests((requests) -> requests
|
||||
.anyRequest().hasRole("USER"))
|
||||
.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.context.NullSecurityContextRepository;
|
||||
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.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
@ -195,13 +195,13 @@ public class NamespaceHttpTests {
|
|||
}
|
||||
|
||||
@Test // http@request-matcher-ref ant
|
||||
public void configureWhenAntPatternMatchingThenAntPathRequestMatcherUsed() {
|
||||
public void configureWhenAntPatternMatchingThenPathPatternRequestMatcherUsed() {
|
||||
this.spring.register(RequestMatcherAntConfig.class).autowire();
|
||||
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
|
||||
assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class);
|
||||
DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains()
|
||||
.get(0);
|
||||
assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class);
|
||||
assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(PathPatternRequestMatcher.class);
|
||||
}
|
||||
|
||||
@Test // http@request-matcher-ref regex
|
||||
|
@ -226,21 +226,21 @@ public class NamespaceHttpTests {
|
|||
}
|
||||
|
||||
@Test // http@security=none
|
||||
public void configureWhenIgnoredAntPatternsThenAntPathRequestMatcherUsedWithNoFilters() {
|
||||
public void configureWhenIgnoredAntPatternsThenPathPatternRequestMatcherUsedWithNoFilters() {
|
||||
this.spring.register(SecurityNoneConfig.class).autowire();
|
||||
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
|
||||
assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class);
|
||||
DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains()
|
||||
.get(0);
|
||||
assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class);
|
||||
assertThat(((AntPathRequestMatcher) securityFilterChain.getRequestMatcher()).getPattern())
|
||||
.isEqualTo("/resources/**");
|
||||
assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(PathPatternRequestMatcher.class);
|
||||
assertThat(securityFilterChain.getRequestMatcher())
|
||||
.isEqualTo(PathPatternRequestMatcher.withDefaults().matcher("/resources/**"));
|
||||
assertThat(securityFilterChain.getFilters()).isEmpty();
|
||||
assertThat(filterChainProxy.getFilterChains().get(1)).isInstanceOf(DefaultSecurityFilterChain.class);
|
||||
securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains().get(1);
|
||||
assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class);
|
||||
assertThat(((AntPathRequestMatcher) securityFilterChain.getRequestMatcher()).getPattern())
|
||||
.isEqualTo("/public/**");
|
||||
assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(PathPatternRequestMatcher.class);
|
||||
assertThat(securityFilterChain.getRequestMatcher())
|
||||
.isEqualTo(PathPatternRequestMatcher.withDefaults().matcher("/public/**"));
|
||||
assertThat(securityFilterChain.getFilters()).isEmpty();
|
||||
}
|
||||
|
||||
|
@ -482,7 +482,7 @@ public class NamespaceHttpTests {
|
|||
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.securityMatcher(new AntPathRequestMatcher("/api/**"));
|
||||
.securityMatcher(PathPatternRequestMatcher.withDefaults().matcher("/api/**"));
|
||||
return http.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
@ -534,8 +534,9 @@ public class NamespaceHttpTests {
|
|||
|
||||
@Bean
|
||||
WebSecurityCustomizer webSecurityCustomizer() {
|
||||
PathPatternRequestMatcher.Builder builder = PathPatternRequestMatcher.withDefaults();
|
||||
return (web) -> web.ignoring()
|
||||
.requestMatchers(new AntPathRequestMatcher("/resources/**"), new AntPathRequestMatcher("/public/**"));
|
||||
.requestMatchers(builder.matcher("/resources/**"), builder.matcher("/public/**"));
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
|
@ -31,7 +31,7 @@ import org.springframework.security.web.UnreachableFilterChainException;
|
|||
import org.springframework.security.web.access.ExceptionTranslationFilter;
|
||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
||||
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.RequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatchers;
|
||||
|
@ -49,6 +49,8 @@ public class WebSecurityFilterChainValidatorTests {
|
|||
|
||||
private final WebSecurityFilterChainValidator validator = new WebSecurityFilterChainValidator();
|
||||
|
||||
private final PathPatternRequestMatcher.Builder builder = PathPatternRequestMatcher.withDefaults();
|
||||
|
||||
@Mock
|
||||
private AnonymousAuthenticationFilter authenticationFilter;
|
||||
|
||||
|
@ -60,7 +62,7 @@ public class WebSecurityFilterChainValidatorTests {
|
|||
|
||||
@Test
|
||||
void validateWhenFilterSecurityInterceptorConfiguredThenValidates() {
|
||||
SecurityFilterChain chain = new DefaultSecurityFilterChain(AntPathRequestMatcher.antMatcher("/api"),
|
||||
SecurityFilterChain chain = new DefaultSecurityFilterChain(this.builder.matcher("/api"),
|
||||
this.authenticationFilter, this.exceptionTranslationFilter, this.authorizationInterceptor);
|
||||
FilterChainProxy proxy = new FilterChainProxy(List.of(chain));
|
||||
|
||||
|
@ -69,7 +71,7 @@ public class WebSecurityFilterChainValidatorTests {
|
|||
|
||||
@Test
|
||||
void validateWhenAnyRequestMatcherIsPresentThenUnreachableFilterChainException() {
|
||||
SecurityFilterChain chain1 = new DefaultSecurityFilterChain(AntPathRequestMatcher.antMatcher("/api"),
|
||||
SecurityFilterChain chain1 = new DefaultSecurityFilterChain(this.builder.matcher("/api"),
|
||||
this.authenticationFilter, this.exceptionTranslationFilter, this.authorizationInterceptor);
|
||||
SecurityFilterChain chain2 = new DefaultSecurityFilterChain(AnyRequestMatcher.INSTANCE,
|
||||
this.authenticationFilter, this.exceptionTranslationFilter, this.authorizationInterceptor);
|
||||
|
@ -84,9 +86,9 @@ public class WebSecurityFilterChainValidatorTests {
|
|||
|
||||
@Test
|
||||
void validateWhenSameRequestMatchersArePresentThenUnreachableFilterChainException() {
|
||||
SecurityFilterChain chain1 = new DefaultSecurityFilterChain(AntPathRequestMatcher.antMatcher("/api"),
|
||||
SecurityFilterChain chain1 = new DefaultSecurityFilterChain(this.builder.matcher("/api"),
|
||||
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);
|
||||
List<SecurityFilterChain> chains = new ArrayList<>();
|
||||
chains.add(chain2);
|
||||
|
@ -99,10 +101,12 @@ public class WebSecurityFilterChainValidatorTests {
|
|||
|
||||
@Test
|
||||
void validateWhenSameComposedRequestMatchersArePresentThenUnreachableFilterChainException() {
|
||||
RequestMatcher matcher1 = RequestMatchers.anyOf(RequestMatchers.allOf(AntPathRequestMatcher.antMatcher("/api"),
|
||||
AntPathRequestMatcher.antMatcher("*.do")), AntPathRequestMatcher.antMatcher("/admin"));
|
||||
RequestMatcher matcher2 = RequestMatchers.anyOf(RequestMatchers.allOf(AntPathRequestMatcher.antMatcher("/api"),
|
||||
AntPathRequestMatcher.antMatcher("*.do")), AntPathRequestMatcher.antMatcher("/admin"));
|
||||
RequestMatcher matcher1 = RequestMatchers.anyOf(
|
||||
RequestMatchers.allOf(this.builder.matcher("/api"), this.builder.matcher("/*.do")),
|
||||
this.builder.matcher("/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,
|
||||
this.exceptionTranslationFilter, this.authorizationInterceptor);
|
||||
SecurityFilterChain chain2 = new DefaultSecurityFilterChain(matcher2, this.authenticationFilter,
|
||||
|
|
|
@ -37,17 +37,17 @@ import org.springframework.mock.web.MockHttpServletResponse;
|
|||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
|
||||
import org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean;
|
||||
import org.springframework.security.core.userdetails.PasswordEncodedUser;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
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.RestController;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
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.springframework.security.config.Customizer.withDefaults;
|
||||
|
@ -130,8 +130,13 @@ public class WebSecurityTests {
|
|||
static class MvcMatcherConfig {
|
||||
|
||||
@Bean
|
||||
WebSecurityCustomizer webSecurityCustomizer(HandlerMappingIntrospector introspector) {
|
||||
return (web) -> web.ignoring().requestMatchers(new MvcRequestMatcher(introspector, "/path"));
|
||||
PathPatternRequestMatcherBuilderFactoryBean pathPatternRequestMatcherBuilder() {
|
||||
return new PathPatternRequestMatcherBuilderFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
WebSecurityCustomizer webSecurityCustomizer(PathPatternRequestMatcher.Builder builder) {
|
||||
return (web) -> web.ignoring().requestMatchers(builder.matcher("/path"));
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
@ -168,9 +173,15 @@ public class WebSecurityTests {
|
|||
static class MvcMatcherServletPathConfig {
|
||||
|
||||
@Bean
|
||||
WebSecurityCustomizer webSecurityCustomizer(HandlerMappingIntrospector introspector) {
|
||||
MvcRequestMatcher.Builder builder = new MvcRequestMatcher.Builder(introspector).servletPath("/spring");
|
||||
return (web) -> web.ignoring().requestMatchers(builder.pattern("/path")).requestMatchers("/notused");
|
||||
PathPatternRequestMatcherBuilderFactoryBean pathPatternRequestMatcherBuilder() {
|
||||
return new PathPatternRequestMatcherBuilderFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
WebSecurityCustomizer webSecurityCustomizer(PathPatternRequestMatcher.Builder builder) {
|
||||
return (web) -> web.ignoring()
|
||||
.requestMatchers(builder.basePath("/spring").matcher("/path"))
|
||||
.requestMatchers("/notused");
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
|
@ -26,20 +26,19 @@ import org.springframework.security.authentication.TestAuthentication;
|
|||
import org.springframework.security.config.test.SpringTestContext;
|
||||
import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners;
|
||||
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.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
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.Mockito.mock;
|
||||
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}.
|
||||
*
|
||||
* @author Rob Winch
|
||||
|
@ -59,20 +58,8 @@ public class AuthorizationManagerWebInvocationPrivilegeEvaluatorConfigTests {
|
|||
WebInvocationPrivilegeEvaluator wipe;
|
||||
|
||||
@Test
|
||||
void mvcEnabledConfigThenHandlerMappingIntrospectorRequestTransformerBeanExists() {
|
||||
this.spring.register(MvcEnabledConfig.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();
|
||||
void webAndTransformerThenWIPEDelegatesToTransformer() {
|
||||
this.spring.register(WebConfig.class, TransformerConfig.class).autowire();
|
||||
|
||||
this.wipe.isAllowed("/uri", TestAuthentication.authenticatedUser());
|
||||
|
||||
|
@ -90,15 +77,8 @@ public class AuthorizationManagerWebInvocationPrivilegeEvaluatorConfigTests {
|
|||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
@EnableWebSecurity
|
||||
static class MvcEnabledConfig {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class MvcNotEnabledConfig {
|
||||
static class WebConfig {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -63,7 +63,6 @@ import org.springframework.security.web.access.RequestMatcherDelegatingWebInvoca
|
|||
import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
|
||||
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.util.ClassUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
@ -106,14 +105,13 @@ public class WebSecurityConfigurationTests {
|
|||
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
|
||||
List<SecurityFilterChain> filterChains = filterChainProxy.getFilterChains();
|
||||
assertThat(filterChains).hasSize(4);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
||||
request.setServletPath("/role1/**");
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/role1/**");
|
||||
assertThat(filterChains.get(0).matches(request)).isTrue();
|
||||
request.setServletPath("/role2/**");
|
||||
request = new MockHttpServletRequest("GET", "/role2/**");
|
||||
assertThat(filterChains.get(1).matches(request)).isTrue();
|
||||
request.setServletPath("/role3/**");
|
||||
request = new MockHttpServletRequest("GET", "/role3/**");
|
||||
assertThat(filterChains.get(2).matches(request)).isTrue();
|
||||
request.setServletPath("/**");
|
||||
request = new MockHttpServletRequest("GET", "/**");
|
||||
assertThat(filterChains.get(3).matches(request)).isTrue();
|
||||
}
|
||||
|
||||
|
@ -123,10 +121,9 @@ public class WebSecurityConfigurationTests {
|
|||
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
|
||||
List<SecurityFilterChain> filterChains = filterChainProxy.getFilterChains();
|
||||
assertThat(filterChains).hasSize(2);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
||||
request.setServletPath("/role1/**");
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/role1/**");
|
||||
assertThat(filterChains.get(0).matches(request)).isTrue();
|
||||
request.setServletPath("/role2/**");
|
||||
request = new MockHttpServletRequest("GET", "/role2/**");
|
||||
assertThat(filterChains.get(1).matches(request)).isTrue();
|
||||
}
|
||||
|
||||
|
@ -240,14 +237,13 @@ public class WebSecurityConfigurationTests {
|
|||
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
|
||||
List<SecurityFilterChain> filterChains = filterChainProxy.getFilterChains();
|
||||
assertThat(filterChains).hasSize(3);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
||||
request.setServletPath("/ignore1");
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/ignore1");
|
||||
assertThat(filterChains.get(0).matches(request)).isTrue();
|
||||
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).getFilters()).isEmpty();
|
||||
request.setServletPath("/test/**");
|
||||
request = new MockHttpServletRequest("GET", "/test/**");
|
||||
assertThat(filterChains.get(2).matches(request)).isTrue();
|
||||
}
|
||||
|
||||
|
@ -257,16 +253,15 @@ public class WebSecurityConfigurationTests {
|
|||
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
|
||||
List<SecurityFilterChain> filterChains = filterChainProxy.getFilterChains();
|
||||
assertThat(filterChains).hasSize(3);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
||||
request.setServletPath("/ignore1");
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/ignore1");
|
||||
assertThat(filterChains.get(0).matches(request)).isTrue();
|
||||
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).getFilters()).isEmpty();
|
||||
request.setServletPath("/role1/**");
|
||||
request = new MockHttpServletRequest("GET", "/role1/**");
|
||||
assertThat(filterChains.get(2).matches(request)).isTrue();
|
||||
request.setServletPath("/test/**");
|
||||
request = new MockHttpServletRequest("GET", "/test/**");
|
||||
assertThat(filterChains.get(2).matches(request)).isFalse();
|
||||
}
|
||||
|
||||
|
@ -276,11 +271,10 @@ public class WebSecurityConfigurationTests {
|
|||
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
|
||||
List<SecurityFilterChain> filterChains = filterChainProxy.getFilterChains();
|
||||
assertThat(filterChains).hasSize(3);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
||||
request.setServletPath("/ignore1");
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/ignore1");
|
||||
assertThat(filterChains.get(0).matches(request)).isTrue();
|
||||
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).getFilters()).isEmpty();
|
||||
}
|
||||
|
@ -420,7 +414,7 @@ public class WebSecurityConfigurationTests {
|
|||
SecurityFilterChain filterChain1(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
return http
|
||||
.securityMatcher(new AntPathRequestMatcher("/role1/**"))
|
||||
.securityMatcher(PathPatternRequestMatcher.withDefaults().matcher("/role1/**"))
|
||||
.authorizeRequests((authorize) -> authorize
|
||||
.anyRequest().hasRole("1")
|
||||
)
|
||||
|
@ -433,7 +427,7 @@ public class WebSecurityConfigurationTests {
|
|||
SecurityFilterChain filterChain2(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
return http
|
||||
.securityMatcher(new AntPathRequestMatcher("/role2/**"))
|
||||
.securityMatcher(PathPatternRequestMatcher.withDefaults().matcher("/role2/**"))
|
||||
.authorizeRequests((authorize) -> authorize
|
||||
.anyRequest().hasRole("2")
|
||||
)
|
||||
|
@ -446,7 +440,7 @@ public class WebSecurityConfigurationTests {
|
|||
SecurityFilterChain filterChain3(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
return http
|
||||
.securityMatcher(new AntPathRequestMatcher("/role3/**"))
|
||||
.securityMatcher(PathPatternRequestMatcher.withDefaults().matcher("/role3/**"))
|
||||
.authorizeRequests((authorize) -> authorize
|
||||
.anyRequest().hasRole("3")
|
||||
)
|
||||
|
@ -477,7 +471,7 @@ public class WebSecurityConfigurationTests {
|
|||
SecurityFilterChain securityFilterChain1(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
return http
|
||||
.securityMatcher(new AntPathRequestMatcher("/role1/**"))
|
||||
.securityMatcher(PathPatternRequestMatcher.withDefaults().matcher("/role1/**"))
|
||||
.authorizeRequests((authorize) -> authorize
|
||||
.anyRequest().hasRole("1")
|
||||
)
|
||||
|
@ -734,7 +728,7 @@ public class WebSecurityConfigurationTests {
|
|||
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
return http
|
||||
.securityMatcher(new AntPathRequestMatcher("/role1/**"))
|
||||
.securityMatcher(PathPatternRequestMatcher.withDefaults().matcher("/role1/**"))
|
||||
.authorizeRequests((authorize) -> authorize
|
||||
.anyRequest().hasRole("1")
|
||||
)
|
||||
|
@ -773,7 +767,7 @@ public class WebSecurityConfigurationTests {
|
|||
public SecurityFilterChain path1(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/path1/**")))
|
||||
.securityMatchers((requests) -> requests.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/path1/**")))
|
||||
.authorizeRequests((requests) -> requests.anyRequest().authenticated());
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
|
@ -797,7 +791,7 @@ public class WebSecurityConfigurationTests {
|
|||
public SecurityFilterChain path1(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/path1/**")))
|
||||
.securityMatchers((requests) -> requests.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/path1/**")))
|
||||
.authorizeRequests((requests) -> requests.anyRequest().authenticated());
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
|
@ -822,7 +816,7 @@ public class WebSecurityConfigurationTests {
|
|||
public SecurityFilterChain notAuthorized(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/user")))
|
||||
.securityMatchers((requests) -> requests.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/user")))
|
||||
.authorizeRequests((requests) -> requests.anyRequest().hasRole("USER"));
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
|
@ -833,7 +827,7 @@ public class WebSecurityConfigurationTests {
|
|||
public SecurityFilterChain path1(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/admin")))
|
||||
.securityMatchers((requests) -> requests.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/admin")))
|
||||
.authorizeRequests((requests) -> requests.anyRequest().hasRole("ADMIN"));
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
|
@ -864,7 +858,7 @@ public class WebSecurityConfigurationTests {
|
|||
public SecurityFilterChain notAuthorized(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/user")))
|
||||
.securityMatchers((requests) -> requests.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/user")))
|
||||
.authorizeRequests((requests) -> requests.anyRequest().hasRole("USER"));
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
|
@ -875,7 +869,7 @@ public class WebSecurityConfigurationTests {
|
|||
public SecurityFilterChain admin(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.securityMatchers((requests) -> requests.requestMatchers(new AntPathRequestMatcher("/admin")))
|
||||
.securityMatchers((requests) -> requests.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/admin")))
|
||||
.authorizeRequests((requests) -> requests.anyRequest().hasRole("ADMIN"));
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
|
|
|
@ -22,7 +22,7 @@ import org.junit.jupiter.api.BeforeEach;
|
|||
import org.junit.jupiter.api.Test;
|
||||
|
||||
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.RequestMatcher;
|
||||
|
||||
|
@ -55,19 +55,20 @@ public class AbstractConfigAttributeRequestMatcherRegistryTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testGetRequestMatcherIsTypeAntPathRequestMatcher() {
|
||||
public void testGetRequestMatcherIsTypePathPatternRequestMatcher() {
|
||||
List<RequestMatcher> requestMatchers = this.registry
|
||||
.requestMatchers(new AntPathRequestMatcher("/a.*", HttpMethod.GET.name()));
|
||||
.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.GET, "/a.*"));
|
||||
for (RequestMatcher requestMatcher : requestMatchers) {
|
||||
assertThat(requestMatcher).isInstanceOf(AntPathRequestMatcher.class);
|
||||
assertThat(requestMatcher).isInstanceOf(PathPatternRequestMatcher.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestMatcherIsTypeAntPathRequestMatcher() {
|
||||
List<RequestMatcher> requestMatchers = this.registry.requestMatchers(new AntPathRequestMatcher("/a.*"));
|
||||
public void testRequestMatcherIsTypePathPatternRequestMatcher() {
|
||||
List<RequestMatcher> requestMatchers = this.registry
|
||||
.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/a.*"));
|
||||
for (RequestMatcher requestMatcher : requestMatchers) {
|
||||
assertThat(requestMatcher).isInstanceOf(AntPathRequestMatcher.class);
|
||||
assertThat(requestMatcher).isInstanceOf(PathPatternRequestMatcher.class);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,6 @@ import org.springframework.security.web.access.expression.WebExpressionAuthoriza
|
|||
import org.springframework.security.web.access.intercept.AuthorizationFilter;
|
||||
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
|
||||
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.stereotype.Component;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
@ -81,7 +80,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
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.assertThatExceptionOfType;
|
||||
|
@ -148,7 +146,7 @@ public class AuthorizeHttpRequestsConfigurerTests {
|
|||
public void configureWhenMvcMatcherAfterAnyRequestThenException() {
|
||||
assertThatExceptionOfType(BeanCreationException.class)
|
||||
.isThrownBy(() -> this.spring.register(AfterAnyRequestConfig.class).autowire())
|
||||
.withMessageContaining("Can't configure mvcMatchers after anyRequest");
|
||||
.withMessageContaining("Can't configure requestMatchers after anyRequest");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -689,7 +687,7 @@ public class AuthorizeHttpRequestsConfigurerTests {
|
|||
|
||||
@Test
|
||||
public void requestMatchersWhenMultipleDispatcherServletsAndPathBeanThenAllows() throws Exception {
|
||||
this.spring.register(MvcRequestMatcherBuilderConfig.class, BasicController.class)
|
||||
this.spring.register(PathPatternRequestMatcherBuilderConfig.class, BasicController.class)
|
||||
.postProcessor((context) -> context.getServletContext()
|
||||
.addServlet("otherDispatcherServlet", DispatcherServlet.class)
|
||||
.addMapping("/mvc"))
|
||||
|
@ -1063,13 +1061,16 @@ public class AuthorizeHttpRequestsConfigurerTests {
|
|||
static class ServletPathConfig {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector)
|
||||
.servletPath("/spring");
|
||||
PathPatternRequestMatcherBuilderFactoryBean pathPattern() {
|
||||
return new PathPatternRequestMatcherBuilderFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||
// @formatter:off
|
||||
return http
|
||||
.authorizeHttpRequests((authorize) -> authorize
|
||||
.requestMatchers(mvcMatcherBuilder.pattern("/")).hasRole("ADMIN")
|
||||
.requestMatchers(builder.basePath("/spring").matcher("/")).hasRole("ADMIN")
|
||||
)
|
||||
.build();
|
||||
// @formatter:on
|
||||
|
@ -1358,7 +1359,7 @@ public class AuthorizeHttpRequestsConfigurerTests {
|
|||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableWebMvc
|
||||
static class MvcRequestMatcherBuilderConfig {
|
||||
static class PathPatternRequestMatcherBuilderConfig {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain security(HttpSecurity http) throws Exception {
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
|
|||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextImpl;
|
||||
|
@ -42,13 +43,12 @@ import org.springframework.security.web.FilterChainProxy;
|
|||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||
import org.springframework.security.web.servlet.MockServletContext;
|
||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
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.mockito.Mockito.spy;
|
||||
|
@ -111,10 +111,12 @@ public class AuthorizeRequestsTests {
|
|||
public void antMatchersPathVariables() throws Exception {
|
||||
loadConfig(AntPatchersPathVariables.class);
|
||||
this.request.setServletPath("/user/user");
|
||||
this.request.setRequestURI("/user/user");
|
||||
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
||||
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
||||
this.setup();
|
||||
this.request.setServletPath("/user/deny");
|
||||
this.request.setRequestURI("/user/deny");
|
||||
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
||||
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
|
||||
}
|
||||
|
@ -124,10 +126,12 @@ public class AuthorizeRequestsTests {
|
|||
public void antMatchersPathVariablesCaseInsensitive() throws Exception {
|
||||
loadConfig(AntPatchersPathVariables.class);
|
||||
this.request.setServletPath("/USER/user");
|
||||
this.request.setRequestURI("/USER/user");
|
||||
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
||||
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
||||
this.setup();
|
||||
this.request.setServletPath("/USER/deny");
|
||||
this.request.setRequestURI("/USER/deny");
|
||||
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
||||
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
|
||||
}
|
||||
|
@ -137,10 +141,12 @@ public class AuthorizeRequestsTests {
|
|||
public void antMatchersPathVariablesCaseInsensitiveCamelCaseVariables() throws Exception {
|
||||
loadConfig(AntMatchersPathVariablesCamelCaseVariables.class);
|
||||
this.request.setServletPath("/USER/user");
|
||||
this.request.setRequestURI("/USER/user");
|
||||
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
||||
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
||||
this.setup();
|
||||
this.request.setServletPath("/USER/deny");
|
||||
this.request.setRequestURI("/USER/deny");
|
||||
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
|
||||
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
|
||||
}
|
||||
|
@ -199,7 +205,7 @@ public class AuthorizeRequestsTests {
|
|||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests((requests) -> requests
|
||||
.requestMatchers(new AntPathRequestMatcher("/**", HttpMethod.POST.name())).denyAll());
|
||||
.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.POST, "/**")).denyAll());
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
}
|
||||
|
@ -220,7 +226,7 @@ public class AuthorizeRequestsTests {
|
|||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests((authorize) -> authorize
|
||||
.requestMatchers(new AntPathRequestMatcher("/**", HttpMethod.POST.name())).denyAll()
|
||||
.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.POST, "/**")).denyAll()
|
||||
);
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
|
@ -239,10 +245,13 @@ public class AuthorizeRequestsTests {
|
|||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
PathPatternParser parser = new PathPatternParser();
|
||||
parser.setCaseSensitive(false);
|
||||
PathPatternRequestMatcher.Builder builder = PathPatternRequestMatcher.withPathPatternParser(parser);
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests((requests) -> requests
|
||||
.requestMatchers(new AntPathRequestMatcher("/user/{user}", null, false)).access("#user == 'user'")
|
||||
.requestMatchers(builder.matcher("/user/{user}")).access("#user == 'user'")
|
||||
.anyRequest().denyAll());
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
|
@ -261,10 +270,13 @@ public class AuthorizeRequestsTests {
|
|||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
PathPatternParser parser = new PathPatternParser();
|
||||
parser.setCaseSensitive(false);
|
||||
PathPatternRequestMatcher.Builder builder = PathPatternRequestMatcher.withPathPatternParser(parser);
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests((requests) -> requests
|
||||
.requestMatchers(new AntPathRequestMatcher("/user/{userName}", null, false)).access("#userName == 'user'")
|
||||
.requestMatchers(builder.matcher("/user/{userName}")).access("#userName == 'user'")
|
||||
.anyRequest().denyAll());
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
|
@ -378,14 +390,18 @@ public class AuthorizeRequestsTests {
|
|||
static class MvcMatcherServletPathConfig {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector)
|
||||
.servletPath("/spring");
|
||||
PathPatternRequestMatcherBuilderFactoryBean pathPattern() {
|
||||
return new PathPatternRequestMatcherBuilderFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||
PathPatternRequestMatcher.Builder spring = builder.basePath("/spring");
|
||||
// @formatter:off
|
||||
http
|
||||
.httpBasic(withDefaults())
|
||||
.authorizeRequests((requests) -> requests
|
||||
.requestMatchers(mvcMatcherBuilder.pattern("/path")).denyAll());
|
||||
.requestMatchers(spring.matcher("/path")).denyAll());
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
}
|
||||
|
@ -413,14 +429,18 @@ public class AuthorizeRequestsTests {
|
|||
static class MvcMatcherServletPathInLambdaConfig {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector)
|
||||
.servletPath("/spring");
|
||||
PathPatternRequestMatcherBuilderFactoryBean pathPattern() {
|
||||
return new PathPatternRequestMatcherBuilderFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||
PathPatternRequestMatcher.Builder spring = builder.basePath("/spring");
|
||||
// @formatter:off
|
||||
http
|
||||
.httpBasic(withDefaults())
|
||||
.authorizeRequests((authorize) -> authorize
|
||||
.requestMatchers(mvcMatcherBuilder.pattern("/path")).denyAll()
|
||||
.requestMatchers(spring.matcher("/path")).denyAll()
|
||||
);
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
|
|
|
@ -28,7 +28,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
|
|||
import org.springframework.security.config.test.SpringTestContext;
|
||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||
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.test.web.servlet.MockMvc;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
@ -109,7 +109,7 @@ public class CsrfConfigurerIgnoringRequestMatchersTests {
|
|||
// @formatter:off
|
||||
http
|
||||
.csrf((csrf) -> csrf
|
||||
.requireCsrfProtectionMatcher(new AntPathRequestMatcher("/path"))
|
||||
.requireCsrfProtectionMatcher(PathPatternRequestMatcher.withDefaults().matcher("/path"))
|
||||
.ignoringRequestMatchers(this.requestMatcher));
|
||||
return http.build();
|
||||
// @formatter:on
|
||||
|
@ -129,7 +129,7 @@ public class CsrfConfigurerIgnoringRequestMatchersTests {
|
|||
// @formatter:off
|
||||
http
|
||||
.csrf((csrf) -> csrf
|
||||
.requireCsrfProtectionMatcher(new AntPathRequestMatcher("/path"))
|
||||
.requireCsrfProtectionMatcher(PathPatternRequestMatcher.withDefaults().matcher("/path"))
|
||||
.ignoringRequestMatchers(this.requestMatcher)
|
||||
);
|
||||
return http.build();
|
||||
|
@ -149,7 +149,7 @@ public class CsrfConfigurerIgnoringRequestMatchersTests {
|
|||
// @formatter:off
|
||||
http
|
||||
.csrf((csrf) -> csrf
|
||||
.ignoringRequestMatchers(new AntPathRequestMatcher("/no-csrf"))
|
||||
.ignoringRequestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/no-csrf"))
|
||||
.ignoringRequestMatchers(this.requestMatcher));
|
||||
return http.build();
|
||||
// @formatter:on
|
||||
|
@ -169,7 +169,7 @@ public class CsrfConfigurerIgnoringRequestMatchersTests {
|
|||
// @formatter:off
|
||||
http
|
||||
.csrf((csrf) -> csrf
|
||||
.ignoringRequestMatchers(new AntPathRequestMatcher("/no-csrf"))
|
||||
.ignoringRequestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/no-csrf"))
|
||||
.ignoringRequestMatchers(this.requestMatcher)
|
||||
);
|
||||
return http.build();
|
||||
|
|
|
@ -57,7 +57,7 @@ import org.springframework.security.web.csrf.XorCsrfTokenRequestAttributeHandler
|
|||
import org.springframework.security.web.firewall.StrictHttpFirewall;
|
||||
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
|
||||
import org.springframework.security.web.savedrequest.RequestCache;
|
||||
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.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
|
@ -906,7 +906,7 @@ public class CsrfConfigurerTests {
|
|||
http
|
||||
.formLogin(withDefaults())
|
||||
.logout((logout) -> logout
|
||||
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")));
|
||||
.logoutRequestMatcher(PathPatternRequestMatcher.withDefaults().matcher("/logout")));
|
||||
return http.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
|
|
@ -128,8 +128,7 @@ public class DefaultFiltersTests {
|
|||
public void defaultFiltersPermitAll() throws IOException, ServletException {
|
||||
this.spring.register(DefaultFiltersConfigPermitAll.class, UserDetailsServiceConfig.class);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", "");
|
||||
request.setServletPath("/logout");
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout");
|
||||
CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN");
|
||||
CsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
|
||||
repository.saveToken(csrfToken, request, response);
|
||||
|
|
|
@ -32,7 +32,7 @@ import org.springframework.security.test.context.support.WithMockUser;
|
|||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||
import org.springframework.security.web.access.AccessDeniedHandlerImpl;
|
||||
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.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
@ -92,7 +92,7 @@ public class ExceptionHandlingConfigurerAccessDeniedHandlerTests {
|
|||
.exceptionHandling((handling) -> handling
|
||||
.defaultAccessDeniedHandlerFor(
|
||||
this.teapotDeniedHandler,
|
||||
new AntPathRequestMatcher("/hello/**"))
|
||||
PathPatternRequestMatcher.withDefaults().matcher("/hello/**"))
|
||||
.defaultAccessDeniedHandlerFor(
|
||||
new AccessDeniedHandlerImpl(),
|
||||
AnyRequestMatcher.INSTANCE));
|
||||
|
@ -119,7 +119,7 @@ public class ExceptionHandlingConfigurerAccessDeniedHandlerTests {
|
|||
.exceptionHandling((exceptionHandling) -> exceptionHandling
|
||||
.defaultAccessDeniedHandlerFor(
|
||||
this.teapotDeniedHandler,
|
||||
new AntPathRequestMatcher("/hello/**")
|
||||
PathPatternRequestMatcher.withDefaults().matcher("/hello/**")
|
||||
)
|
||||
.defaultAccessDeniedHandlerFor(
|
||||
new AccessDeniedHandlerImpl(),
|
||||
|
@ -148,7 +148,7 @@ public class ExceptionHandlingConfigurerAccessDeniedHandlerTests {
|
|||
.exceptionHandling((handling) -> handling
|
||||
.defaultAccessDeniedHandlerFor(
|
||||
this.teapotDeniedHandler,
|
||||
new AntPathRequestMatcher("/hello/**")));
|
||||
PathPatternRequestMatcher.withDefaults().matcher("/hello/**")));
|
||||
return http.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
|
|
@ -32,16 +32,16 @@ import org.springframework.mock.web.MockHttpServletResponse;
|
|||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
import org.springframework.security.web.FilterChainProxy;
|
||||
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.RestController;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
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.springframework.security.config.Customizer.withDefaults;
|
||||
|
@ -167,16 +167,20 @@ public class HttpSecurityRequestMatchersTests {
|
|||
@EnableWebMvc
|
||||
static class MultiMvcMatcherInLambdaConfig {
|
||||
|
||||
@Bean
|
||||
PathPatternRequestMatcherBuilderFactoryBean pathPattern() {
|
||||
return new PathPatternRequestMatcherBuilderFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
SecurityFilterChain first(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector);
|
||||
SecurityFilterChain first(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.securityMatchers((requests) -> requests
|
||||
.requestMatchers(mvcMatcherBuilder.pattern("/test-1"))
|
||||
.requestMatchers(mvcMatcherBuilder.pattern("/test-2"))
|
||||
.requestMatchers(mvcMatcherBuilder.pattern("/test-3"))
|
||||
.requestMatchers(builder.matcher("/test-1"))
|
||||
.requestMatchers(builder.matcher("/test-2"))
|
||||
.requestMatchers(builder.matcher("/test-3"))
|
||||
)
|
||||
.authorizeRequests((authorize) -> authorize.anyRequest().denyAll())
|
||||
.httpBasic(withDefaults());
|
||||
|
@ -185,12 +189,11 @@ public class HttpSecurityRequestMatchersTests {
|
|||
}
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain second(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector);
|
||||
SecurityFilterChain second(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.securityMatchers((requests) -> requests
|
||||
.requestMatchers(mvcMatcherBuilder.pattern("/test-1"))
|
||||
.requestMatchers(builder.matcher("/test-1"))
|
||||
)
|
||||
.authorizeRequests((authorize) -> authorize
|
||||
.anyRequest().permitAll()
|
||||
|
@ -216,16 +219,20 @@ public class HttpSecurityRequestMatchersTests {
|
|||
@EnableWebMvc
|
||||
static class MultiMvcMatcherConfig {
|
||||
|
||||
@Bean
|
||||
PathPatternRequestMatcherBuilderFactoryBean pathPattern() {
|
||||
return new PathPatternRequestMatcherBuilderFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
SecurityFilterChain first(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector);
|
||||
SecurityFilterChain first(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.securityMatchers((security) -> security
|
||||
.requestMatchers(mvcMatcherBuilder.pattern("/test-1"))
|
||||
.requestMatchers(mvcMatcherBuilder.pattern("/test-2"))
|
||||
.requestMatchers(mvcMatcherBuilder.pattern("/test-3")))
|
||||
.requestMatchers(builder.matcher("/test-1"))
|
||||
.requestMatchers(builder.matcher("/test-2"))
|
||||
.requestMatchers(builder.matcher("/test-3")))
|
||||
.authorizeRequests((requests) -> requests
|
||||
.anyRequest().denyAll())
|
||||
.httpBasic(withDefaults());
|
||||
|
@ -234,12 +241,11 @@ public class HttpSecurityRequestMatchersTests {
|
|||
}
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain second(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector);
|
||||
SecurityFilterChain second(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.securityMatchers((security) -> security
|
||||
.requestMatchers(mvcMatcherBuilder.pattern("/test-1")))
|
||||
.requestMatchers(builder.matcher("/test-1")))
|
||||
.authorizeRequests((requests) -> requests
|
||||
.anyRequest().permitAll());
|
||||
// @formatter:on
|
||||
|
@ -264,10 +270,15 @@ public class HttpSecurityRequestMatchersTests {
|
|||
static class MvcMatcherConfig {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
||||
PathPatternRequestMatcherBuilderFactoryBean pathPattern() {
|
||||
return new PathPatternRequestMatcherBuilderFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.securityMatcher(new MvcRequestMatcher(introspector, "/path"))
|
||||
.securityMatcher(builder.matcher("/path"))
|
||||
.httpBasic(withDefaults())
|
||||
.authorizeRequests((requests) -> requests
|
||||
.anyRequest().denyAll());
|
||||
|
@ -298,11 +309,16 @@ public class HttpSecurityRequestMatchersTests {
|
|||
static class RequestMatchersMvcMatcherConfig {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
||||
PathPatternRequestMatcherBuilderFactoryBean pathPattern() {
|
||||
return new PathPatternRequestMatcherBuilderFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.securityMatchers((security) -> security
|
||||
.requestMatchers(new MvcRequestMatcher(introspector, "/path")))
|
||||
.requestMatchers(builder.matcher("/path")))
|
||||
.httpBasic(withDefaults())
|
||||
.authorizeRequests((requests) -> requests
|
||||
.anyRequest().denyAll());
|
||||
|
@ -333,11 +349,16 @@ public class HttpSecurityRequestMatchersTests {
|
|||
static class RequestMatchersMvcMatcherInLambdaConfig {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
||||
PathPatternRequestMatcherBuilderFactoryBean pathPattern() {
|
||||
return new PathPatternRequestMatcherBuilderFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.securityMatchers((secure) -> secure
|
||||
.requestMatchers(new MvcRequestMatcher(introspector, "/path"))
|
||||
.requestMatchers(builder.matcher("/path"))
|
||||
)
|
||||
.httpBasic(withDefaults())
|
||||
.authorizeRequests((authorize) -> authorize
|
||||
|
@ -365,13 +386,16 @@ public class HttpSecurityRequestMatchersTests {
|
|||
static class RequestMatchersMvcMatcherServeltPathConfig {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector);
|
||||
mvcMatcherBuilder.servletPath("/spring");
|
||||
PathPatternRequestMatcherBuilderFactoryBean pathPattern() {
|
||||
return new PathPatternRequestMatcherBuilderFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.securityMatchers((security) -> security
|
||||
.requestMatchers(mvcMatcherBuilder.pattern("/path"))
|
||||
.requestMatchers(builder.basePath("/spring").matcher("/path"))
|
||||
.requestMatchers("/never-match"))
|
||||
.httpBasic(withDefaults())
|
||||
.authorizeRequests((requests) -> requests
|
||||
|
@ -403,13 +427,16 @@ public class HttpSecurityRequestMatchersTests {
|
|||
static class RequestMatchersMvcMatcherServletPathInLambdaConfig {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector);
|
||||
mvcMatcherBuilder.servletPath("/spring");
|
||||
PathPatternRequestMatcherBuilderFactoryBean pathPattern() {
|
||||
return new PathPatternRequestMatcherBuilderFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.securityMatchers((secure) -> secure
|
||||
.requestMatchers(mvcMatcherBuilder.pattern("/path"))
|
||||
.requestMatchers(builder.basePath("/spring").matcher("/path"))
|
||||
.requestMatchers("/never-match")
|
||||
)
|
||||
.httpBasic(withDefaults())
|
||||
|
|
|
@ -37,7 +37,7 @@ import org.springframework.security.test.support.ClassPathExclusions;
|
|||
import org.springframework.security.web.DefaultSecurityFilterChain;
|
||||
import org.springframework.security.web.FilterChainProxy;
|
||||
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.test.util.ReflectionTestUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
@ -101,7 +101,7 @@ public class HttpSecuritySecurityMatchersNoMvcTests {
|
|||
.findFirst()
|
||||
.get();
|
||||
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
||||
assertThat(requestMatchers).hasOnlyElementsOfType(AntPathRequestMatcher.class);
|
||||
assertThat(requestMatchers).hasOnlyElementsOfType(PathPatternRequestMatcher.class);
|
||||
}
|
||||
|
||||
public void loadConfig(Class<?>... configs) {
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.springframework.mock.web.MockHttpServletRequest;
|
|||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
|
@ -39,12 +40,11 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
|||
import org.springframework.security.web.FilterChainProxy;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
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.RestController;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
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.springframework.security.config.Customizer.withDefaults;
|
||||
|
@ -356,14 +356,18 @@ public class HttpSecuritySecurityMatchersTests {
|
|||
static class SecurityMatchersMvcMatcherServletPathConfig {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain appSecurity(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector)
|
||||
.servletPath("/spring");
|
||||
PathPatternRequestMatcherBuilderFactoryBean pathPattern() {
|
||||
return new PathPatternRequestMatcherBuilderFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain appSecurity(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||
PathPatternRequestMatcher.Builder spring = builder.basePath("/spring");
|
||||
// @formatter:off
|
||||
http
|
||||
.securityMatchers((security) -> security
|
||||
.requestMatchers(mvcMatcherBuilder.pattern("/path"))
|
||||
.requestMatchers(mvcMatcherBuilder.pattern("/never-match"))
|
||||
.requestMatchers(spring.matcher("/path"))
|
||||
.requestMatchers(spring.matcher("/never-match"))
|
||||
)
|
||||
.httpBasic(withDefaults())
|
||||
.authorizeHttpRequests((authorize) -> authorize
|
||||
|
@ -391,14 +395,18 @@ public class HttpSecuritySecurityMatchersTests {
|
|||
static class SecurityMatchersMvcMatcherServletPathInLambdaConfig {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain appSecurity(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector)
|
||||
.servletPath("/spring");
|
||||
PathPatternRequestMatcherBuilderFactoryBean pathPattern() {
|
||||
return new PathPatternRequestMatcherBuilderFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain appSecurity(HttpSecurity http, PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||
PathPatternRequestMatcher.Builder spring = builder.basePath("/spring");
|
||||
// @formatter:off
|
||||
http
|
||||
.securityMatchers((matchers) -> matchers
|
||||
.requestMatchers(mvcMatcherBuilder.pattern("/path"))
|
||||
.requestMatchers(mvcMatcherBuilder.pattern("/never-match"))
|
||||
.requestMatchers(spring.matcher("/path"))
|
||||
.requestMatchers(spring.matcher("/never-match"))
|
||||
)
|
||||
.httpBasic(withDefaults())
|
||||
.authorizeHttpRequests((authorize) -> authorize
|
||||
|
|
|
@ -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.PersistentRememberMeToken;
|
||||
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.MvcResult;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
@ -349,7 +348,7 @@ public class NamespaceRememberMeTests {
|
|||
SecurityFilterChain withoutKeyFilterChain(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.securityMatcher(new AntPathRequestMatcher("/without-key/**"))
|
||||
.securityMatcher("/without-key/**")
|
||||
.authorizeHttpRequests((authorize) -> authorize.anyRequest().authenticated())
|
||||
.formLogin((login) -> login
|
||||
.loginProcessingUrl("/without-key/login"))
|
||||
|
|
|
@ -27,7 +27,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
|
|||
import org.springframework.security.config.test.SpringTestContext;
|
||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||
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.test.web.servlet.MockMvc;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
|
@ -79,9 +79,9 @@ public class RequestMatcherConfigurerTests {
|
|||
// @formatter:off
|
||||
http
|
||||
.securityMatchers((security) -> security
|
||||
.requestMatchers(new AntPathRequestMatcher("/api/**")))
|
||||
.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/api/**")))
|
||||
.securityMatchers((security) -> security
|
||||
.requestMatchers(new AntPathRequestMatcher("/oauth/**")))
|
||||
.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/oauth/**")))
|
||||
.authorizeRequests((requests) -> requests
|
||||
.anyRequest().denyAll());
|
||||
return http.build();
|
||||
|
@ -99,10 +99,10 @@ public class RequestMatcherConfigurerTests {
|
|||
// @formatter:off
|
||||
http
|
||||
.securityMatchers((secure) -> secure
|
||||
.requestMatchers(new AntPathRequestMatcher("/api/**"))
|
||||
.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/api/**"))
|
||||
)
|
||||
.securityMatchers((securityMatchers) -> securityMatchers
|
||||
.requestMatchers(new AntPathRequestMatcher("/oauth/**"))
|
||||
.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/oauth/**"))
|
||||
)
|
||||
.authorizeRequests((authorize) -> authorize
|
||||
.anyRequest().denyAll()
|
||||
|
|
|
@ -78,7 +78,7 @@ public class SessionManagementConfigurerServlet31Tests {
|
|||
|
||||
@Test
|
||||
public void changeSessionIdThenPreserveParameters() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/login");
|
||||
String id = request.getSession().getId();
|
||||
request.getSession();
|
||||
request.setServletPath("/login");
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.springframework.mock.web.MockHttpServletResponse;
|
|||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean;
|
||||
import org.springframework.security.core.userdetails.PasswordEncodedUser;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
@ -41,12 +42,11 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
|||
import org.springframework.security.web.FilterChainProxy;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
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.RestController;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
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.springframework.security.config.Customizer.withDefaults;
|
||||
|
@ -131,14 +131,19 @@ public class UrlAuthorizationConfigurerTests {
|
|||
@EnableWebMvc
|
||||
static class MvcMatcherConfig {
|
||||
|
||||
@Bean
|
||||
PathPatternRequestMatcherBuilderFactoryBean pathPattern() {
|
||||
return new PathPatternRequestMatcherBuilderFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http, ApplicationContext context,
|
||||
HandlerMappingIntrospector introspector) throws Exception {
|
||||
PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.httpBasic(withDefaults())
|
||||
.apply(new UrlAuthorizationConfigurer(context)).getRegistry()
|
||||
.requestMatchers(new MvcRequestMatcher(introspector, "/path")).hasRole("ADMIN");
|
||||
.requestMatchers(builder.matcher("/path")).hasRole("ADMIN");
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
}
|
||||
|
@ -165,16 +170,20 @@ public class UrlAuthorizationConfigurerTests {
|
|||
@EnableWebMvc
|
||||
static class MvcMatcherServletPathConfig {
|
||||
|
||||
@Bean
|
||||
PathPatternRequestMatcherBuilderFactoryBean pathPattern() {
|
||||
return new PathPatternRequestMatcherBuilderFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http, ApplicationContext context,
|
||||
HandlerMappingIntrospector introspector) throws Exception {
|
||||
MvcRequestMatcher mvcRequestMatcher = new MvcRequestMatcher(introspector, "/path");
|
||||
mvcRequestMatcher.setServletPath("/spring");
|
||||
PathPatternRequestMatcher.Builder builder) throws Exception {
|
||||
PathPatternRequestMatcher.Builder spring = builder.basePath("/spring");
|
||||
// @formatter:off
|
||||
http
|
||||
.httpBasic(withDefaults())
|
||||
.apply(new UrlAuthorizationConfigurer(context)).getRegistry()
|
||||
.requestMatchers(mvcRequestMatcher).hasRole("ADMIN");
|
||||
.requestMatchers(builder.matcher("/path")).hasRole("ADMIN");
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
}
|
||||
|
|
|
@ -185,7 +185,7 @@ public class OAuth2LoginConfigurerTests {
|
|||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
this.request = new MockHttpServletRequest("GET", "");
|
||||
this.request = new MockHttpServletRequest("GET", "/login/oauth2/code/google");
|
||||
this.request.setServletPath("/login/oauth2/code/google");
|
||||
this.response = new MockHttpServletResponse();
|
||||
this.filterChain = new MockFilterChain();
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.springframework.context.ConfigurableApplicationContext;
|
|||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
|
@ -76,7 +77,7 @@ import org.springframework.security.web.SecurityFilterChain;
|
|||
import org.springframework.security.web.authentication.logout.LogoutFilter;
|
||||
import org.springframework.security.web.authentication.logout.LogoutHandler;
|
||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
|
||||
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.MvcResult;
|
||||
import org.springframework.test.web.servlet.request.RequestPostProcessor;
|
||||
|
@ -620,7 +621,7 @@ public class Saml2LogoutConfigurerTests {
|
|||
.saml2Logout((saml2) -> saml2.addObjectPostProcessor(new ObjectPostProcessor<LogoutFilter>() {
|
||||
@Override
|
||||
public <O extends LogoutFilter> O postProcess(O filter) {
|
||||
filter.setLogoutRequestMatcher(new AntPathRequestMatcher("/logout", "GET"));
|
||||
filter.setLogoutRequestMatcher(PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.GET, "/logout"));
|
||||
return filter;
|
||||
}
|
||||
}));
|
||||
|
|
|
@ -53,12 +53,4 @@ class WebMvcSecurityConfigurationRuntimeHintsTests {
|
|||
.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.authentication.AnonymousAuthenticationFilter;
|
||||
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.test.util.ReflectionTestUtils;
|
||||
|
||||
|
@ -144,12 +144,13 @@ public class DefaultFilterChainValidatorTests {
|
|||
|
||||
@Test
|
||||
void validateWhenSameRequestMatchersArePresentThenUnreachableFilterChainException() {
|
||||
PathPatternRequestMatcher.Builder builder = PathPatternRequestMatcher.withDefaults();
|
||||
AnonymousAuthenticationFilter authenticationFilter = mock(AnonymousAuthenticationFilter.class);
|
||||
ExceptionTranslationFilter exceptionTranslationFilter = mock(ExceptionTranslationFilter.class);
|
||||
SecurityFilterChain chain1 = new DefaultSecurityFilterChain(AntPathRequestMatcher.antMatcher("/api"),
|
||||
authenticationFilter, exceptionTranslationFilter, this.authorizationInterceptor);
|
||||
SecurityFilterChain chain2 = new DefaultSecurityFilterChain(AntPathRequestMatcher.antMatcher("/api"),
|
||||
authenticationFilter, exceptionTranslationFilter, this.authorizationInterceptor);
|
||||
SecurityFilterChain chain1 = new DefaultSecurityFilterChain(builder.matcher("/api"), authenticationFilter,
|
||||
exceptionTranslationFilter, this.authorizationInterceptor);
|
||||
SecurityFilterChain chain2 = new DefaultSecurityFilterChain(builder.matcher("/api"), authenticationFilter,
|
||||
exceptionTranslationFilter, this.authorizationInterceptor);
|
||||
List<SecurityFilterChain> chains = new ArrayList<>();
|
||||
chains.add(chain2);
|
||||
chains.add(chain1);
|
||||
|
|
|
@ -92,12 +92,10 @@ public class FilterSecurityMetadataSourceBeanDefinitionParserTests {
|
|||
public void interceptUrlsSupportPropertyPlaceholders() {
|
||||
System.setProperty("secure.url", "/secure");
|
||||
System.setProperty("secure.role", "ROLE_A");
|
||||
setContext(
|
||||
"<b:bean class=\"org.springframework.web.servlet.handler.HandlerMappingIntrospector\" name=\"mvcHandlerMappingIntrospector\"/>"
|
||||
+ "<b:bean class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer'/>"
|
||||
+ "<filter-security-metadata-source id='fids' use-expressions='false'>"
|
||||
+ " <intercept-url pattern='${secure.url}' access='${secure.role}'/>"
|
||||
+ "</filter-security-metadata-source>");
|
||||
setContext("<b:bean class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer'/>"
|
||||
+ "<filter-security-metadata-source id='fids' use-expressions='false'>"
|
||||
+ " <intercept-url pattern='${secure.url}' access='${secure.role}'/>"
|
||||
+ "</filter-security-metadata-source>");
|
||||
DefaultFilterInvocationSecurityMetadataSource fids = (DefaultFilterInvocationSecurityMetadataSource) this.appContext
|
||||
.getBean("fids");
|
||||
Collection<ConfigAttribute> cad = fids.getAttributes(createFilterInvocation("/secure", "GET"));
|
||||
|
@ -107,8 +105,7 @@ public class FilterSecurityMetadataSourceBeanDefinitionParserTests {
|
|||
@Test
|
||||
public void parsingWithinFilterSecurityInterceptorIsSuccessful() {
|
||||
// @formatter:off
|
||||
setContext("<b:bean class=\"org.springframework.web.servlet.handler.HandlerMappingIntrospector\" name=\"mvcHandlerMappingIntrospector\"/>" +
|
||||
"<http auto-config='true' use-expressions='false' use-authorization-manager='false'/>"
|
||||
setContext("<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:property name='securityMetadataSource'>"
|
||||
+ " <filter-security-metadata-source use-expressions='false'>"
|
||||
|
|
|
@ -72,7 +72,7 @@ public class FormLoginConfigTests {
|
|||
|
||||
@Test
|
||||
public void getProtectedPageWhenFormLoginConfiguredThenRedirectsToDefaultLoginPage() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithAntRequestMatcher")).autowire();
|
||||
this.spring.configLocations(this.xml("WithRequestMatcher")).autowire();
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
|
|
|
@ -25,7 +25,6 @@ import org.junit.jupiter.api.Test;
|
|||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
||||
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.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.ConfigurableWebApplicationContext;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
@ -250,21 +248,6 @@ public class InterceptUrlConfigTests {
|
|||
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
|
||||
public void requestWhenUsingMvcMatchersAndPathVariablesThenAuthorizesRequestsAccordingly() throws Exception {
|
||||
this.spring.configLocations(this.xml("MvcMatchersPathVariables")).autowire();
|
||||
|
@ -293,48 +276,6 @@ public class InterceptUrlConfigTests {
|
|||
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
|
||||
public void configureWhenUsingRegexMatcherAndServletPathThenThrowsException() {
|
||||
assertThatExceptionOfType(BeanDefinitionParsingException.class)
|
||||
|
@ -366,12 +307,6 @@ public class InterceptUrlConfigTests {
|
|||
.isThrownBy(() -> this.spring.configLocations(this.xml("DefaultMatcherServletPath")).autowire());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenUsingDefaultMatcherAndNoIntrospectorBeanThenException() {
|
||||
assertThatExceptionOfType(BeanCreationException.class)
|
||||
.isThrownBy(() -> this.spring.configLocations(this.xml("DefaultMatcherNoIntrospectorBean")).autowire());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenUsingDefaultMatcherAndServletPathAndAuthorizationManagerThenNoException() {
|
||||
assertThatNoException()
|
||||
|
|
|
@ -22,7 +22,7 @@ import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
|
|||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer;
|
||||
import org.springframework.security.web.DefaultSecurityFilterChain;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
|
@ -44,7 +44,7 @@ public class CustomConfigurer extends SecurityConfigurerAdapter<DefaultSecurityF
|
|||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests((requests) -> requests
|
||||
.requestMatchers(new AntPathRequestMatcher(this.permitAllPattern)).permitAll()
|
||||
.requestMatchers(PathPatternRequestMatcher.withDefaults().matcher(this.permitAllPattern)).permitAll()
|
||||
.anyRequest().authenticated());
|
||||
// @formatter:on
|
||||
if (http.getConfigurer(FormLoginConfigurer.class) == null) {
|
||||
|
|
|
@ -43,7 +43,7 @@ import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler
|
|||
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.security.web.servlet.util.matcher.PathPatternRequestMatcher
|
||||
import org.springframework.test.web.servlet.MockMvc
|
||||
import org.springframework.test.web.servlet.get
|
||||
import org.springframework.test.web.servlet.post
|
||||
|
@ -176,7 +176,7 @@ class CsrfDslTests {
|
|||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||
http {
|
||||
csrf {
|
||||
requireCsrfProtectionMatcher = AntPathRequestMatcher("/test1")
|
||||
requireCsrfProtectionMatcher = PathPatternRequestMatcher.withDefaults().matcher("/test1")
|
||||
}
|
||||
}
|
||||
return http.build()
|
||||
|
@ -247,8 +247,8 @@ class CsrfDslTests {
|
|||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||
http {
|
||||
csrf {
|
||||
requireCsrfProtectionMatcher = AntPathRequestMatcher("/**")
|
||||
ignoringRequestMatchers(AntPathRequestMatcher("/test2"))
|
||||
requireCsrfProtectionMatcher = PathPatternRequestMatcher.withDefaults().matcher("/**")
|
||||
ignoringRequestMatchers(PathPatternRequestMatcher.withDefaults().matcher("/test2"))
|
||||
}
|
||||
}
|
||||
return http.build()
|
||||
|
@ -279,7 +279,7 @@ class CsrfDslTests {
|
|||
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
|
||||
http {
|
||||
csrf {
|
||||
requireCsrfProtectionMatcher = AntPathRequestMatcher("/**")
|
||||
requireCsrfProtectionMatcher = PathPatternRequestMatcher.withDefaults().matcher("/**")
|
||||
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.access.AccessDeniedHandlerImpl
|
||||
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.get
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc
|
||||
|
@ -195,6 +195,7 @@ class ExceptionHandlingDslTests {
|
|||
customAccessDeniedHandler1.setErrorPage("/access-denied1")
|
||||
val customAccessDeniedHandler2 = AccessDeniedHandlerImpl()
|
||||
customAccessDeniedHandler2.setErrorPage("/access-denied2")
|
||||
val builder = PathPatternRequestMatcher.withDefaults()
|
||||
http {
|
||||
authorizeRequests {
|
||||
authorize("/admin1", hasAuthority("ROLE_ADMIN"))
|
||||
|
@ -202,8 +203,8 @@ class ExceptionHandlingDslTests {
|
|||
authorize(anyRequest, authenticated)
|
||||
}
|
||||
exceptionHandling {
|
||||
defaultAccessDeniedHandlerFor(customAccessDeniedHandler1, AntPathRequestMatcher("/admin1"))
|
||||
defaultAccessDeniedHandlerFor(customAccessDeniedHandler2, AntPathRequestMatcher("/admin2"))
|
||||
defaultAccessDeniedHandlerFor(customAccessDeniedHandler1, builder.matcher("/admin1"))
|
||||
defaultAccessDeniedHandlerFor(customAccessDeniedHandler2, builder.matcher("/admin2"))
|
||||
}
|
||||
}
|
||||
return http.build()
|
||||
|
@ -264,13 +265,14 @@ class ExceptionHandlingDslTests {
|
|||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||
val customAuthenticationEntryPoint1 = LoginUrlAuthenticationEntryPoint("/custom-login1")
|
||||
val customAuthenticationEntryPoint2 = LoginUrlAuthenticationEntryPoint("/custom-login2")
|
||||
val builder = PathPatternRequestMatcher.withDefaults();
|
||||
http {
|
||||
authorizeRequests {
|
||||
authorize(anyRequest, authenticated)
|
||||
}
|
||||
exceptionHandling {
|
||||
defaultAuthenticationEntryPointFor(customAuthenticationEntryPoint1, AntPathRequestMatcher("/secured1"))
|
||||
defaultAuthenticationEntryPointFor(customAuthenticationEntryPoint2, AntPathRequestMatcher("/secured2"))
|
||||
defaultAuthenticationEntryPointFor(customAuthenticationEntryPoint1, builder.matcher("/secured1"))
|
||||
defaultAuthenticationEntryPointFor(customAuthenticationEntryPoint2, builder.matcher("/secured2"))
|
||||
}
|
||||
}
|
||||
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.SimpleUrlLogoutSuccessHandler
|
||||
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.post
|
||||
|
||||
|
@ -102,7 +102,7 @@ class LogoutDslTests {
|
|||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||
http {
|
||||
logout {
|
||||
logoutRequestMatcher = AntPathRequestMatcher("/custom/logout")
|
||||
logoutRequestMatcher = PathPatternRequestMatcher.withDefaults().matcher("/custom/logout")
|
||||
}
|
||||
}
|
||||
return http.build()
|
||||
|
@ -307,8 +307,8 @@ class LogoutDslTests {
|
|||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||
http {
|
||||
logout {
|
||||
logoutRequestMatcher = AntPathRequestMatcher("/logout/**")
|
||||
defaultLogoutSuccessHandlerFor(SimpleUrlLogoutSuccessHandler(), AntPathRequestMatcher("/logout/custom"))
|
||||
logoutRequestMatcher = PathPatternRequestMatcher.withDefaults().matcher("/logout/**")
|
||||
defaultLogoutSuccessHandlerFor(SimpleUrlLogoutSuccessHandler(), PathPatternRequestMatcher.withDefaults().matcher("/logout/custom"))
|
||||
}
|
||||
}
|
||||
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.rememberme.AbstractRememberMeServices
|
||||
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.MockMvc
|
||||
import org.springframework.test.web.servlet.get
|
||||
|
@ -472,7 +471,7 @@ internal class RememberMeDslTests {
|
|||
@Order(0)
|
||||
open fun securityFilterChainWithoutKey(http: HttpSecurity): SecurityFilterChain {
|
||||
http {
|
||||
securityMatcher(AntPathRequestMatcher("/without-key/**"))
|
||||
securityMatcher("/without-key/**")
|
||||
formLogin {
|
||||
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.web.SecurityFilterChain
|
||||
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.get
|
||||
|
||||
|
@ -148,7 +148,7 @@ class HttpStrictTransportSecurityDslTests {
|
|||
headers {
|
||||
defaultsDisabled = true
|
||||
httpStrictTransportSecurity {
|
||||
requestMatcher = AntPathRequestMatcher("/secure/**")
|
||||
requestMatcher = PathPatternRequestMatcher.withDefaults().matcher("/secure/**")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ http://www.springframework.org/schema/security https://www.springframework.org/s
|
|||
</security:user-service>
|
||||
</security:authentication-provider>
|
||||
</security:authentication-manager>
|
||||
|
||||
<import resource="handlermappingintrospector.xml"/>
|
||||
|
||||
<import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
|
||||
</beans>
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
</http>
|
||||
|
||||
<b:import resource="CsrfConfigTests-shared-userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
|
||||
<b:bean id="firewall" class="org.springframework.security.web.firewall.StrictHttpFirewall"
|
||||
p:unsafeAllowAnyHttpMethod="true"/>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
http://www.springframework.org/schema/beans
|
||||
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"/>
|
||||
<form-login/>
|
||||
</http>
|
|
@ -24,7 +24,7 @@
|
|||
http://www.springframework.org/schema/beans
|
||||
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"/>
|
||||
<form-login authentication-success-handler-ref="fsh" authentication-failure-handler-ref="fsh"/>
|
||||
</http>
|
||||
|
|
|
@ -16,8 +16,12 @@
|
|||
<user name="user" password="password" authorities="ROLE_USER"/>
|
||||
</user-service>
|
||||
|
||||
<b:bean id="matcherRef" class="org.springframework.security.web.util.matcher.AntPathRequestMatcher"
|
||||
c:pattern="/foo"
|
||||
c:httpMethod="GET"
|
||||
c:caseSensitive="false"/>
|
||||
<b:bean id="mvcPatternParser" class="org.springframework.web.util.pattern.PathPatternParser">
|
||||
<b:property name="caseSensitive" value="false"/>
|
||||
</b:bean>
|
||||
|
||||
<b:bean id="builderRef" class="org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean"/>
|
||||
|
||||
<b:bean id="matcherRef" class="org.springframework.security.config.http.PathPatternRequestMatcherFactoryBean"
|
||||
c:pattern="/foo" c:method="GET"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -33,15 +33,15 @@
|
|||
|
||||
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
||||
<b:bean name="error" class="org.springframework.security.config.http.InterceptUrlConfigTests.ErrorController"/>
|
||||
|
||||
|
||||
<b:bean name="errorRequestMatcher" class="org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher">
|
||||
<b:constructor-arg value="ERROR"/>
|
||||
</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:bean>
|
||||
|
||||
|
||||
<b:bean name="pathErrorRequestMatcher" class="org.springframework.security.web.util.matcher.AndRequestMatcher">
|
||||
<b:constructor-arg>
|
||||
<b:list>
|
||||
|
|
|
@ -33,5 +33,5 @@
|
|||
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -33,5 +33,5 @@
|
|||
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -30,5 +30,5 @@
|
|||
</http>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -30,5 +30,5 @@
|
|||
</http>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -33,15 +33,15 @@
|
|||
|
||||
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
||||
<b:bean name="error" class="org.springframework.security.config.http.InterceptUrlConfigTests.ErrorController"/>
|
||||
|
||||
|
||||
<b:bean name="errorRequestMatcher" class="org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher">
|
||||
<b:constructor-arg value="ERROR"/>
|
||||
</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:bean>
|
||||
|
||||
|
||||
<b:bean name="pathErrorRequestMatcher" class="org.springframework.security.web.util.matcher.AndRequestMatcher">
|
||||
<b:constructor-arg>
|
||||
<b:list>
|
||||
|
|
|
@ -33,5 +33,5 @@
|
|||
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -33,5 +33,5 @@
|
|||
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -33,5 +33,5 @@
|
|||
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -33,5 +33,5 @@
|
|||
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -34,5 +34,5 @@
|
|||
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -34,5 +34,5 @@
|
|||
<b:bean name="path" class="org.springframework.security.config.http.InterceptUrlConfigTests.PathController"/>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -34,5 +34,5 @@
|
|||
<b:bean name="id" class="org.springframework.security.config.http.InterceptUrlConfigTests.Id"/>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -34,5 +34,5 @@
|
|||
<b:bean name="id" class="org.springframework.security.config.http.InterceptUrlConfigTests.Id"/>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -32,5 +32,5 @@
|
|||
</http>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -31,5 +31,5 @@
|
|||
</http>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -34,5 +34,5 @@
|
|||
</b:bean>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
<http-basic/>
|
||||
</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:bean>
|
||||
|
||||
|
|
|
@ -29,5 +29,5 @@
|
|||
<http pattern="/unprotected" security="none"/>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -31,5 +31,5 @@
|
|||
</http>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -31,5 +31,5 @@
|
|||
</http>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -30,5 +30,5 @@
|
|||
</http>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -30,5 +30,5 @@
|
|||
</http>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -35,5 +35,5 @@
|
|||
<b:bean name="basicController" class="org.springframework.security.config.http.MultiHttpBlockConfigTests.BasicController"/>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -33,5 +33,5 @@
|
|||
</http>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -50,5 +50,5 @@
|
|||
</authentication-provider>
|
||||
</authentication-manager>
|
||||
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -32,5 +32,5 @@
|
|||
</http>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -33,5 +33,5 @@
|
|||
</http>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -33,5 +33,5 @@
|
|||
</http>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
|
@ -39,5 +39,5 @@
|
|||
</http>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
<b:import resource="handlermappingintrospector.xml"/>
|
||||
<b:import resource="pathpatternrequestmatcherbuilder.xml"/>
|
||||
</b:beans>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue