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 61200331c4..f59c2218be 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2016 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. @@ -65,6 +65,7 @@ import org.springframework.security.web.PortMapper; import org.springframework.security.web.PortMapperImpl; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; +import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; import org.springframework.security.web.session.HttpSessionEventPublisher; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.AnyRequestMatcher; @@ -1080,12 +1081,12 @@ public final class HttpSecurity extends * 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 + * 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 + * Invoking {@link #requestMatchers()} will not override previous invocations of {@link #mvcMatcher(String)}}, * {@link #requestMatchers()}, {@link #antMatcher(String)}, * {@link #regexMatcher(String)}, and {@link #requestMatcher(RequestMatcher)}. *
@@ -1194,7 +1195,7 @@ public final class HttpSecurity extends * ** Invoking {@link #requestMatcher(RequestMatcher)} will override previous invocations - * of {@link #requestMatchers()}, {@link #antMatcher(String)}, + * of {@link #requestMatchers()}, {@link #mvcMatcher(String)}, {@link #antMatcher(String)}, * {@link #regexMatcher(String)}, and {@link #requestMatcher(RequestMatcher)}. *
* @@ -1216,7 +1217,7 @@ public final class HttpSecurity extends * {@link #requestMatchers()} or {@link #requestMatcher(RequestMatcher)}. * *- * Invoking {@link #antMatcher(String)} will override previous invocations of + * Invoking {@link #antMatcher(String)} will override previous invocations of {@link #mvcMatcher(String)}}, * {@link #requestMatchers()}, {@link #antMatcher(String)}, * {@link #regexMatcher(String)}, and {@link #requestMatcher(RequestMatcher)}. *
@@ -1229,13 +1230,33 @@ public final class HttpSecurity extends return requestMatcher(new AntPathRequestMatcher(antPattern)); } + /** + * Allows configuring the {@link HttpSecurity} to only be invoked when matching the + * provided Spring MVC pattern. If more advanced configuration is necessary, consider using + * {@link #requestMatchers()} or {@link #requestMatcher(RequestMatcher)}. + * + *+ * Invoking {@link #mvcMatcher(String)} will override previous invocations of {@link #mvcMatcher(String)}}, + * {@link #requestMatchers()}, {@link #antMatcher(String)}, + * {@link #regexMatcher(String)}, and {@link #requestMatcher(RequestMatcher)}. + *
+ * + * @param mvcPattern the Spring MVC Pattern to match on (i.e. "/admin/**") + * @return the {@link HttpSecurity} for further customizations + * @see MvcRequestMatcher + */ + public HttpSecurity mvcMatcher(String mvcPattern) { + HandlerMappingIntrospector introspector = new HandlerMappingIntrospector(getContext()); + return requestMatcher(new MvcRequestMatcher(introspector, mvcPattern)); + } + /** * Allows configuring the {@link HttpSecurity} to only be invoked when matching the * provided regex pattern. If more advanced configuration is necessary, consider using * {@link #requestMatchers()} or {@link #requestMatcher(RequestMatcher)}. * *- * Invoking {@link #regexMatcher(String)} will override previous invocations of + * Invoking {@link #regexMatcher(String)} will override previous invocations of {@link #mvcMatcher(String)}}, * {@link #requestMatchers()}, {@link #antMatcher(String)}, * {@link #regexMatcher(String)}, and {@link #requestMatcher(RequestMatcher)}. *
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 23ed6e30e7..b86302bb9a 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 @@ -68,6 +68,65 @@ public class HttpSecurityRequestMatchersTests { } } + @Test + public void mvcMatcher() throws Exception { + loadConfig(MvcMatcherConfig.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 MvcMatcherConfig extends WebSecurityConfigurerAdapter { + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http + .mvcMatcher("/path") + .httpBasic().and() + .authorizeRequests() + .anyRequest().denyAll(); + // @formatter:on + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off + auth + .inMemoryAuthentication(); + // @formatter:on + } + + @RestController + static class PathController { + @RequestMapping("/path") + public String path() { + return "path"; + } + } + } + @Test public void requestMatchersMvcMatcher() throws Exception { loadConfig(RequestMatchersMvcMatcherConfig.class);