Skip to content

Commit e96203d

Browse files
committed
Merge remote-tracking branch 'origin/7.0.x' into 7.0.x
2 parents 1637727 + 3ef1c34 commit e96203d

28 files changed

Lines changed: 1954 additions & 98 deletions

File tree

config/src/main/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,9 @@ private Map<Class<?>, Object> createSharedObjects() {
238238
Map<Class<?>, Object> sharedObjects = new HashMap<>();
239239
sharedObjects.put(ApplicationContext.class, this.context);
240240
sharedObjects.put(ContentNegotiationStrategy.class, this.contentNegotiationStrategy);
241-
sharedObjects.put(PathPatternRequestMatcher.Builder.class, constructRequestMatcherBuilder(this.context));
241+
sharedObjects.put(PathPatternRequestMatcher.Builder.class,
242+
this.context.getBeanProvider(PathPatternRequestMatcher.Builder.class)
243+
.getIfUnique(() -> constructRequestMatcherBuilder(this.context)));
242244
return sharedObjects;
243245
}
244246

config/src/main/java/org/springframework/security/config/http/PathPatternRequestMatcherFactoryBean.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public void setApplicationContext(ApplicationContext context) throws BeansExcept
7070
@Override
7171
public void afterPropertiesSet() throws Exception {
7272
if (this.basePath != null) {
73-
this.builder.basePath(this.basePath);
73+
this.builder = this.builder.basePath(this.basePath);
7474
}
7575
}
7676

config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurerTests.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,18 @@ public void getWhenServletPathRoleAdminConfiguredAndRoleIsAdminThenRespondsWithO
452452
this.mvc.perform(requestWithAdmin).andExpect(status().isOk());
453453
}
454454

455+
@Test
456+
public void requestMatchersWhenBuilderBeanWithBasePathAndRawStringThenHonorsBasePath() throws Exception {
457+
this.spring.register(RequestMatchersRawStringServletPathConfig.class, BasicController.class).autowire();
458+
// @formatter:off
459+
MockHttpServletRequestBuilder matchedByBasePath = get("/spring/path")
460+
.servletPath("/spring")
461+
.with(user("user").roles("USER"));
462+
// @formatter:on
463+
this.mvc.perform(matchedByBasePath).andExpect(status().isForbidden());
464+
this.mvc.perform(get("/path").with(user("user").roles("USER"))).andExpect(status().isOk());
465+
}
466+
455467
@Test
456468
public void getWhenAnyRequestAuthenticatedConfiguredAndNoUserThenRespondsWithUnauthorized() throws Exception {
457469
this.spring.register(AuthenticatedConfig.class, BasicController.class).autowire();
@@ -1359,6 +1371,32 @@ SecurityFilterChain filterChain(HttpSecurity http, PathPatternRequestMatcher.Bui
13591371

13601372
}
13611373

1374+
@Configuration
1375+
@EnableWebMvc
1376+
@EnableWebSecurity
1377+
static class RequestMatchersRawStringServletPathConfig {
1378+
1379+
@Bean
1380+
PathPatternRequestMatcherBuilderFactoryBean requestMatcherBuilder() {
1381+
PathPatternRequestMatcherBuilderFactoryBean bean = new PathPatternRequestMatcherBuilderFactoryBean();
1382+
bean.setBasePath("/spring");
1383+
return bean;
1384+
}
1385+
1386+
@Bean
1387+
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
1388+
// @formatter:off
1389+
return http
1390+
.authorizeHttpRequests((authorize) -> authorize
1391+
.requestMatchers("/path").hasRole("ADMIN")
1392+
.anyRequest().permitAll()
1393+
)
1394+
.build();
1395+
// @formatter:on
1396+
}
1397+
1398+
}
1399+
13621400
@Configuration
13631401
@EnableWebSecurity
13641402
static class AuthenticatedConfig {

config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecuritySecurityMatchersTests.java

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,34 @@ public void securityMatchersWhensMvcMatcherServletPathInLambdaThenPathIsSecured(
125125
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
126126
}
127127

128+
@Test
129+
public void securityMatcherWhenBuilderBeanWithBasePathThenHonorsBasePath() throws Exception {
130+
loadConfig(SecurityMatcherBuilderBeanConfig.class);
131+
this.request.setServletPath("/spring");
132+
this.request.setRequestURI("/spring/path");
133+
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
134+
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
135+
setup();
136+
this.request.setServletPath("");
137+
this.request.setRequestURI("/path");
138+
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
139+
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
140+
}
141+
142+
@Test
143+
public void securityMatchersWhenBuilderBeanWithBasePathAndRawStringsThenHonorsBasePath() throws Exception {
144+
loadConfig(SecurityMatchersBuilderBeanConfig.class);
145+
this.request.setServletPath("/spring");
146+
this.request.setRequestURI("/spring/path");
147+
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
148+
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
149+
setup();
150+
this.request.setServletPath("");
151+
this.request.setRequestURI("/path");
152+
this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
153+
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
154+
}
155+
128156
@Test
129157
public void securityMatchersWhenMultiMvcMatcherInLambdaThenAllPathsAreDenied() throws Exception {
130158
loadConfig(MultiMvcMatcherInLambdaConfig.class);
@@ -430,6 +458,83 @@ String path() {
430458

431459
}
432460

461+
@EnableWebSecurity
462+
@Configuration
463+
@EnableWebMvc
464+
@Import(UsersConfig.class)
465+
static class SecurityMatcherBuilderBeanConfig {
466+
467+
@Bean
468+
PathPatternRequestMatcherBuilderFactoryBean requestMatcherBuilder() {
469+
PathPatternRequestMatcherBuilderFactoryBean bean = new PathPatternRequestMatcherBuilderFactoryBean();
470+
bean.setBasePath("/spring");
471+
return bean;
472+
}
473+
474+
@Bean
475+
SecurityFilterChain appSecurity(HttpSecurity http) throws Exception {
476+
// @formatter:off
477+
http
478+
.securityMatcher("/path")
479+
.httpBasic(withDefaults())
480+
.authorizeHttpRequests((authorize) -> authorize
481+
.anyRequest().denyAll());
482+
// @formatter:on
483+
return http.build();
484+
}
485+
486+
@RestController
487+
static class PathController {
488+
489+
@RequestMapping("/path")
490+
String path() {
491+
return "path";
492+
}
493+
494+
}
495+
496+
}
497+
498+
@EnableWebSecurity
499+
@Configuration
500+
@EnableWebMvc
501+
@Import(UsersConfig.class)
502+
static class SecurityMatchersBuilderBeanConfig {
503+
504+
@Bean
505+
PathPatternRequestMatcherBuilderFactoryBean requestMatcherBuilder() {
506+
PathPatternRequestMatcherBuilderFactoryBean bean = new PathPatternRequestMatcherBuilderFactoryBean();
507+
bean.setBasePath("/spring");
508+
return bean;
509+
}
510+
511+
@Bean
512+
SecurityFilterChain appSecurity(HttpSecurity http) throws Exception {
513+
// @formatter:off
514+
http
515+
.securityMatchers((matchers) -> matchers
516+
.requestMatchers("/path")
517+
)
518+
.httpBasic(withDefaults())
519+
.authorizeHttpRequests((authorize) -> authorize
520+
.anyRequest().denyAll()
521+
);
522+
// @formatter:on
523+
return http.build();
524+
}
525+
526+
@RestController
527+
static class PathController {
528+
529+
@RequestMapping("/path")
530+
String path() {
531+
return "path";
532+
}
533+
534+
}
535+
536+
}
537+
433538
@Configuration
434539
static class UsersConfig {
435540

0 commit comments

Comments
 (0)