Browse Source

UserDetailsRepositoryReactiveAuthenticationManager uses DelegatingPasswordEncoder

This means passwords will be encoded with BCrypt by default

Issue: gh-2775
Rob Winch 7 years ago
parent
commit
d19b222b55

+ 10 - 15
config/src/test/java/org/springframework/security/config/annotation/web/reactive/EnableWebFluxSecurityTests.java

@@ -20,12 +20,15 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.ImportResource;
 import org.springframework.core.Ordered;
 import org.springframework.core.annotation.Order;
 import org.springframework.core.io.buffer.DataBuffer;
 import org.springframework.core.io.buffer.DefaultDataBufferFactory;
 import org.springframework.security.authentication.TestingAuthenticationToken;
 import org.springframework.security.config.test.SpringTestRule;
+import org.springframework.security.config.users.ReactiveAuthenticationTestConfiguration;
 import org.springframework.security.config.web.server.ServerHttpSecurity;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
@@ -141,15 +144,8 @@ public class EnableWebFluxSecurityTests {
 	}
 
 	@EnableWebFluxSecurity
+	@Import(ReactiveAuthenticationTestConfiguration.class)
 	static class Config {
-		@Bean
-		public ReactiveUserDetailsService userDetailsRepository() {
-			return new MapReactiveUserDetailsService(User.withUsername("user")
-				.password("password")
-				.roles("USER")
-				.build()
-			);
-		}
 	}
 
 	@Test
@@ -236,22 +232,21 @@ public class EnableWebFluxSecurityTests {
 	}
 
 	@EnableWebFluxSecurity
+	@Import(ReactiveAuthenticationTestConfiguration.class)
 	static class MultiSecurityHttpConfig {
-		@Order(Ordered.HIGHEST_PRECEDENCE) @Bean public SecurityWebFilterChain apiHttpSecurity(
+		@Order(Ordered.HIGHEST_PRECEDENCE)
+		@Bean
+		public SecurityWebFilterChain apiHttpSecurity(
 			ServerHttpSecurity http) {
 			http.securityMatcher(new PathPatternParserServerWebExchangeMatcher("/api/**"))
 				.authorizeExchange().anyExchange().denyAll();
 			return http.build();
 		}
 
-		@Bean public SecurityWebFilterChain httpSecurity(ServerHttpSecurity http) {
+		@Bean
+		public SecurityWebFilterChain httpSecurity(ServerHttpSecurity http) {
 			return http.build();
 		}
-
-		@Bean public ReactiveUserDetailsService userDetailsRepository() {
-			return new MapReactiveUserDetailsService(
-				User.withUsername("user").password("password").roles("USER").build());
-		}
 	}
 
 	private static DataBuffer toDataBuffer(String body) {

+ 6 - 7
config/src/test/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfigurationBuilder.java

@@ -18,25 +18,24 @@ package org.springframework.security.config.annotation.web.reactive;
 
 import org.springframework.security.authentication.ReactiveAuthenticationManager;
 import org.springframework.security.authentication.UserDetailsRepositoryReactiveAuthenticationManager;
+import org.springframework.security.config.users.ReactiveAuthenticationTestConfiguration;
 import org.springframework.security.config.web.server.ServerHttpSecurity;
-import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
-import org.springframework.security.core.userdetails.User;
-import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
 
 /**
  * @author Rob Winch
  * @since 5.0
  */
 public class ServerHttpSecurityConfigurationBuilder {
-	public static final UserDetails USER = User.withUsername("user").password("password").roles("USER").build();
-	public static final UserDetails ADMIN = User.withUsername("admin").password("password").roles("USER","ADMIN").build();
-
 	public static ServerHttpSecurity http() {
 		return new ServerHttpSecurityConfiguration().httpSecurity();
 	}
 
 	public static ServerHttpSecurity httpWithDefaultAuthentication() {
-		ReactiveAuthenticationManager authenticationManager = new UserDetailsRepositoryReactiveAuthenticationManager(new MapReactiveUserDetailsService(USER,ADMIN));
+		ReactiveUserDetailsService reactiveUserDetailsService = ReactiveAuthenticationTestConfiguration
+			.userDetailsRepository();
+		ReactiveAuthenticationManager authenticationManager = new UserDetailsRepositoryReactiveAuthenticationManager(
+			reactiveUserDetailsService);
 		return http()
 			.authenticationManager(authenticationManager);
 	}

+ 37 - 0
config/src/test/java/org/springframework/security/config/users/ReactiveAuthenticationTestConfiguration.java

@@ -0,0 +1,37 @@
+/*
+ * Copyright 2002-2017 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.security.config.users;
+
+import org.junit.Test;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
+import org.springframework.security.core.userdetails.PasswordEncodedUser;
+import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
+import org.springframework.security.core.userdetails.User;
+
+/**
+ * @author Rob Winch
+ * @since 5.0
+ */
+@Configuration
+public class ReactiveAuthenticationTestConfiguration {
+	@Bean
+	public static ReactiveUserDetailsService userDetailsRepository() {
+		return new MapReactiveUserDetailsService(PasswordEncodedUser.user(), PasswordEncodedUser.admin());
+	}
+}

+ 2 - 2
core/src/main/java/org/springframework/security/authentication/UserDetailsRepositoryReactiveAuthenticationManager.java

@@ -19,7 +19,7 @@ package org.springframework.security.authentication;
 import org.springframework.security.core.Authentication;
 
 import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
-import org.springframework.security.crypto.password.NoOpPasswordEncoder;
+import org.springframework.security.crypto.factory.PasswordEncoderFactories;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.util.Assert;
 import reactor.core.publisher.Mono;
@@ -32,7 +32,7 @@ import reactor.core.scheduler.Schedulers;
 public class UserDetailsRepositoryReactiveAuthenticationManager implements ReactiveAuthenticationManager {
 	private final ReactiveUserDetailsService repository;
 
-	private PasswordEncoder passwordEncoder = NoOpPasswordEncoder.getInstance();
+	private PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
 
 	public UserDetailsRepositoryReactiveAuthenticationManager(ReactiveUserDetailsService reactiveUserDetailsService) {
 		Assert.notNull(reactiveUserDetailsService, "userDetailsRepository cannot be null");

+ 11 - 3
core/src/test/java/org/springframework/security/authentication/ReactiveUserDetailsServiceAuthenticationManagerTests.java

@@ -26,9 +26,11 @@ import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.core.userdetails.PasswordEncodedUser;
 import org.springframework.security.core.userdetails.User;
 
 import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
+import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import reactor.core.publisher.Mono;
 import reactor.test.StepVerifier;
@@ -74,10 +76,13 @@ public class ReactiveUserDetailsServiceAuthenticationManagerTests {
 
 	@Test
 	public void authenticateWhenPasswordNotEqualThenBadCredentials() {
-		User user = new User(username, password, AuthorityUtils.createAuthorityList("ROLE_USER"));
+		UserDetails user = PasswordEncodedUser.withUsername(this.username)
+			.password(this.password)
+			.roles("USER")
+			.build();
 		when(repository.findByUsername(user.getUsername())).thenReturn(Mono.just(user));
 
-		UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password + "INVALID");
+		UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, this.password + "INVALID");
 		Mono<Authentication> authentication = manager.authenticate(token);
 
 		StepVerifier
@@ -88,7 +93,10 @@ public class ReactiveUserDetailsServiceAuthenticationManagerTests {
 
 	@Test
 	public void authenticateWhenSuccessThenSuccess() {
-		User user = new User(username, password, AuthorityUtils.createAuthorityList("ROLE_USER"));
+		UserDetails user = PasswordEncodedUser.withUsername(this.username)
+			.password(this.password)
+			.roles("USER")
+			.build();
 		when(repository.findByUsername(user.getUsername())).thenReturn(Mono.just(user));
 
 		UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);

+ 4 - 2
samples/javaconfig/hellowebflux-method/src/main/java/sample/SecurityConfig.java

@@ -23,6 +23,7 @@ import org.springframework.security.config.annotation.web.reactive.EnableWebFlux
 import org.springframework.security.config.web.server.ServerHttpSecurity;
 import org.springframework.security.core.userdetails.User;
 import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.crypto.factory.PasswordEncoderFactories;
 import org.springframework.security.web.server.SecurityWebFilterChain;
 
 /**
@@ -47,8 +48,9 @@ public class SecurityConfig {
 
 	@Bean
 	public MapReactiveUserDetailsService userDetailsRepository() {
-		UserDetails rob = User.withUsername("rob").password("rob").roles("USER").build();
-		UserDetails admin = User.withUsername("admin").password("admin").roles("USER","ADMIN").build();
+		User.UserBuilder userBuilder = User.withDefaultPasswordEncoder();
+		UserDetails rob = userBuilder.username("rob").password("rob").roles("USER").build();
+		UserDetails admin = userBuilder.username("admin").password("admin").roles("USER","ADMIN").build();
 		return new MapReactiveUserDetailsService(rob, admin);
 	}
 

+ 2 - 1
samples/javaconfig/hellowebflux/src/main/java/sample/HelloWebfluxSecurityConfig.java

@@ -31,7 +31,8 @@ public class HelloWebfluxSecurityConfig {
 
 	@Bean
 	public MapReactiveUserDetailsService userDetailsRepository() {
-		UserDetails user = User.withUsername("user")
+		UserDetails user = User.withDefaultPasswordEncoder()
+			.username("user")
 			.password("user")
 			.roles("USER")
 			.build();

+ 2 - 1
samples/javaconfig/hellowebfluxfn/src/main/java/sample/HelloWebfluxFnSecurityConfig.java

@@ -31,7 +31,8 @@ public class HelloWebfluxFnSecurityConfig {
 
 	@Bean
 	public MapReactiveUserDetailsService userDetailsRepository() {
-		UserDetails user = User.withUsername("user")
+		UserDetails user = User.withDefaultPasswordEncoder()
+			.username("user")
 			.password("user")
 			.roles("USER")
 			.build();