Apply springSecurity configurer to WebTestClient
Also, @WebFluxTest now adds any ServerHttpSecurity beans to the context. Closes gh-13632
This commit is contained in:
parent
424dfc398b
commit
ab6bdc7ae2
|
@ -29,6 +29,7 @@ import org.springframework.core.annotation.AnnotatedElementUtils;
|
|||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
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.reactive.config.WebFluxConfigurer;
|
||||
|
@ -43,6 +44,9 @@ class WebFluxTypeExcludeFilter extends AnnotationCustomizableTypeExcludeFilter {
|
|||
|
||||
private static final Set<Class<?>> DEFAULT_INCLUDES;
|
||||
|
||||
private static final String[] OPTIONAL_INCLUDES = {
|
||||
"org.springframework.security.config.web.server.ServerHttpSecurity" };
|
||||
|
||||
static {
|
||||
Set<Class<?>> includes = new LinkedHashSet<>();
|
||||
includes.add(ControllerAdvice.class);
|
||||
|
@ -51,6 +55,13 @@ class WebFluxTypeExcludeFilter extends AnnotationCustomizableTypeExcludeFilter {
|
|||
includes.add(Converter.class);
|
||||
includes.add(GenericConverter.class);
|
||||
includes.add(WebExceptionHandler.class);
|
||||
for (String optionalInclude : OPTIONAL_INCLUDES) {
|
||||
try {
|
||||
includes.add(ClassUtils.forName(optionalInclude, null));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
DEFAULT_INCLUDES = Collections.unmodifiableSet(includes);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@ import org.springframework.boot.web.codec.CodecCustomizer;
|
|||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.web.reactive.server.MockServerConfigurer;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import org.springframework.web.server.WebHandler;
|
||||
|
@ -47,6 +49,7 @@ import org.springframework.web.server.WebHandler;
|
|||
@Configuration
|
||||
@ConditionalOnClass({ WebClient.class, WebTestClient.class })
|
||||
@AutoConfigureAfter({ CodecsAutoConfiguration.class, WebFluxAutoConfiguration.class })
|
||||
@Import(WebTestClientSecurityConfiguration.class)
|
||||
@EnableConfigurationProperties
|
||||
public class WebTestClientAutoConfiguration {
|
||||
|
||||
|
@ -54,9 +57,14 @@ public class WebTestClientAutoConfiguration {
|
|||
@ConditionalOnMissingBean
|
||||
@ConditionalOnBean(WebHandler.class)
|
||||
public WebTestClient webTestClient(ApplicationContext applicationContext,
|
||||
List<WebTestClientBuilderCustomizer> customizers) {
|
||||
WebTestClient.Builder builder = WebTestClient
|
||||
.bindToApplicationContext(applicationContext).configureClient();
|
||||
List<WebTestClientBuilderCustomizer> customizers,
|
||||
List<MockServerConfigurer> configurers) {
|
||||
WebTestClient.MockServerSpec<?> mockServerSpec = WebTestClient
|
||||
.bindToApplicationContext(applicationContext);
|
||||
for (MockServerConfigurer configurer : configurers) {
|
||||
mockServerSpec.apply(configurer);
|
||||
}
|
||||
WebTestClient.Builder builder = mockServerSpec.configureClient();
|
||||
for (WebTestClientBuilderCustomizer customizer : customizers) {
|
||||
customizer.customize(builder);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright 2012-2018 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.boot.test.autoconfigure.web.reactive;
|
||||
|
||||
/** Configuration for Spring Security's {@link org.springframework.test.web.reactive.server.WebTestClient} integration.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers;
|
||||
import org.springframework.test.web.reactive.server.MockServerConfigurer;
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(SecurityMockServerConfigurers.class)
|
||||
class WebTestClientSecurityConfiguration {
|
||||
|
||||
@Bean
|
||||
public MockServerConfigurer get() {
|
||||
return SecurityMockServerConfigurers.springSecurity();
|
||||
}
|
||||
|
||||
}
|
|
@ -78,6 +78,8 @@ org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration
|
|||
|
||||
# AutoConfigureWebClient auto-configuration imports
|
||||
org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient=\
|
||||
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
|
||||
org.springframework.boot.test.autoconfigure.web.reactive.WebTestClientAutoConfiguration
|
||||
|
||||
# AutoConfigureWebFlux auto-configuration imports
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.springframework.context.annotation.Bean;
|
|||
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
|
||||
import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
import org.springframework.util.FileSystemUtils;
|
||||
|
@ -46,6 +47,7 @@ import static org.springframework.restdocs.webtestclient.WebTestClientRestDocume
|
|||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@WebFluxTest
|
||||
@WithMockUser
|
||||
@AutoConfigureRestDocs(uriScheme = "https", uriHost = "api.example.com", uriPort = 443)
|
||||
public class WebTestClientRestDocsAutoConfigurationAdvancedConfigurationIntegrationTests {
|
||||
|
||||
|
@ -59,8 +61,8 @@ public class WebTestClientRestDocsAutoConfigurationAdvancedConfigurationIntegrat
|
|||
|
||||
@Test
|
||||
public void defaultSnippetsAreWritten() throws Exception {
|
||||
this.webTestClient.get().uri("/").exchange().expectBody()
|
||||
.consumeWith(document("default-snippets"));
|
||||
this.webTestClient.get().uri("/").exchange().expectStatus().is2xxSuccessful()
|
||||
.expectBody().consumeWith(document("default-snippets"));
|
||||
File defaultSnippetsDir = new File("target/generated-snippets/default-snippets");
|
||||
assertThat(defaultSnippetsDir).exists();
|
||||
assertThat(new File(defaultSnippetsDir, "curl-request.md"))
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.junit.runner.RunWith;
|
|||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
import org.springframework.util.FileSystemUtils;
|
||||
|
@ -39,6 +40,7 @@ import static org.springframework.restdocs.webtestclient.WebTestClientRestDocume
|
|||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@WebFluxTest
|
||||
@WithMockUser
|
||||
@AutoConfigureRestDocs(uriScheme = "https", uriHost = "api.example.com", uriPort = 443)
|
||||
public class WebTestClientRestDocsAutoConfigurationIntegrationTests {
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.springframework.context.annotation.FilterType;
|
|||
import org.springframework.core.type.classreading.MetadataReader;
|
||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
@ -53,6 +54,7 @@ public class WebFluxTypeExcludeFilterTests {
|
|||
assertThat(excludes(filter, ExampleWeb.class)).isFalse();
|
||||
assertThat(excludes(filter, ExampleService.class)).isTrue();
|
||||
assertThat(excludes(filter, ExampleRepository.class)).isTrue();
|
||||
assertThat(excludes(filter, ExampleServerHttpSecurity.class)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -65,6 +67,7 @@ public class WebFluxTypeExcludeFilterTests {
|
|||
assertThat(excludes(filter, ExampleWeb.class)).isFalse();
|
||||
assertThat(excludes(filter, ExampleService.class)).isTrue();
|
||||
assertThat(excludes(filter, ExampleRepository.class)).isTrue();
|
||||
assertThat(excludes(filter, ExampleServerHttpSecurity.class)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -77,6 +80,7 @@ public class WebFluxTypeExcludeFilterTests {
|
|||
assertThat(excludes(filter, ExampleWeb.class)).isTrue();
|
||||
assertThat(excludes(filter, ExampleService.class)).isTrue();
|
||||
assertThat(excludes(filter, ExampleRepository.class)).isTrue();
|
||||
assertThat(excludes(filter, ExampleServerHttpSecurity.class)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -89,6 +93,7 @@ public class WebFluxTypeExcludeFilterTests {
|
|||
assertThat(excludes(filter, ExampleWeb.class)).isFalse();
|
||||
assertThat(excludes(filter, ExampleService.class)).isTrue();
|
||||
assertThat(excludes(filter, ExampleRepository.class)).isFalse();
|
||||
assertThat(excludes(filter, ExampleServerHttpSecurity.class)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -101,6 +106,7 @@ public class WebFluxTypeExcludeFilterTests {
|
|||
assertThat(excludes(filter, ExampleWeb.class)).isFalse();
|
||||
assertThat(excludes(filter, ExampleService.class)).isTrue();
|
||||
assertThat(excludes(filter, ExampleRepository.class)).isTrue();
|
||||
assertThat(excludes(filter, ExampleServerHttpSecurity.class)).isFalse();
|
||||
}
|
||||
|
||||
private boolean excludes(WebFluxTypeExcludeFilter filter, Class<?> type)
|
||||
|
@ -164,4 +170,8 @@ public class WebFluxTypeExcludeFilterTests {
|
|||
|
||||
}
|
||||
|
||||
static class ExampleServerHttpSecurity extends ServerHttpSecurity {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,19 +18,24 @@ package org.springframework.boot.test.autoconfigure.web.reactive;
|
|||
|
||||
import java.time.Duration;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.web.codec.CodecCustomizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.http.codec.CodecConfigurer;
|
||||
import org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
import org.springframework.web.server.WebHandler;
|
||||
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
|
@ -80,6 +85,41 @@ public class WebTestClientAutoConfigurationTests {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void shouldApplySpringSecurityConfigurer() {
|
||||
this.contextRunner.withUserConfiguration(BaseConfiguration.class)
|
||||
.run((context) -> {
|
||||
WebTestClient webTestClient = context.getBean(WebTestClient.class);
|
||||
WebTestClient.Builder builder = (WebTestClient.Builder) ReflectionTestUtils
|
||||
.getField(webTestClient, "builder");
|
||||
WebHttpHandlerBuilder httpHandlerBuilder = (WebHttpHandlerBuilder) ReflectionTestUtils
|
||||
.getField(builder, "httpHandlerBuilder");
|
||||
List<WebFilter> filters = (List<WebFilter>) ReflectionTestUtils
|
||||
.getField(httpHandlerBuilder, "filters");
|
||||
assertThat(filters.get(0).getClass().getName()).isEqualTo(
|
||||
"org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers$MutatorFilter");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void shouldNotApplySpringSecurityConfigurerWhenSpringSecurityNotOnClassPath() {
|
||||
FilteredClassLoader classLoader = new FilteredClassLoader(
|
||||
SecurityMockServerConfigurers.class);
|
||||
this.contextRunner.withUserConfiguration(BaseConfiguration.class)
|
||||
.withClassLoader(classLoader).run((context) -> {
|
||||
WebTestClient webTestClient = context.getBean(WebTestClient.class);
|
||||
WebTestClient.Builder builder = (WebTestClient.Builder) ReflectionTestUtils
|
||||
.getField(webTestClient, "builder");
|
||||
WebHttpHandlerBuilder httpHandlerBuilder = (WebHttpHandlerBuilder) ReflectionTestUtils
|
||||
.getField(builder, "httpHandlerBuilder");
|
||||
List<WebFilter> filters = (List<WebFilter>) ReflectionTestUtils
|
||||
.getField(httpHandlerBuilder, "filters");
|
||||
assertThat(filters.size()).isEqualTo(0);
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class BaseConfiguration {
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.junit.runner.RunWith;
|
|||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
|
@ -30,6 +31,7 @@ import org.springframework.test.web.reactive.server.WebTestClient;
|
|||
* @author Stephane Nicoll
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@WithMockUser
|
||||
@WebFluxTest
|
||||
public class WebFluxTestAllControllersIntegrationTests {
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.junit.runner.RunWith;
|
|||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
|
@ -32,6 +33,7 @@ import org.springframework.test.web.reactive.server.WebTestClient;
|
|||
* @author Stephane Nicoll
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@WithMockUser
|
||||
@WebFluxTest(controllers = ExampleController2.class)
|
||||
public class WebFluxTestConverterIntegrationTests {
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.junit.runner.RunWith;
|
|||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
|
@ -30,6 +31,7 @@ import org.springframework.test.web.reactive.server.WebTestClient;
|
|||
* @author Stephane Nicoll
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@WithMockUser
|
||||
@WebFluxTest(controllers = ExampleController1.class)
|
||||
public class WebFluxTestOneControllerIntegrationTests {
|
||||
|
||||
|
|
Loading…
Reference in New Issue