Use PathPatternRequestMatcher by Default
This commit is contained in:
parent
772f0cc741
commit
25cfbe85d0
|
@ -43,6 +43,7 @@ import org.springframework.security.config.ObjectPostProcessor;
|
|||
import org.springframework.security.config.annotation.web.ServletRegistrationsSupport.RegistrationMapping;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractConfigAttributeRequestMatcherRegistry;
|
||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
||||
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher;
|
||||
|
@ -53,8 +54,8 @@ import org.springframework.security.web.util.matcher.RequestMatcherBuilder;
|
|||
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;
|
||||
import org.springframework.web.util.pattern.PathPatternParser;
|
||||
|
||||
/**
|
||||
* A base class for registering {@link RequestMatcher}'s. For example, it might allow for
|
||||
|
@ -234,7 +235,7 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||
return false;
|
||||
}
|
||||
|
||||
private RequestMatcher resolve(AntPathRequestMatcher ant, MvcRequestMatcher mvc, ServletContext servletContext) {
|
||||
private RequestMatcher resolve(AntPathRequestMatcher ant, RequestMatcher mvc, ServletContext servletContext) {
|
||||
ServletRegistrationsSupport registrations = new ServletRegistrationsSupport(servletContext);
|
||||
Collection<RegistrationMapping> mappings = registrations.mappings();
|
||||
if (mappings.isEmpty()) {
|
||||
|
@ -280,10 +281,10 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||
|
||||
/**
|
||||
* <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/",
|
||||
* If the {@link HandlerMappingIntrospector} is available in the classpath, maps to a
|
||||
* {@link PathPatternRequestMatcher} 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}.
|
||||
* </p>
|
||||
|
@ -408,8 +409,26 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||
|
||||
@Override
|
||||
public RequestMatcher pattern(HttpMethod method, String pattern) {
|
||||
Assert.state(!AbstractRequestMatcherRegistry.this.anyRequestConfigured,
|
||||
"Can't configure mvcMatchers after anyRequest");
|
||||
AntPathRequestMatcher ant = new AntPathRequestMatcher(pattern, (method != null) ? method.name() : null);
|
||||
MvcRequestMatcher mvc = createMvcMatchers(method, pattern).get(0);
|
||||
RequestMatcher mvc;
|
||||
if (!AbstractRequestMatcherRegistry.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 = AbstractRequestMatcherRegistry.this.context
|
||||
.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, HandlerMappingIntrospector.class);
|
||||
if (introspector.allHandlerMappingsUsePathPatternParser()) {
|
||||
PathPatternParser pathPatternParser = AbstractRequestMatcherRegistry.this.context
|
||||
.getBeanProvider(PathPatternParser.class)
|
||||
.getIfUnique(() -> PathPatternParser.defaultInstance);
|
||||
mvc = PathPatternRequestMatcher.withPathPatternParser(pathPatternParser).pattern(method, pattern);
|
||||
}
|
||||
else {
|
||||
mvc = createMvcMatchers(method, pattern).get(0);
|
||||
}
|
||||
return new DeferredRequestMatcher((c) -> resolve(ant, mvc, c), mvc, ant);
|
||||
}
|
||||
|
||||
|
@ -466,13 +485,8 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||
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;
|
||||
}
|
||||
return new RegistrationMapping(registration, request.getHttpServletMapping().getPattern())
|
||||
.isDispatcherServlet();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -481,15 +495,15 @@ public abstract class AbstractRequestMatcherRegistry<C> {
|
|||
|
||||
private final AntPathRequestMatcher ant;
|
||||
|
||||
private final MvcRequestMatcher mvc;
|
||||
private final RequestMatcher mvc;
|
||||
|
||||
private final RequestMatcher dispatcherServlet;
|
||||
|
||||
DispatcherServletDelegatingRequestMatcher(AntPathRequestMatcher ant, MvcRequestMatcher mvc) {
|
||||
DispatcherServletDelegatingRequestMatcher(AntPathRequestMatcher ant, RequestMatcher mvc) {
|
||||
this(ant, mvc, new OrRequestMatcher(new MockMvcRequestMatcher(), new DispatcherServletRequestMatcher()));
|
||||
}
|
||||
|
||||
DispatcherServletDelegatingRequestMatcher(AntPathRequestMatcher ant, MvcRequestMatcher mvc,
|
||||
DispatcherServletDelegatingRequestMatcher(AntPathRequestMatcher ant, RequestMatcher mvc,
|
||||
RequestMatcher dispatcherServlet) {
|
||||
this.ant = ant;
|
||||
this.mvc = mvc;
|
||||
|
|
|
@ -16,20 +16,25 @@
|
|||
|
||||
package org.springframework.security.config.http;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
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.servlet.util.matcher.PathPatternRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
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;
|
||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
||||
import org.springframework.web.util.pattern.PathPatternParser;
|
||||
|
||||
/**
|
||||
* Defines the {@link RequestMatcher} types supported by the namespace.
|
||||
|
@ -40,7 +45,7 @@ import org.springframework.util.StringUtils;
|
|||
public enum MatcherType {
|
||||
|
||||
ant(AntPathRequestMatcher.class), regex(RegexRequestMatcher.class), ciRegex(RegexRequestMatcher.class),
|
||||
mvc(MvcRequestMatcher.class);
|
||||
mvc(MvcRequestMatcherFactoryBean.class);
|
||||
|
||||
private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector";
|
||||
|
||||
|
@ -100,4 +105,56 @@ public enum MatcherType {
|
|||
return MatcherType.fromElement(elt);
|
||||
}
|
||||
|
||||
private static class MvcRequestMatcherFactoryBean implements FactoryBean<RequestMatcher>, RequestMatcher {
|
||||
|
||||
private final HandlerMappingIntrospector introspector;
|
||||
|
||||
private final String pattern;
|
||||
|
||||
private PathPatternParser pathPatternParser = PathPatternParser.defaultInstance;
|
||||
|
||||
private String servletPath;
|
||||
|
||||
private HttpMethod method;
|
||||
|
||||
public MvcRequestMatcherFactoryBean(HandlerMappingIntrospector introspector, String pattern) {
|
||||
this.introspector = introspector;
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestMatcher getObject() {
|
||||
if (this.introspector.allHandlerMappingsUsePathPatternParser()) {
|
||||
return PathPatternRequestMatcher.withPathPatternParser(this.pathPatternParser)
|
||||
.servletPath(this.servletPath)
|
||||
.pattern(this.method, this.pattern);
|
||||
}
|
||||
return new MvcRequestMatcher.Builder(this.introspector).servletPath(this.servletPath)
|
||||
.pattern(this.method, this.pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return RequestMatcher.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(HttpServletRequest request) {
|
||||
return getObject().matches(request);
|
||||
}
|
||||
|
||||
public void setPathPatternParser(PathPatternParser pathPatternParser) {
|
||||
this.pathPatternParser = pathPatternParser;
|
||||
}
|
||||
|
||||
public void setServletPath(String servletPath) {
|
||||
this.servletPath = servletPath;
|
||||
}
|
||||
|
||||
public void setMethod(HttpMethod method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,10 +32,12 @@ 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 org.springframework.web.util.pattern.PathPatternParser
|
||||
import java.util.function.Supplier
|
||||
|
||||
/**
|
||||
|
@ -292,11 +294,20 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl {
|
|||
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)
|
||||
if (introspector.allHandlerMappingsUsePathPatternParser()) {
|
||||
val pathPatternParser: PathPatternParser = requests.applicationContext.getBeanProvider(PathPatternParser::class.java)
|
||||
.getIfUnique({PathPatternParser.defaultInstance})
|
||||
val mvcMatcher = PathPatternRequestMatcher.withPathPatternParser(pathPatternParser)
|
||||
.servletPath(rule.servletPath)
|
||||
.pattern(rule.httpMethod, rule.pattern)
|
||||
requests.requestMatchers(mvcMatcher).access(rule.rule)
|
||||
} else {
|
||||
val mvcMatcher = MvcRequestMatcher.Builder(introspector)
|
||||
.servletPath(rule.servletPath)
|
||||
.pattern(rule.pattern)
|
||||
mvcMatcher.setMethod(rule.httpMethod)
|
||||
requests.requestMatchers(mvcMatcher).access(rule.rule)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,8 @@ public class FilterChainProxyConfigTests {
|
|||
|
||||
private String getPattern(SecurityFilterChain chain) {
|
||||
RequestMatcher requestMatcher = ((DefaultSecurityFilterChain) chain).getRequestMatcher();
|
||||
return (String) ReflectionTestUtils.getField(requestMatcher, "pattern");
|
||||
Object pattern = ReflectionTestUtils.getField(requestMatcher, "pattern");
|
||||
return (pattern instanceof PathPattern) ? pattern.toString() : (String) pattern;
|
||||
}
|
||||
|
||||
private void checkPathAndFilterOrder(FilterChainProxy filterChainProxy) {
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.util.List;
|
|||
|
||||
import jakarta.servlet.DispatcherType;
|
||||
import jakarta.servlet.Servlet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@ -39,6 +40,7 @@ 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.servlet.util.matcher.PathPatternRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
||||
|
@ -49,10 +51,13 @@ 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 org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
||||
|
||||
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.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
@ -91,11 +96,13 @@ public class AbstractRequestMatcherRegistryTests {
|
|||
given(this.context.getServletContext()).willReturn(MockServletContext.mvc());
|
||||
ObjectProvider<RequestMatcherBuilder> requestMatcherFactories = new ObjectProvider<>() {
|
||||
@Override
|
||||
public RequestMatcherBuilder getObject() throws BeansException {
|
||||
public @NotNull RequestMatcherBuilder getObject() throws BeansException {
|
||||
return AbstractRequestMatcherRegistryTests.this.matcherRegistry.new DefaultRequestMatcherBuilder();
|
||||
}
|
||||
};
|
||||
given(this.context.getBeanProvider(RequestMatcherBuilder.class)).willReturn(requestMatcherFactories);
|
||||
HandlerMappingIntrospector introspector = mock(HandlerMappingIntrospector.class);
|
||||
given(this.context.getBean(any(), eq(HandlerMappingIntrospector.class))).willReturn(introspector);
|
||||
this.matcherRegistry.setApplicationContext(this.context);
|
||||
mockMvcIntrospector(true);
|
||||
}
|
||||
|
@ -231,7 +238,7 @@ public class AbstractRequestMatcherRegistryTests {
|
|||
assertThat(requestMatchers).hasSize(1);
|
||||
assertThat(requestMatchers.get(0)).asInstanceOf(type(DispatcherServletDelegatingRequestMatcher.class))
|
||||
.extracting((matcher) -> matcher.requestMatcher(request))
|
||||
.isInstanceOf(MvcRequestMatcher.class);
|
||||
.isInstanceOf(PathPatternRequestMatcher.class);
|
||||
servletContext.addServlet("servletOne", Servlet.class).addMapping("/one");
|
||||
servletContext.addServlet("servletTwo", Servlet.class).addMapping("/two");
|
||||
requestMatchers = this.matcherRegistry.requestMatchers("/**");
|
||||
|
@ -239,7 +246,7 @@ public class AbstractRequestMatcherRegistryTests {
|
|||
assertThat(requestMatchers).hasSize(1);
|
||||
assertThat(requestMatchers.get(0)).asInstanceOf(type(DispatcherServletDelegatingRequestMatcher.class))
|
||||
.extracting((matcher) -> matcher.requestMatcher(request))
|
||||
.isInstanceOf(MvcRequestMatcher.class);
|
||||
.isInstanceOf(PathPatternRequestMatcher.class);
|
||||
servletContext.addServlet("servletOne", Servlet.class);
|
||||
servletContext.addServlet("servletTwo", Servlet.class);
|
||||
requestMatchers = this.matcherRegistry.requestMatchers("/**");
|
||||
|
@ -247,7 +254,7 @@ public class AbstractRequestMatcherRegistryTests {
|
|||
assertThat(requestMatchers).hasSize(1);
|
||||
assertThat(requestMatchers.get(0)).asInstanceOf(type(DispatcherServletDelegatingRequestMatcher.class))
|
||||
.extracting((matcher) -> matcher.requestMatcher(request))
|
||||
.isInstanceOf(MvcRequestMatcher.class);
|
||||
.isInstanceOf(PathPatternRequestMatcher.class);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ Corresponds to the `realmName` property on `BasicAuthenticationEntryPoint`.
|
|||
Defines the `RequestMatcher` strategy used in the `FilterChainProxy` and the beans created by the `intercept-url` to match incoming requests.
|
||||
Options are currently `mvc`, `ant`, `regex` and `ciRegex`, for Spring MVC, ant, regular-expression and case-insensitive regular-expression respectively.
|
||||
A separate instance is created for each <<nsa-intercept-url,intercept-url>> element using its <<nsa-intercept-url-pattern,pattern>>, <<nsa-intercept-url-method,method>> and <<nsa-intercept-url-servlet-path,servlet-path>> attributes.
|
||||
Ant paths are matched using an `AntPathRequestMatcher`, regular expressions are matched using a `RegexRequestMatcher` and for Spring MVC path matching the `MvcRequestMatcher` is used.
|
||||
Ant paths are matched using an `AntPathRequestMatcher`, regular expressions are matched using a `RegexRequestMatcher` and for Spring MVC path matching the `PathPatternRequestMatcher` is used.
|
||||
See the Javadoc for these classes for more details on exactly how the matching is performed.
|
||||
MVC is the default strategy if Spring MVC is present in the classpath, if not, Ant paths are used.
|
||||
|
||||
|
|
|
@ -22,13 +22,13 @@ This means that, if you use more advanced options, such as integrating with `Web
|
|||
====
|
||||
|
||||
[[mvc-requestmatcher]]
|
||||
== MvcRequestMatcher
|
||||
== PathPatternRequestMatcher
|
||||
|
||||
Spring Security provides deep integration with how Spring MVC matches on URLs with `MvcRequestMatcher`.
|
||||
Spring Security provides deep integration with how Spring MVC matches on URLs with `PahtPatternRequestMatcher`.
|
||||
This is helpful to ensure that your Security rules match the logic used to handle your requests.
|
||||
|
||||
To use `MvcRequestMatcher`, you must place the Spring Security Configuration in the same `ApplicationContext` as your `DispatcherServlet`.
|
||||
This is necessary because Spring Security's `MvcRequestMatcher` expects a `HandlerMappingIntrospector` bean with the name of `mvcHandlerMappingIntrospector` to be registered by your Spring MVC configuration that is used to perform the matching.
|
||||
To use `PathPatternRequestMatcher`, you may need to place the Spring Security Configuration in the same `ApplicationContext` as your `DispatcherServlet`.
|
||||
This is necessary when using a custom `PathPatternParser` `@Bean`. In this case, both Spring MVC and Spring Security needs to be able to see this bean.
|
||||
|
||||
For a `web.xml` file, this means that you should place your configuration in the `DispatcherServlet.xml`:
|
||||
|
||||
|
@ -196,18 +196,18 @@ Additionally, depending on our Spring MVC configuration, the `/admin` URL also m
|
|||
The problem is that our security rule protects only `/admin`.
|
||||
We could add additional rules for all the permutations of Spring MVC, but this would be quite verbose and tedious.
|
||||
|
||||
Fortunately, when using the `requestMatchers` DSL method, Spring Security automatically creates a `MvcRequestMatcher` if it detects that Spring MVC is available in the classpath.
|
||||
Fortunately, when using the `requestMatchers` DSL method, Spring Security automatically creates a `PathPatternRequestMatcher` if it detects that Spring MVC is available in the classpath.
|
||||
Therefore, it will protect the same URLs that Spring MVC will match on by using Spring MVC to match on the URL.
|
||||
|
||||
One common requirement when using Spring MVC is to specify the servlet path property.
|
||||
|
||||
For Java-based Configuration, you can use the `MvcRequestMatcher.Builder` to create multiple `MvcRequestMatcher` instances that share the same servlet path:
|
||||
For Java-based Configuration, you can use the `PathPatternRequestMatcher.Builder` to create multiple `PathPatternRequestMatcher` instances that share the same servlet path:
|
||||
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector).servletPath("/path");
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
PathPatternRequestMatcher.Builder mvcMatcherBuilder = new PathPatternRequestMatcher.Builder().servletPath("/path");
|
||||
http
|
||||
.authorizeHttpRequests((authorize) -> authorize
|
||||
.requestMatchers(mvcMatcherBuilder.pattern("/admin")).hasRole("ADMIN")
|
||||
|
@ -217,6 +217,11 @@ public SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospe
|
|||
}
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
=====
|
||||
For your convenience, you also can use `ServletRequestMatcherBuilders` which exposes an API that more directly reflects the Servlet spec.
|
||||
=====
|
||||
|
||||
For Kotlin and XML, this happens when you specify the servlet path for each path like so:
|
||||
|
||||
[tabs]
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
<suppress files="AbstractOAuth2AuthorizationGrantRequestEntityConverter\.java" checks="SpringMethodVisibility"/>
|
||||
<suppress files="JoseHeader\.java" checks="SpringMethodVisibility"/>
|
||||
<suppress files="DefaultLoginPageGeneratingFilterTests\.java" checks="SpringLeadingWhitespace"/>
|
||||
<suppress files="MatcherType\.java" checks="SpringMethodVisibility"/>
|
||||
<suppress files="MatcherType\.java" checks="RedundantModifier"/>
|
||||
|
||||
<!-- Lambdas that we can't replace with a method reference because a closure is required -->
|
||||
<suppress files="BearerTokenAuthenticationFilter\.java" checks="SpringLambda"/>
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.lang.reflect.Method;
|
|||
import java.lang.reflect.Proxy;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -178,6 +179,8 @@ public class FilterInvocation {
|
|||
|
||||
private final Map<String, String[]> parameters = new LinkedHashMap<>();
|
||||
|
||||
private final Map<String, Object> attributes = new HashMap<>();
|
||||
|
||||
DummyRequest() {
|
||||
super(UNSUPPORTED_REQUEST);
|
||||
}
|
||||
|
@ -189,7 +192,12 @@ public class FilterInvocation {
|
|||
|
||||
@Override
|
||||
public Object getAttribute(String attributeName) {
|
||||
return null;
|
||||
return this.attributes.get(attributeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String name, Object value) {
|
||||
this.attributes.put(name, value);
|
||||
}
|
||||
|
||||
void setRequestURI(String requestURI) {
|
||||
|
|
Loading…
Reference in New Issue