Browse Source

Allow configuration of request matchers through nested builder

Issue: gh-5557
pull/7099/head
Eleftheria Stein 7 years ago
parent
commit
c3dad06ea6
  1. 101
      config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java
  2. 119
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityRequestMatchersTests.java
  3. 33
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestMatcherConfigurerTests.java

101
config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java

@ -2234,6 +2234,107 @@ public final class HttpSecurity extends @@ -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)}.
*
* <p>
* Invoking {@link #requestMatchers()} will not override previous invocations of {@link #mvcMatcher(String)}},
* {@link #requestMatchers()}, {@link #antMatcher(String)},
* {@link #regexMatcher(String)}, and {@link #requestMatcher(RequestMatcher)}.
* </p>
*
* <h3>Example Configurations</h3>
*
* The following configuration enables the {@link HttpSecurity} for URLs that begin
* with "/api/" or "/oauth/".
*
* <pre>
* &#064;Configuration
* &#064;EnableWebSecurity
* public class RequestMatchersSecurityConfig extends WebSecurityConfigurerAdapter {
*
* &#064;Override
* protected void configure(HttpSecurity http) throws Exception {
* http
* .requestMatchers(requestMatchers ->
* requestMatchers
* .antMatchers(&quot;/api/**&quot;, &quot;/oauth/**&quot;)
* )
* .authorizeRequests(authorizeRequests ->
* authorizeRequests
* .antMatchers(&quot;/**&quot;).hasRole(&quot;USER&quot;)
* )
* .httpBasic(withDefaults());
* }
* }
* </pre>
*
* The configuration below is the same as the previous configuration.
*
* <pre>
* &#064;Configuration
* &#064;EnableWebSecurity
* public class RequestMatchersSecurityConfig extends WebSecurityConfigurerAdapter {
*
* &#064;Override
* protected void configure(HttpSecurity http) throws Exception {
* http
* .requestMatchers(requestMatchers ->
* requestMatchers
* .antMatchers(&quot;/api/**&quot;)
* .antMatchers(&quot;/oauth/**&quot;)
* )
* .authorizeRequests(authorizeRequests ->
* authorizeRequests
* .antMatchers(&quot;/**&quot;).hasRole(&quot;USER&quot;)
* )
* .httpBasic(withDefaults());
* }
* }
* </pre>
*
* The configuration below is also the same as the above configuration.
*
* <pre>
* &#064;Configuration
* &#064;EnableWebSecurity
* public class RequestMatchersSecurityConfig extends WebSecurityConfigurerAdapter {
*
* &#064;Override
* protected void configure(HttpSecurity http) throws Exception {
* http
* .requestMatchers(requestMatchers ->
* requestMatchers
* .antMatchers(&quot;/api/**&quot;)
* )
* .requestMatchers(requestMatchers ->
* requestMatchers
* .antMatchers(&quot;/oauth/**&quot;)
* )
* .authorizeRequests(authorizeRequests ->
* authorizeRequests
* .antMatchers(&quot;/**&quot;).hasRole(&quot;USER&quot;)
* )
* .httpBasic(withDefaults());
* }
* }
* </pre>
*
* @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<RequestMatcherConfigurer> 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,

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

@ -1,5 +1,5 @@ @@ -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 @@ -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 { @@ -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 { @@ -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);

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

@ -71,4 +71,37 @@ public class RequestMatcherConfigurerTests { @@ -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
}
}
}

Loading…
Cancel
Save