diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java
index c609fa6056..175cf5b11f 100644
--- a/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java
+++ b/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java
@@ -2234,6 +2234,107 @@ public final class HttpSecurity extends
return requestMatcherConfigurer;
}
+ /**
+ * Allows specifying which {@link HttpServletRequest} instances this
+ * {@link HttpSecurity} will be invoked on. This method allows for easily invoking the
+ * {@link HttpSecurity} for multiple different {@link RequestMatcher} instances. If
+ * only a single {@link RequestMatcher} is necessary consider using {@link #mvcMatcher(String)},
+ * {@link #antMatcher(String)}, {@link #regexMatcher(String)}, or
+ * {@link #requestMatcher(RequestMatcher)}.
+ *
+ *
+ * Invoking {@link #requestMatchers()} will not override previous invocations of {@link #mvcMatcher(String)}},
+ * {@link #requestMatchers()}, {@link #antMatcher(String)},
+ * {@link #regexMatcher(String)}, and {@link #requestMatcher(RequestMatcher)}.
+ *
+ *
+ * Example Configurations
+ *
+ * The following configuration enables the {@link HttpSecurity} for URLs that begin
+ * with "/api/" or "/oauth/".
+ *
+ *
+ * @Configuration
+ * @EnableWebSecurity
+ * public class RequestMatchersSecurityConfig extends WebSecurityConfigurerAdapter {
+ *
+ * @Override
+ * protected void configure(HttpSecurity http) throws Exception {
+ * http
+ * .requestMatchers(requestMatchers ->
+ * requestMatchers
+ * .antMatchers("/api/**", "/oauth/**")
+ * )
+ * .authorizeRequests(authorizeRequests ->
+ * authorizeRequests
+ * .antMatchers("/**").hasRole("USER")
+ * )
+ * .httpBasic(withDefaults());
+ * }
+ * }
+ *
+ *
+ * The configuration below is the same as the previous configuration.
+ *
+ *
+ * @Configuration
+ * @EnableWebSecurity
+ * public class RequestMatchersSecurityConfig extends WebSecurityConfigurerAdapter {
+ *
+ * @Override
+ * protected void configure(HttpSecurity http) throws Exception {
+ * http
+ * .requestMatchers(requestMatchers ->
+ * requestMatchers
+ * .antMatchers("/api/**")
+ * .antMatchers("/oauth/**")
+ * )
+ * .authorizeRequests(authorizeRequests ->
+ * authorizeRequests
+ * .antMatchers("/**").hasRole("USER")
+ * )
+ * .httpBasic(withDefaults());
+ * }
+ * }
+ *
+ *
+ * The configuration below is also the same as the above configuration.
+ *
+ *
+ * @Configuration
+ * @EnableWebSecurity
+ * public class RequestMatchersSecurityConfig extends WebSecurityConfigurerAdapter {
+ *
+ * @Override
+ * protected void configure(HttpSecurity http) throws Exception {
+ * http
+ * .requestMatchers(requestMatchers ->
+ * requestMatchers
+ * .antMatchers("/api/**")
+ * )
+ * .requestMatchers(requestMatchers ->
+ * requestMatchers
+ * .antMatchers("/oauth/**")
+ * )
+ * .authorizeRequests(authorizeRequests ->
+ * authorizeRequests
+ * .antMatchers("/**").hasRole("USER")
+ * )
+ * .httpBasic(withDefaults());
+ * }
+ * }
+ *
+ *
+ * @param requestMatcherCustomizer the {@link Customizer} to provide more options for
+ * the {@link RequestMatcherConfigurer}
+ * @return the {@link HttpSecurity} for further customizations
+ * @throws Exception
+ */
+ public HttpSecurity requestMatchers(Customizer requestMatcherCustomizer) throws Exception {
+ requestMatcherCustomizer.customize(requestMatcherConfigurer);
+ return HttpSecurity.this;
+ }
+
/**
* Allows configuring the {@link HttpSecurity} to only be invoked when matching the
* provided {@link RequestMatcher}. If more advanced configuration is necessary,
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityRequestMatchersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityRequestMatchersTests.java
index c05f8064a6..ef4d4a2e42 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityRequestMatchersTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityRequestMatchersTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -38,6 +38,7 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationCon
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.springframework.security.config.Customizer.withDefaults;
/**
* @author Rob Winch
@@ -195,6 +196,62 @@ public class HttpSecurityRequestMatchersTests {
}
}
+ @Test
+ public void requestMatchersWhenMvcMatcherInLambdaThenPathIsSecured() throws Exception {
+ loadConfig(RequestMatchersMvcMatcherInLambdaConfig.class);
+
+ this.request.setServletPath("/path");
+ this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+ assertThat(this.response.getStatus())
+ .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
+
+ setup();
+
+ this.request.setServletPath("/path.html");
+ this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+ assertThat(this.response.getStatus())
+ .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
+
+ setup();
+
+ this.request.setServletPath("/path/");
+ this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+ assertThat(this.response.getStatus())
+ .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
+ }
+
+ @EnableWebSecurity
+ @Configuration
+ @EnableWebMvc
+ static class RequestMatchersMvcMatcherInLambdaConfig extends WebSecurityConfigurerAdapter {
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ // @formatter:off
+ http
+ .requestMatchers(requestMatchers ->
+ requestMatchers
+ .mvcMatchers("/path")
+ )
+ .httpBasic(withDefaults())
+ .authorizeRequests(authorizeRequests ->
+ authorizeRequests
+ .anyRequest().denyAll()
+ );
+ // @formatter:on
+ }
+
+ @RestController
+ static class PathController {
+ @RequestMapping("/path")
+ public String path() {
+ return "path";
+ }
+ }
+ }
+
@Test
public void requestMatchersMvcMatcherServletPath() throws Exception {
loadConfig(RequestMatchersMvcMatcherServeltPathConfig.class);
@@ -260,6 +317,66 @@ public class HttpSecurityRequestMatchersTests {
}
}
+ @Test
+ public void requestMatcherWhensMvcMatcherServletPathInLambdaThenPathIsSecured() throws Exception {
+ loadConfig(RequestMatchersMvcMatcherServletPathInLambdaConfig.class);
+
+ this.request.setServletPath("/spring");
+ this.request.setRequestURI("/spring/path");
+ this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+ assertThat(this.response.getStatus())
+ .isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
+
+ setup();
+
+ this.request.setServletPath("");
+ this.request.setRequestURI("/path");
+ this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+ assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
+
+ setup();
+
+ this.request.setServletPath("/other");
+ this.request.setRequestURI("/other/path");
+
+ this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+ assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
+ }
+
+ @EnableWebSecurity
+ @Configuration
+ @EnableWebMvc
+ static class RequestMatchersMvcMatcherServletPathInLambdaConfig
+ extends WebSecurityConfigurerAdapter {
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ // @formatter:off
+ http
+ .requestMatchers(requestMatchers ->
+ requestMatchers
+ .mvcMatchers("/path").servletPath("/spring")
+ .mvcMatchers("/never-match")
+ )
+ .httpBasic(withDefaults())
+ .authorizeRequests(authorizeRequests ->
+ authorizeRequests
+ .anyRequest().denyAll()
+ );
+ // @formatter:on
+ }
+
+ @RestController
+ static class PathController {
+ @RequestMapping("/path")
+ public String path() {
+ return "path";
+ }
+ }
+ }
+
public void loadConfig(Class>... configs) {
this.context = new AnnotationConfigWebApplicationContext();
this.context.register(configs);
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestMatcherConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestMatcherConfigurerTests.java
index c47b8f970f..4bc131761b 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestMatcherConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestMatcherConfigurerTests.java
@@ -71,4 +71,37 @@ public class RequestMatcherConfigurerTests {
// @formatter:on
}
}
+
+ @Test
+ public void authorizeRequestsWhenInvokedMultipleTimesInLambdaThenChainsPaths() throws Exception {
+ this.spring.register(AuthorizeRequestInLambdaConfig.class).autowire();
+
+ this.mvc.perform(get("/oauth/abc"))
+ .andExpect(status().isForbidden());
+ this.mvc.perform(get("/api/abc"))
+ .andExpect(status().isForbidden());
+ }
+
+ @EnableWebSecurity
+ static class AuthorizeRequestInLambdaConfig extends WebSecurityConfigurerAdapter {
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ // @formatter:off
+ http
+ .requestMatchers(requestMatchers ->
+ requestMatchers
+ .antMatchers("/api/**")
+ )
+ .requestMatchers(requestMatchers ->
+ requestMatchers
+ .antMatchers("/oauth/**")
+ )
+ .authorizeRequests(authorizeRequests ->
+ authorizeRequests
+ .anyRequest().denyAll()
+ );
+ // @formatter:on
+ }
+ }
}