1
0
mirror of synced 2026-05-22 21:33:16 +00:00

Add setBasePath

Originally, it was thought that this feature would be rather uncommon;
however, given some feedback from the Boot team, it makes sense to make
this easier to configure.

Of specific note is migrating from an earlier version were the
servlet path did not need to be specified in authorizeHttpRequests.
Since it does in 7, this will be a significant migration for those
who have a servlet path configured. This setter simplifies that a great
deal, including simplifying Boot's support of it.

Closes gh-17579
This commit is contained in:
Josh Cummings
2025-07-20 22:57:06 -06:00
parent 15fc898804
commit 63e0a56bee
2 changed files with 37 additions and 2 deletions
@@ -46,6 +46,8 @@ public final class PathPatternRequestMatcherBuilderFactoryBean implements
private final PathPatternParser parser;
private String basePath;
private ApplicationContext context;
private String beanName;
@@ -78,23 +80,43 @@ public final class PathPatternRequestMatcherBuilderFactoryBean implements
public PathPatternRequestMatcher.Builder getObject() throws Exception {
if (!this.context.containsBean(MVC_PATTERN_PARSER_BEAN_NAME)) {
PathPatternParser parser = (this.parser != null) ? this.parser : PathPatternParser.defaultInstance;
return PathPatternRequestMatcher.withPathPatternParser(parser);
return withPathPatternParser(parser);
}
PathPatternParser mvc = this.context.getBean(MVC_PATTERN_PARSER_BEAN_NAME, PathPatternParser.class);
PathPatternParser parser = (this.parser != null) ? this.parser : mvc;
if (mvc.equals(parser)) {
return PathPatternRequestMatcher.withPathPatternParser(parser);
return withPathPatternParser(parser);
}
throw new IllegalArgumentException("Spring Security and Spring MVC must use the same path pattern parser. "
+ "To have Spring Security use Spring MVC's [" + describe(mvc, MVC_PATTERN_PARSER_BEAN_NAME)
+ "] simply publish this bean [" + describe(this, this.beanName) + "] using its default constructor");
}
private PathPatternRequestMatcher.Builder withPathPatternParser(PathPatternParser parser) {
if (this.basePath == null) {
return PathPatternRequestMatcher.withPathPatternParser(parser);
}
else {
return PathPatternRequestMatcher.withPathPatternParser(parser).basePath(this.basePath);
}
}
@Override
public Class<?> getObjectType() {
return PathPatternRequestMatcher.Builder.class;
}
/**
* Use this as the base path for patterns built by the resulting
* {@link PathPatternRequestMatcher.Builder} instance
* @param basePath the base path to use
* @since 7.0
* @see PathPatternRequestMatcher.Builder#basePath(String)
*/
public void setBasePath(String basePath) {
this.basePath = basePath;
}
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
this.context = context;
@@ -22,9 +22,11 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.security.web.servlet.TestMockHttpServletRequests;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.web.util.pattern.PathPatternParser;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -75,6 +77,17 @@ class PathPatternRequestMatcherBuilderFactoryBeanTests {
verify(mvc).parse("/path/**");
}
@Test
void getObjectWhenBasePathThenUses() throws Exception {
PathPatternRequestMatcherBuilderFactoryBean factoryBean = new PathPatternRequestMatcherBuilderFactoryBean();
factoryBean.setApplicationContext(this.context);
factoryBean.setBasePath("/mvc");
PathPatternRequestMatcher.Builder builder = factoryBean.getObject();
PathPatternRequestMatcher matcher = builder.matcher("/path/**");
assertThat(matcher.matches(TestMockHttpServletRequests.get("/mvc/path/123").build())).isTrue();
assertThat(matcher.matches(TestMockHttpServletRequests.get("/path/123").build())).isFalse();
}
PathPatternRequestMatcherBuilderFactoryBean factoryBean() {
PathPatternRequestMatcherBuilderFactoryBean factoryBean = new PathPatternRequestMatcherBuilderFactoryBean();
factoryBean.setApplicationContext(this.context);