This commit is contained in:
Phillip Webb 2017-12-21 19:12:05 -08:00
parent 6eabe8235c
commit ba86b68484
9 changed files with 213 additions and 163 deletions

View File

@ -51,33 +51,38 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager;
UserDetailsService.class })
public class AuthenticationManagerConfiguration {
private final Pattern pattern = Pattern.compile("^\\{.+}.*$");
private static final String NOOP_PASSWORD_PREFIX = "{noop}";
private static final Pattern PASSWORD_ALGORITHM_PATTERN = Pattern
.compile("^\\{.+}.*$");
private static final Log logger = LogFactory
.getLog(AuthenticationManagerConfiguration.class);
private static final String NOOP_PREFIX = "{noop}";
@Bean
public InMemoryUserDetailsManager inMemoryUserDetailsManager(SecurityProperties properties,
public InMemoryUserDetailsManager inMemoryUserDetailsManager(
SecurityProperties properties,
ObjectProvider<PasswordEncoder> passwordEncoder) throws Exception {
SecurityProperties.User user = properties.getUser();
if (user.isPasswordGenerated()) {
logger.info(String.format("%n%nUsing generated security password: %s%n", user.getPassword()));
}
String password = deducePassword(passwordEncoder, user.getPassword());
List<String> roles = user.getRoles();
return new InMemoryUserDetailsManager(
User.withUsername(user.getName()).password(password)
.roles(roles.toArray(new String[roles.size()])).build());
User.withUsername(user.getName())
.password(getOrDeducePassword(user,
passwordEncoder.getIfAvailable()))
.roles(roles.toArray(new String[roles.size()])).build());
}
private String deducePassword(ObjectProvider<PasswordEncoder> passwordEncoder, String password) {
if (passwordEncoder.getIfAvailable() == null &&
!this.pattern.matcher(password).matches()) {
return NOOP_PREFIX + password;
public String getOrDeducePassword(SecurityProperties.User user,
PasswordEncoder encoder) {
String password = user.getPassword();
if (user.isPasswordGenerated()) {
logger.info(String.format("%n%nUsing generated security password: %s%n",
user.getPassword()));
}
return password;
if (encoder != null || PASSWORD_ALGORITHM_PATTERN.matcher(password).matches()) {
return password;
}
return NOOP_PASSWORD_PREFIX + password;
}
}

View File

@ -51,9 +51,10 @@ import org.springframework.security.crypto.password.PasswordEncoder;
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
class ReactiveAuthenticationManagerConfiguration {
private final Pattern pattern = Pattern.compile("^\\{.+}.*$");
private static final String NOOP_PASSWORD_PREFIX = "{noop}";
private static final String NOOP_PREFIX = "{noop}";
private static final Pattern PASSWORD_ALGORITHM_PATTERN = Pattern
.compile("^\\{.+}.*$");
private static final Log logger = LogFactory
.getLog(ReactiveAuthenticationManagerConfiguration.class);
@ -63,28 +64,28 @@ class ReactiveAuthenticationManagerConfiguration {
SecurityProperties properties,
ObjectProvider<PasswordEncoder> passwordEncoder) {
SecurityProperties.User user = properties.getUser();
if (user.isPasswordGenerated()) {
logger.info(String.format("%n%nUsing default security password: %s%n",
user.getPassword()));
}
String password = deducePassword(passwordEncoder, user.getPassword());
UserDetails userDetails = getUserDetails(user, password);
UserDetails userDetails = getUserDetails(user,
getOrDeducePassword(user, passwordEncoder.getIfAvailable()));
return new MapReactiveUserDetailsService(userDetails);
}
private String deducePassword(ObjectProvider<PasswordEncoder> passwordEncoder, String password) {
if (passwordEncoder.getIfAvailable() == null &&
!this.pattern.matcher(password).matches()) {
return NOOP_PREFIX + password;
}
return password;
}
private UserDetails getUserDetails(SecurityProperties.User user,
String password) {
private UserDetails getUserDetails(SecurityProperties.User user, String password) {
List<String> roles = user.getRoles();
return User.withUsername(user.getName()).password(password)
.roles(roles.toArray(new String[roles.size()])).build();
}
private String getOrDeducePassword(SecurityProperties.User user,
PasswordEncoder encoder) {
String password = user.getPassword();
if (user.isPasswordGenerated()) {
logger.info(String.format("%n%nUsing default security password: %s%n",
user.getPassword()));
}
if (encoder != null || PASSWORD_ALGORITHM_PATTERN.matcher(password).matches()) {
return password;
}
return NOOP_PASSWORD_PREFIX + password;
}
}

View File

@ -34,35 +34,35 @@ import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
* {@link org.springframework.format.support.FormattingConversionService} dedicated
* to web applications for formatting and converting values to/from the web.
*
* <p>This service replaces the default implementations provided by
* {@link org.springframework.web.servlet.config.annotation.EnableWebMvc}
* and {@link org.springframework.web.reactive.config.EnableWebFlux}.
* {@link org.springframework.format.support.FormattingConversionService} dedicated to web
* applications for formatting and converting values to/from the web.
* <p>
* This service replaces the default implementations provided by
* {@link org.springframework.web.servlet.config.annotation.EnableWebMvc} and
* {@link org.springframework.web.reactive.config.EnableWebFlux}.
*
* @author Brian Clozel
* @since 2.0.0
*/
public class WebConversionService extends DefaultFormattingConversionService {
private static final boolean jsr354Present = ClassUtils
.isPresent("javax.money.MonetaryAmount", WebConversionService.class.getClassLoader());
private static final boolean jsr354Present = ClassUtils.isPresent(
"javax.money.MonetaryAmount", WebConversionService.class.getClassLoader());
private static final boolean jodaTimePresent = ClassUtils
.isPresent("org.joda.time.LocalDate", WebConversionService.class.getClassLoader());
private static final boolean jodaTimePresent = ClassUtils.isPresent(
"org.joda.time.LocalDate", WebConversionService.class.getClassLoader());
private String dateFormat;
private final String dateFormat;
/**
* Create a new WebConversionService that configures formatters with the provided date format,
* or register the default ones if no custom format is provided.
* Create a new WebConversionService that configures formatters with the provided date
* format, or register the default ones if no custom format is provided.
* @param dateFormat the custom date format to use for date conversions
*/
public WebConversionService(String dateFormat) {
super(false);
if (StringUtils.hasText(dateFormat)) {
this.dateFormat = dateFormat;
this.dateFormat = (StringUtils.hasText(dateFormat) ? dateFormat : null);
if (this.dateFormat != null) {
addFormatters();
}
else {
@ -70,13 +70,13 @@ public class WebConversionService extends DefaultFormattingConversionService {
}
}
private void addFormatters() {
addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory());
if (jsr354Present) {
addFormatter(new CurrencyUnitFormatter());
addFormatter(new MonetaryAmountFormatter());
addFormatterForFieldAnnotation(new Jsr354NumberFormatAnnotationFormatterFactory());
addFormatterForFieldAnnotation(
new Jsr354NumberFormatAnnotationFormatterFactory());
}
registerJsr310();
if (jodaTimePresent) {
@ -88,10 +88,8 @@ public class WebConversionService extends DefaultFormattingConversionService {
private void registerJsr310() {
DateTimeFormatterRegistrar dateTime = new DateTimeFormatterRegistrar();
if (this.dateFormat != null) {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter
.ofPattern(this.dateFormat)
.withResolverStyle(ResolverStyle.STRICT);
dateTime.setDateFormatter(dateTimeFormatter);
dateTime.setDateFormatter(DateTimeFormatter.ofPattern(this.dateFormat)
.withResolverStyle(ResolverStyle.STRICT));
}
dateTime.registerFormatters(this);
}
@ -99,10 +97,8 @@ public class WebConversionService extends DefaultFormattingConversionService {
private void registerJodaTime() {
JodaTimeFormatterRegistrar jodaTime = new JodaTimeFormatterRegistrar();
if (this.dateFormat != null) {
org.joda.time.format.DateTimeFormatter dateTimeFormatter = new DateTimeFormatterBuilder()
.appendPattern(this.dateFormat)
.toFormatter();
jodaTime.setDateFormatter(dateTimeFormatter);
jodaTime.setDateFormatter(new DateTimeFormatterBuilder()
.appendPattern(this.dateFormat).toFormatter());
}
jodaTime.registerFormatters(this);
}
@ -115,4 +111,5 @@ public class WebConversionService extends DefaultFormattingConversionService {
}
dateFormatterRegistrar.registerFormatters(this);
}
}

View File

@ -223,7 +223,8 @@ public class WebFluxAutoConfiguration {
@Bean
@Override
public FormattingConversionService webFluxConversionService() {
WebConversionService conversionService = new WebConversionService(this.webFluxProperties.getDateFormat());
WebConversionService conversionService = new WebConversionService(
this.webFluxProperties.getDateFormat());
addFormatters(conversionService);
return conversionService;
}

View File

@ -301,8 +301,8 @@ public class WebMvcAutoConfiguration {
return;
}
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol()
.toHttpCacheControl();
CacheControl cacheControl = this.resourceProperties.getCache()
.getCachecontrol().toHttpCacheControl();
if (!registry.hasMappingForPattern("/webjars/**")) {
customizeResourceHandlerRegistration(
registry.addResourceHandler("/webjars/**")
@ -475,7 +475,8 @@ public class WebMvcAutoConfiguration {
@Bean
@Override
public FormattingConversionService mvcConversionService() {
WebConversionService conversionService = new WebConversionService(this.mvcProperties.getDateFormat());
WebConversionService conversionService = new WebConversionService(
this.mvcProperties.getDateFormat());
addFormatters(conversionService);
return conversionService;
}

View File

@ -40,22 +40,27 @@ public class AuthenticationManagerConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner();
@Test
public void userDetailsServiceWhenPasswordEncoderAbsentAndDefaultPassword() throws Exception {
public void userDetailsServiceWhenPasswordEncoderAbsentAndDefaultPassword()
throws Exception {
this.contextRunner.withUserConfiguration(TestSecurityConfiguration.class,
AuthenticationManagerConfiguration.class).run((context -> {
InMemoryUserDetailsManager userDetailsService = context.getBean(InMemoryUserDetailsManager.class);
String password = userDetailsService.loadUserByUsername("user").getPassword();
assertThat(password).startsWith("{noop}");
}));
InMemoryUserDetailsManager userDetailsService = context
.getBean(InMemoryUserDetailsManager.class);
String password = userDetailsService.loadUserByUsername("user")
.getPassword();
assertThat(password).startsWith("{noop}");
}));
}
@Test
public void userDetailsServiceWhenPasswordEncoderAbsentAndRawPassword() throws Exception {
public void userDetailsServiceWhenPasswordEncoderAbsentAndRawPassword()
throws Exception {
testPasswordEncoding(TestSecurityConfiguration.class, "secret", "{noop}secret");
}
@Test
public void userDetailsServiceWhenPasswordEncoderAbsentAndEncodedPassword() throws Exception {
public void userDetailsServiceWhenPasswordEncoderAbsentAndEncodedPassword()
throws Exception {
String password = "{bcrypt}$2a$10$sCBi9fy9814vUPf2ZRbtp.fR5/VgRk2iBFZ.ypu5IyZ28bZgxrVDa";
testPasswordEncoding(TestSecurityConfiguration.class, password, password);
}
@ -65,14 +70,19 @@ public class AuthenticationManagerConfigurationTests {
testPasswordEncoding(TestConfigWithPasswordEncoder.class, "secret", "secret");
}
private void testPasswordEncoding(Class<?> configClass, String providedPassword, String expectedPassword) {
this.contextRunner.withUserConfiguration(configClass,
AuthenticationManagerConfiguration.class)
.withPropertyValues("spring.security.user.password=" + providedPassword).run((context -> {
InMemoryUserDetailsManager userDetailsService = context.getBean(InMemoryUserDetailsManager.class);
String password = userDetailsService.loadUserByUsername("user").getPassword();
assertThat(password).isEqualTo(expectedPassword);
}));
private void testPasswordEncoding(Class<?> configClass, String providedPassword,
String expectedPassword) {
this.contextRunner
.withUserConfiguration(configClass,
AuthenticationManagerConfiguration.class)
.withPropertyValues("spring.security.user.password=" + providedPassword)
.run((context -> {
InMemoryUserDetailsManager userDetailsService = context
.getBean(InMemoryUserDetailsManager.class);
String password = userDetailsService.loadUserByUsername("user")
.getPassword();
assertThat(password).isEqualTo(expectedPassword);
}));
}
@Configuration
@ -92,4 +102,5 @@ public class AuthenticationManagerConfigurationTests {
}
}
}

View File

@ -41,22 +41,29 @@ public class ReactiveAuthenticationManagerConfigurationTests {
private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner();
@Test
public void userDetailsServiceWhenPasswordEncoderAbsentAndDefaultPassword() throws Exception {
this.contextRunner.withUserConfiguration(TestSecurityConfiguration.class,
ReactiveAuthenticationManagerConfiguration.class).run((context -> {
MapReactiveUserDetailsService userDetailsService = context.getBean(MapReactiveUserDetailsService.class);
String password = userDetailsService.findByUsername("user").block().getPassword();
assertThat(password).startsWith("{noop}");
}));
public void userDetailsServiceWhenPasswordEncoderAbsentAndDefaultPassword()
throws Exception {
this.contextRunner
.withUserConfiguration(TestSecurityConfiguration.class,
ReactiveAuthenticationManagerConfiguration.class)
.run((context -> {
MapReactiveUserDetailsService userDetailsService = context
.getBean(MapReactiveUserDetailsService.class);
String password = userDetailsService.findByUsername("user").block()
.getPassword();
assertThat(password).startsWith("{noop}");
}));
}
@Test
public void userDetailsServiceWhenPasswordEncoderAbsentAndRawPassword() throws Exception {
public void userDetailsServiceWhenPasswordEncoderAbsentAndRawPassword()
throws Exception {
testPasswordEncoding(TestSecurityConfiguration.class, "secret", "{noop}secret");
}
@Test
public void userDetailsServiceWhenPasswordEncoderAbsentAndEncodedPassword() throws Exception {
public void userDetailsServiceWhenPasswordEncoderAbsentAndEncodedPassword()
throws Exception {
String password = "{bcrypt}$2a$10$sCBi9fy9814vUPf2ZRbtp.fR5/VgRk2iBFZ.ypu5IyZ28bZgxrVDa";
testPasswordEncoding(TestSecurityConfiguration.class, password, password);
}
@ -66,14 +73,19 @@ public class ReactiveAuthenticationManagerConfigurationTests {
testPasswordEncoding(TestConfigWithPasswordEncoder.class, "secret", "secret");
}
private void testPasswordEncoding(Class<?> configClass, String providedPassword, String expectedPassword) {
this.contextRunner.withUserConfiguration(configClass,
ReactiveAuthenticationManagerConfiguration.class)
.withPropertyValues("spring.security.user.password=" + providedPassword).run((context -> {
MapReactiveUserDetailsService userDetailsService = context.getBean(MapReactiveUserDetailsService.class);
String password = userDetailsService.findByUsername("user").block().getPassword();
assertThat(password).isEqualTo(expectedPassword);
}));
private void testPasswordEncoding(Class<?> configClass, String providedPassword,
String expectedPassword) {
this.contextRunner
.withUserConfiguration(configClass,
ReactiveAuthenticationManagerConfiguration.class)
.withPropertyValues("spring.security.user.password=" + providedPassword)
.run((context -> {
MapReactiveUserDetailsService userDetailsService = context
.getBean(MapReactiveUserDetailsService.class);
String password = userDetailsService.findByUsername("user").block()
.getPassword();
assertThat(password).isEqualTo(expectedPassword);
}));
}
@Configuration

View File

@ -34,17 +34,14 @@ public class WebConversionServiceTests {
@Test
public void customDateFormat() {
WebConversionService conversionService = new WebConversionService("dd*MM*yyyy");
Date date = new DateTime(2018, 1, 1, 20, 30).toDate();
assertThat(conversionService.convert(date, String.class))
.isEqualTo("01*01*2018");
assertThat(conversionService.convert(date, String.class)).isEqualTo("01*01*2018");
LocalDate jodaDate = LocalDate.fromDateFields(date);
assertThat(conversionService.convert(jodaDate, String.class))
.isEqualTo("01*01*2018");
java.time.LocalDate localDate = java.time.LocalDate.of(2018, 1, 1);
assertThat(conversionService.convert(localDate, String.class))
.isEqualTo("01*01*2018");
}
}

View File

@ -69,8 +69,7 @@ import static org.mockito.Mockito.verify;
*/
public class WebFluxAutoConfigurationTests {
private static final MockReactiveWebServerFactory mockReactiveWebServerFactory
= new MockReactiveWebServerFactory();
private static final MockReactiveWebServerFactory mockReactiveWebServerFactory = new MockReactiveWebServerFactory();
private ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class))
@ -80,8 +79,10 @@ public class WebFluxAutoConfigurationTests {
public void shouldNotProcessIfExistingWebReactiveConfiguration() {
this.contextRunner.withUserConfiguration(WebFluxConfigurationSupport.class)
.run(context -> {
assertThat(context).getBeans(RequestMappingHandlerMapping.class).hasSize(1);
assertThat(context).getBeans(RequestMappingHandlerAdapter.class).hasSize(1);
assertThat(context).getBeans(RequestMappingHandlerMapping.class)
.hasSize(1);
assertThat(context).getBeans(RequestMappingHandlerAdapter.class)
.hasSize(1);
});
}
@ -99,28 +100,30 @@ public class WebFluxAutoConfigurationTests {
@SuppressWarnings("unchecked")
@Test
public void shouldRegisterCustomHandlerMethodArgumentResolver() {
this.contextRunner.withUserConfiguration(CustomArgumentResolvers.class).run(context -> {
RequestMappingHandlerAdapter adapter = context
.getBean(RequestMappingHandlerAdapter.class);
List<HandlerMethodArgumentResolver> customResolvers =
(List<HandlerMethodArgumentResolver>) ReflectionTestUtils
.getField(adapter.getArgumentResolverConfigurer(), "customResolvers");
assertThat(customResolvers).contains(
context.getBean("firstResolver",
HandlerMethodArgumentResolver.class),
context.getBean("secondResolver",
HandlerMethodArgumentResolver.class));
});
this.contextRunner.withUserConfiguration(CustomArgumentResolvers.class)
.run(context -> {
RequestMappingHandlerAdapter adapter = context
.getBean(RequestMappingHandlerAdapter.class);
List<HandlerMethodArgumentResolver> customResolvers = (List<HandlerMethodArgumentResolver>) ReflectionTestUtils
.getField(adapter.getArgumentResolverConfigurer(),
"customResolvers");
assertThat(customResolvers).contains(
context.getBean("firstResolver",
HandlerMethodArgumentResolver.class),
context.getBean("secondResolver",
HandlerMethodArgumentResolver.class));
});
}
@Test
public void shouldCustomizeCodecs() {
this.contextRunner.withUserConfiguration(CustomCodecCustomizers.class).run(context -> {
CodecCustomizer codecCustomizer = context.getBean("firstCodecCustomizer",
CodecCustomizer.class);
assertThat(codecCustomizer).isNotNull();
verify(codecCustomizer).customize(any(ServerCodecConfigurer.class));
});
this.contextRunner.withUserConfiguration(CustomCodecCustomizers.class)
.run(context -> {
CodecCustomizer codecCustomizer = context
.getBean("firstCodecCustomizer", CodecCustomizer.class);
assertThat(codecCustomizer).isNotNull();
verify(codecCustomizer).customize(any(ServerCodecConfigurer.class));
});
}
@Test
@ -129,7 +132,8 @@ public class WebFluxAutoConfigurationTests {
SimpleUrlHandlerMapping hm = context.getBean("resourceHandlerMapping",
SimpleUrlHandlerMapping.class);
assertThat(hm.getUrlMap().get("/**")).isInstanceOf(ResourceWebHandler.class);
ResourceWebHandler staticHandler = (ResourceWebHandler) hm.getUrlMap().get("/**");
ResourceWebHandler staticHandler = (ResourceWebHandler) hm.getUrlMap()
.get("/**");
assertThat(staticHandler.getLocations()).hasSize(4);
assertThat(hm.getUrlMap().get("/webjars/**"))
.isInstanceOf(ResourceWebHandler.class);
@ -143,7 +147,8 @@ public class WebFluxAutoConfigurationTests {
@Test
public void shouldMapResourcesToCustomPath() {
this.contextRunner.withPropertyValues("spring.webflux.static-path-pattern:/static/**")
this.contextRunner
.withPropertyValues("spring.webflux.static-path-pattern:/static/**")
.run(context -> {
SimpleUrlHandlerMapping hm = context.getBean("resourceHandlerMapping",
SimpleUrlHandlerMapping.class);
@ -170,11 +175,16 @@ public class WebFluxAutoConfigurationTests {
.run(context -> {
SimpleUrlHandlerMapping hm = context.getBean("resourceHandlerMapping",
SimpleUrlHandlerMapping.class);
assertThat(hm.getUrlMap().get("/**")).isInstanceOf(ResourceWebHandler.class);
ResourceWebHandler staticHandler = (ResourceWebHandler) hm.getUrlMap().get("/**");
assertThat(staticHandler.getResourceResolvers()).extractingResultOf("getClass")
.containsOnly(CachingResourceResolver.class, PathResourceResolver.class);
assertThat(staticHandler.getResourceTransformers()).extractingResultOf("getClass")
assertThat(hm.getUrlMap().get("/**"))
.isInstanceOf(ResourceWebHandler.class);
ResourceWebHandler staticHandler = (ResourceWebHandler) hm.getUrlMap()
.get("/**");
assertThat(staticHandler.getResourceResolvers())
.extractingResultOf("getClass")
.containsOnly(CachingResourceResolver.class,
PathResourceResolver.class);
assertThat(staticHandler.getResourceTransformers())
.extractingResultOf("getClass")
.containsOnly(CachingResourceTransformer.class);
});
}
@ -216,29 +226,35 @@ public class WebFluxAutoConfigurationTests {
@Test
public void validatorWhenNoValidatorShouldUseDefault() {
this.contextRunner
.run(context -> {
assertThat(context).doesNotHaveBean(ValidatorFactory.class);
assertThat(context).doesNotHaveBean(javax.validation.Validator.class);
assertThat(context).getBeanNames(Validator.class).containsExactly("webFluxValidator");
});
this.contextRunner.run(context -> {
assertThat(context).doesNotHaveBean(ValidatorFactory.class);
assertThat(context).doesNotHaveBean(javax.validation.Validator.class);
assertThat(context).getBeanNames(Validator.class)
.containsExactly("webFluxValidator");
});
}
@Test
public void validatorWhenNoCustomizationShouldUseAutoConfigured() {
this.contextRunner.withConfiguration(
AutoConfigurations.of(ValidationAutoConfiguration.class))
this.contextRunner
.withConfiguration(
AutoConfigurations.of(ValidationAutoConfiguration.class))
.run(context -> {
assertThat(context).getBeanNames(javax.validation.Validator.class)
.containsExactly("defaultValidator");
assertThat(context).getBeanNames(Validator.class)
.containsExactlyInAnyOrder("defaultValidator", "webFluxValidator");
Validator validator = context.getBean("webFluxValidator", Validator.class);
.containsExactlyInAnyOrder("defaultValidator",
"webFluxValidator");
Validator validator = context.getBean("webFluxValidator",
Validator.class);
assertThat(validator).isInstanceOf(ValidatorAdapter.class);
Object defaultValidator = context.getBean("defaultValidator");
assertThat(((ValidatorAdapter) validator).getTarget()).isSameAs(defaultValidator);
// Primary Spring validator is the one used by WebFlux behind the scenes
assertThat(context.getBean(Validator.class)).isEqualTo(defaultValidator);
assertThat(((ValidatorAdapter) validator).getTarget())
.isSameAs(defaultValidator);
// Primary Spring validator is the one used by WebFlux behind the
// scenes
assertThat(context.getBean(Validator.class))
.isEqualTo(defaultValidator);
});
}
@ -250,15 +266,14 @@ public class WebFluxAutoConfigurationTests {
assertThat(context).doesNotHaveBean(javax.validation.Validator.class);
assertThat(context).getBeanNames(Validator.class)
.containsOnly("webFluxValidator");
assertThat(context.getBean("webFluxValidator"))
.isSameAs(context.getBean(ValidatorWebFluxConfigurer.class).validator);
assertThat(context.getBean("webFluxValidator")).isSameAs(
context.getBean(ValidatorWebFluxConfigurer.class).validator);
});
}
@Test
public void validatorWithConfigurerDoesNotExposeJsr303() {
this.contextRunner
.withUserConfiguration(ValidatorJsr303WebFluxConfigurer.class)
this.contextRunner.withUserConfiguration(ValidatorJsr303WebFluxConfigurer.class)
.run(context -> {
assertThat(context).doesNotHaveBean(ValidatorFactory.class);
assertThat(context).doesNotHaveBean(javax.validation.Validator.class);
@ -267,24 +282,28 @@ public class WebFluxAutoConfigurationTests {
Validator validator = context.getBean("webFluxValidator",
Validator.class);
assertThat(validator).isInstanceOf(ValidatorAdapter.class);
assertThat(((ValidatorAdapter) validator).getTarget()).isSameAs(
context.getBean(ValidatorJsr303WebFluxConfigurer.class).validator);
assertThat(((ValidatorAdapter) validator).getTarget())
.isSameAs(context.getBean(
ValidatorJsr303WebFluxConfigurer.class).validator);
});
}
@Test
public void validationCustomConfigurerTakesPrecedence() {
this.contextRunner
.withConfiguration(AutoConfigurations.of(ValidationAutoConfiguration.class))
.withUserConfiguration(ValidatorWebFluxConfigurer.class)
.run(context -> {
.withConfiguration(
AutoConfigurations.of(ValidationAutoConfiguration.class))
.withUserConfiguration(ValidatorWebFluxConfigurer.class).run(context -> {
assertThat(context).getBeans(ValidatorFactory.class).hasSize(1);
assertThat(context).getBeans(javax.validation.Validator.class).hasSize(1);
assertThat(context).getBeans(javax.validation.Validator.class)
.hasSize(1);
assertThat(context).getBeanNames(Validator.class)
.containsExactlyInAnyOrder("defaultValidator", "webFluxValidator");
.containsExactlyInAnyOrder("defaultValidator",
"webFluxValidator");
assertThat(context.getBean("webFluxValidator")).isSameAs(
context.getBean(ValidatorWebFluxConfigurer.class).validator);
// Primary Spring validator is the auto-configured one as the WebFlux one has been
// Primary Spring validator is the auto-configured one as the WebFlux
// one has been
// customized via a WebFluxConfigurer
assertThat(context.getBean(Validator.class))
.isEqualTo(context.getBean("defaultValidator"));
@ -294,19 +313,24 @@ public class WebFluxAutoConfigurationTests {
@Test
public void validatorWithCustomSpringValidatorIgnored() {
this.contextRunner
.withConfiguration(AutoConfigurations.of(ValidationAutoConfiguration.class))
.withUserConfiguration(CustomSpringValidator.class)
.run(context -> {
.withConfiguration(
AutoConfigurations.of(ValidationAutoConfiguration.class))
.withUserConfiguration(CustomSpringValidator.class).run(context -> {
assertThat(context).getBeanNames(javax.validation.Validator.class)
.containsExactly("defaultValidator");
assertThat(context).getBeanNames(Validator.class)
.containsExactlyInAnyOrder("customValidator", "defaultValidator", "webFluxValidator");
Validator validator = context.getBean("webFluxValidator", Validator.class);
.containsExactlyInAnyOrder("customValidator",
"defaultValidator", "webFluxValidator");
Validator validator = context.getBean("webFluxValidator",
Validator.class);
assertThat(validator).isInstanceOf(ValidatorAdapter.class);
Object defaultValidator = context.getBean("defaultValidator");
assertThat(((ValidatorAdapter) validator).getTarget()).isSameAs(defaultValidator);
// Primary Spring validator is the one used by WebFlux behind the scenes
assertThat(context.getBean(Validator.class)).isEqualTo(defaultValidator);
assertThat(((ValidatorAdapter) validator).getTarget())
.isSameAs(defaultValidator);
// Primary Spring validator is the one used by WebFlux behind the
// scenes
assertThat(context.getBean(Validator.class))
.isEqualTo(defaultValidator);
});
}
@ -322,8 +346,9 @@ public class WebFluxAutoConfigurationTests {
Validator validator = context.getBean(Validator.class);
assertThat(validator).isInstanceOf(ValidatorAdapter.class);
Validator target = ((ValidatorAdapter) validator).getTarget();
assertThat(new DirectFieldAccessor(target).getPropertyValue("targetValidator"))
.isSameAs(context.getBean("customValidator"));
assertThat(new DirectFieldAccessor(target)
.getPropertyValue("targetValidator"))
.isSameAs(context.getBean("customValidator"));
});
}