From 0384a88b57b70c2ad73f84447a87429ae0d83edf Mon Sep 17 00:00:00 2001 From: Madhura Bhave Date: Thu, 30 Aug 2018 15:43:17 -0700 Subject: [PATCH] Include web security config classes in @WebMvcTest Security config classes are not included when the secure flag is set to false. Closes gh-6514 --- .../autoconfigure/web/servlet/WebMvcTest.java | 4 ++- .../web/servlet/WebMvcTypeExcludeFilter.java | 32 +++++++++++++++++++ .../servlet/WebMvcTypeExcludeFilterTests.java | 28 ++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/WebMvcTest.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/WebMvcTest.java index d87377abd6..f1fe4ba56d 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/WebMvcTest.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/WebMvcTest.java @@ -141,7 +141,9 @@ public @interface WebMvcTest { /** * If Spring Security's {@link MockMvc} support should be auto-configured when it is - * on the classpath. Defaults to {@code true}. + * on the classpath. Also determines if + * {@link org.springframework.security.config.annotation.web.WebSecurityConfigurer} + * classes should be included in the application context. Defaults to {@code true}. * @return if Spring Security's MockMvc support is auto-configured * @deprecated since 2.1.0 in favor of Spring Security's testing support */ diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/WebMvcTypeExcludeFilter.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/WebMvcTypeExcludeFilter.java index ce53327a55..a74ef88efe 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/WebMvcTypeExcludeFilter.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/WebMvcTypeExcludeFilter.java @@ -33,6 +33,7 @@ import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.converter.GenericConverter; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.stereotype.Controller; +import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.method.support.HandlerMethodArgumentResolver; @@ -42,9 +43,12 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; * {@link TypeExcludeFilter} for {@link WebMvcTest @WebMvcTest}. * * @author Phillip Webb + * @author Madhura Bhave */ class WebMvcTypeExcludeFilter extends AnnotationCustomizableTypeExcludeFilter { + private static final String SECURITY_CONFIGURER = "org.springframework.security.config.annotation.web.WebSecurityConfigurer"; + private static final Set> DEFAULT_INCLUDES; static { @@ -63,6 +67,18 @@ class WebMvcTypeExcludeFilter extends AnnotationCustomizableTypeExcludeFilter { DEFAULT_INCLUDES = Collections.unmodifiableSet(includes); } + private static final Set> DEFAULT_INCLUDES_AND_SECURITY_CONFIGURER; + + static { + Set> includes = new LinkedHashSet<>(DEFAULT_INCLUDES); + try { + includes.add(ClassUtils.forName(SECURITY_CONFIGURER, null)); + } + catch (Exception ex) { + } + DEFAULT_INCLUDES_AND_SECURITY_CONFIGURER = Collections.unmodifiableSet(includes); + } + private static final Set> DEFAULT_INCLUDES_AND_CONTROLLER; static { @@ -71,6 +87,16 @@ class WebMvcTypeExcludeFilter extends AnnotationCustomizableTypeExcludeFilter { DEFAULT_INCLUDES_AND_CONTROLLER = Collections.unmodifiableSet(includes); } + private static final Set> DEFAULT_INCLUDES_SECURITY_CONFIGURER_AND_CONTROLLER; + + static { + Set> includes = new LinkedHashSet<>( + DEFAULT_INCLUDES_AND_SECURITY_CONFIGURER); + includes.add(Controller.class); + DEFAULT_INCLUDES_SECURITY_CONFIGURER_AND_CONTROLLER = Collections + .unmodifiableSet(includes); + } + private final WebMvcTest annotation; WebMvcTypeExcludeFilter(Class testClass) { @@ -101,6 +127,12 @@ class WebMvcTypeExcludeFilter extends AnnotationCustomizableTypeExcludeFilter { @Override protected Set> getDefaultIncludes() { + if (this.annotation.secure()) { + if (ObjectUtils.isEmpty(this.annotation.controllers())) { + return DEFAULT_INCLUDES_SECURITY_CONFIGURER_AND_CONTROLLER; + } + return DEFAULT_INCLUDES_AND_SECURITY_CONFIGURER; + } if (ObjectUtils.isEmpty(this.annotation.controllers())) { return DEFAULT_INCLUDES_AND_CONTROLLER; } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/servlet/WebMvcTypeExcludeFilterTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/servlet/WebMvcTypeExcludeFilterTests.java index 03da0a9362..a082bd6a69 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/servlet/WebMvcTypeExcludeFilterTests.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/servlet/WebMvcTypeExcludeFilterTests.java @@ -26,6 +26,7 @@ import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.classreading.SimpleMetadataReaderFactory; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.stereotype.Controller; import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service; @@ -54,6 +55,7 @@ public class WebMvcTypeExcludeFilterTests { assertThat(excludes(filter, ExampleMessageConverter.class)).isFalse(); assertThat(excludes(filter, ExampleService.class)).isTrue(); assertThat(excludes(filter, ExampleRepository.class)).isTrue(); + assertThat(excludes(filter, ExampleWebSecurityConfigurer.class)).isFalse(); } @Test @@ -67,6 +69,7 @@ public class WebMvcTypeExcludeFilterTests { assertThat(excludes(filter, ExampleMessageConverter.class)).isFalse(); assertThat(excludes(filter, ExampleService.class)).isTrue(); assertThat(excludes(filter, ExampleRepository.class)).isTrue(); + assertThat(excludes(filter, ExampleWebSecurityConfigurer.class)).isFalse(); } @Test @@ -80,6 +83,7 @@ public class WebMvcTypeExcludeFilterTests { assertThat(excludes(filter, ExampleMessageConverter.class)).isTrue(); assertThat(excludes(filter, ExampleService.class)).isTrue(); assertThat(excludes(filter, ExampleRepository.class)).isTrue(); + assertThat(excludes(filter, ExampleWebSecurityConfigurer.class)).isTrue(); } @Test @@ -106,6 +110,21 @@ public class WebMvcTypeExcludeFilterTests { assertThat(excludes(filter, ExampleMessageConverter.class)).isFalse(); assertThat(excludes(filter, ExampleService.class)).isTrue(); assertThat(excludes(filter, ExampleRepository.class)).isTrue(); + assertThat(excludes(filter, ExampleWebSecurityConfigurer.class)).isFalse(); + } + + @Test + public void matchWhenSecureFalse() throws Exception { + WebMvcTypeExcludeFilter filter = new WebMvcTypeExcludeFilter( + WithSecureFalse.class); + assertThat(excludes(filter, Controller1.class)).isFalse(); + assertThat(excludes(filter, Controller2.class)).isFalse(); + assertThat(excludes(filter, ExampleControllerAdvice.class)).isFalse(); + assertThat(excludes(filter, ExampleWeb.class)).isFalse(); + assertThat(excludes(filter, ExampleMessageConverter.class)).isFalse(); + assertThat(excludes(filter, ExampleService.class)).isTrue(); + assertThat(excludes(filter, ExampleRepository.class)).isTrue(); + assertThat(excludes(filter, ExampleWebSecurityConfigurer.class)).isTrue(); } private boolean excludes(WebMvcTypeExcludeFilter filter, Class type) @@ -140,6 +159,11 @@ public class WebMvcTypeExcludeFilterTests { } + @WebMvcTest(secure = false) + static class WithSecureFalse { + + } + @Controller static class Controller1 { @@ -173,4 +197,8 @@ public class WebMvcTypeExcludeFilterTests { } + static class ExampleWebSecurityConfigurer extends WebSecurityConfigurerAdapter { + + } + }