Skip to content

Commit d19b222

Browse files
committed
UserDetailsRepositoryReactiveAuthenticationManager uses DelegatingPasswordEncoder
This means passwords will be encoded with BCrypt by default Issue: gh-2775
1 parent cdc992b commit d19b222

File tree

8 files changed

+74
-31
lines changed

8 files changed

+74
-31
lines changed

config/src/test/java/org/springframework/security/config/annotation/web/reactive/EnableWebFluxSecurityTests.java

+10-15
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,15 @@
2020
import org.junit.Test;
2121
import org.springframework.beans.factory.annotation.Autowired;
2222
import org.springframework.context.annotation.Bean;
23+
import org.springframework.context.annotation.Import;
24+
import org.springframework.context.annotation.ImportResource;
2325
import org.springframework.core.Ordered;
2426
import org.springframework.core.annotation.Order;
2527
import org.springframework.core.io.buffer.DataBuffer;
2628
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
2729
import org.springframework.security.authentication.TestingAuthenticationToken;
2830
import org.springframework.security.config.test.SpringTestRule;
31+
import org.springframework.security.config.users.ReactiveAuthenticationTestConfiguration;
2932
import org.springframework.security.config.web.server.ServerHttpSecurity;
3033
import org.springframework.security.core.Authentication;
3134
import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
@@ -141,15 +144,8 @@ public void defaultPopulatesReactorContextWhenAuthenticating() {
141144
}
142145

143146
@EnableWebFluxSecurity
147+
@Import(ReactiveAuthenticationTestConfiguration.class)
144148
static class Config {
145-
@Bean
146-
public ReactiveUserDetailsService userDetailsRepository() {
147-
return new MapReactiveUserDetailsService(User.withUsername("user")
148-
.password("password")
149-
.roles("USER")
150-
.build()
151-
);
152-
}
153149
}
154150

155151
@Test
@@ -236,22 +232,21 @@ public void multiWorks() {
236232
}
237233

238234
@EnableWebFluxSecurity
235+
@Import(ReactiveAuthenticationTestConfiguration.class)
239236
static class MultiSecurityHttpConfig {
240-
@Order(Ordered.HIGHEST_PRECEDENCE) @Bean public SecurityWebFilterChain apiHttpSecurity(
237+
@Order(Ordered.HIGHEST_PRECEDENCE)
238+
@Bean
239+
public SecurityWebFilterChain apiHttpSecurity(
241240
ServerHttpSecurity http) {
242241
http.securityMatcher(new PathPatternParserServerWebExchangeMatcher("/api/**"))
243242
.authorizeExchange().anyExchange().denyAll();
244243
return http.build();
245244
}
246245

247-
@Bean public SecurityWebFilterChain httpSecurity(ServerHttpSecurity http) {
246+
@Bean
247+
public SecurityWebFilterChain httpSecurity(ServerHttpSecurity http) {
248248
return http.build();
249249
}
250-
251-
@Bean public ReactiveUserDetailsService userDetailsRepository() {
252-
return new MapReactiveUserDetailsService(
253-
User.withUsername("user").password("password").roles("USER").build());
254-
}
255250
}
256251

257252
private static DataBuffer toDataBuffer(String body) {

config/src/test/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfigurationBuilder.java

+6-7
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,24 @@
1818

1919
import org.springframework.security.authentication.ReactiveAuthenticationManager;
2020
import org.springframework.security.authentication.UserDetailsRepositoryReactiveAuthenticationManager;
21+
import org.springframework.security.config.users.ReactiveAuthenticationTestConfiguration;
2122
import org.springframework.security.config.web.server.ServerHttpSecurity;
22-
import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
23-
import org.springframework.security.core.userdetails.User;
24-
import org.springframework.security.core.userdetails.UserDetails;
23+
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
2524

2625
/**
2726
* @author Rob Winch
2827
* @since 5.0
2928
*/
3029
public class ServerHttpSecurityConfigurationBuilder {
31-
public static final UserDetails USER = User.withUsername("user").password("password").roles("USER").build();
32-
public static final UserDetails ADMIN = User.withUsername("admin").password("password").roles("USER","ADMIN").build();
33-
3430
public static ServerHttpSecurity http() {
3531
return new ServerHttpSecurityConfiguration().httpSecurity();
3632
}
3733

3834
public static ServerHttpSecurity httpWithDefaultAuthentication() {
39-
ReactiveAuthenticationManager authenticationManager = new UserDetailsRepositoryReactiveAuthenticationManager(new MapReactiveUserDetailsService(USER,ADMIN));
35+
ReactiveUserDetailsService reactiveUserDetailsService = ReactiveAuthenticationTestConfiguration
36+
.userDetailsRepository();
37+
ReactiveAuthenticationManager authenticationManager = new UserDetailsRepositoryReactiveAuthenticationManager(
38+
reactiveUserDetailsService);
4039
return http()
4140
.authenticationManager(authenticationManager);
4241
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2002-2017 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.config.users;
18+
19+
import org.junit.Test;
20+
import org.springframework.context.annotation.Bean;
21+
import org.springframework.context.annotation.Configuration;
22+
import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
23+
import org.springframework.security.core.userdetails.PasswordEncodedUser;
24+
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
25+
import org.springframework.security.core.userdetails.User;
26+
27+
/**
28+
* @author Rob Winch
29+
* @since 5.0
30+
*/
31+
@Configuration
32+
public class ReactiveAuthenticationTestConfiguration {
33+
@Bean
34+
public static ReactiveUserDetailsService userDetailsRepository() {
35+
return new MapReactiveUserDetailsService(PasswordEncodedUser.user(), PasswordEncodedUser.admin());
36+
}
37+
}

core/src/main/java/org/springframework/security/authentication/UserDetailsRepositoryReactiveAuthenticationManager.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import org.springframework.security.core.Authentication;
2020

2121
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
22-
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
22+
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
2323
import org.springframework.security.crypto.password.PasswordEncoder;
2424
import org.springframework.util.Assert;
2525
import reactor.core.publisher.Mono;
@@ -32,7 +32,7 @@
3232
public class UserDetailsRepositoryReactiveAuthenticationManager implements ReactiveAuthenticationManager {
3333
private final ReactiveUserDetailsService repository;
3434

35-
private PasswordEncoder passwordEncoder = NoOpPasswordEncoder.getInstance();
35+
private PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
3636

3737
public UserDetailsRepositoryReactiveAuthenticationManager(ReactiveUserDetailsService reactiveUserDetailsService) {
3838
Assert.notNull(reactiveUserDetailsService, "userDetailsRepository cannot be null");

core/src/test/java/org/springframework/security/authentication/ReactiveUserDetailsServiceAuthenticationManagerTests.java

+11-3
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@
2626
import org.mockito.junit.MockitoJUnitRunner;
2727
import org.springframework.security.core.Authentication;
2828
import org.springframework.security.core.authority.AuthorityUtils;
29+
import org.springframework.security.core.userdetails.PasswordEncodedUser;
2930
import org.springframework.security.core.userdetails.User;
3031

3132
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
33+
import org.springframework.security.core.userdetails.UserDetails;
3234
import org.springframework.security.crypto.password.PasswordEncoder;
3335
import reactor.core.publisher.Mono;
3436
import reactor.test.StepVerifier;
@@ -74,10 +76,13 @@ public void authenticateWhenUserNotFoundThenBadCredentials() {
7476

7577
@Test
7678
public void authenticateWhenPasswordNotEqualThenBadCredentials() {
77-
User user = new User(username, password, AuthorityUtils.createAuthorityList("ROLE_USER"));
79+
UserDetails user = PasswordEncodedUser.withUsername(this.username)
80+
.password(this.password)
81+
.roles("USER")
82+
.build();
7883
when(repository.findByUsername(user.getUsername())).thenReturn(Mono.just(user));
7984

80-
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password + "INVALID");
85+
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, this.password + "INVALID");
8186
Mono<Authentication> authentication = manager.authenticate(token);
8287

8388
StepVerifier
@@ -88,7 +93,10 @@ public void authenticateWhenPasswordNotEqualThenBadCredentials() {
8893

8994
@Test
9095
public void authenticateWhenSuccessThenSuccess() {
91-
User user = new User(username, password, AuthorityUtils.createAuthorityList("ROLE_USER"));
96+
UserDetails user = PasswordEncodedUser.withUsername(this.username)
97+
.password(this.password)
98+
.roles("USER")
99+
.build();
92100
when(repository.findByUsername(user.getUsername())).thenReturn(Mono.just(user));
93101

94102
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);

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

+4-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.springframework.security.config.web.server.ServerHttpSecurity;
2424
import org.springframework.security.core.userdetails.User;
2525
import org.springframework.security.core.userdetails.UserDetails;
26+
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
2627
import org.springframework.security.web.server.SecurityWebFilterChain;
2728

2829
/**
@@ -47,8 +48,9 @@ SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) throws Exce
4748

4849
@Bean
4950
public MapReactiveUserDetailsService userDetailsRepository() {
50-
UserDetails rob = User.withUsername("rob").password("rob").roles("USER").build();
51-
UserDetails admin = User.withUsername("admin").password("admin").roles("USER","ADMIN").build();
51+
User.UserBuilder userBuilder = User.withDefaultPasswordEncoder();
52+
UserDetails rob = userBuilder.username("rob").password("rob").roles("USER").build();
53+
UserDetails admin = userBuilder.username("admin").password("admin").roles("USER","ADMIN").build();
5254
return new MapReactiveUserDetailsService(rob, admin);
5355
}
5456

samples/javaconfig/hellowebflux/src/main/java/sample/HelloWebfluxSecurityConfig.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ public class HelloWebfluxSecurityConfig {
3131

3232
@Bean
3333
public MapReactiveUserDetailsService userDetailsRepository() {
34-
UserDetails user = User.withUsername("user")
34+
UserDetails user = User.withDefaultPasswordEncoder()
35+
.username("user")
3536
.password("user")
3637
.roles("USER")
3738
.build();

samples/javaconfig/hellowebfluxfn/src/main/java/sample/HelloWebfluxFnSecurityConfig.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ public class HelloWebfluxFnSecurityConfig {
3131

3232
@Bean
3333
public MapReactiveUserDetailsService userDetailsRepository() {
34-
UserDetails user = User.withUsername("user")
34+
UserDetails user = User.withDefaultPasswordEncoder()
35+
.username("user")
3536
.password("user")
3637
.roles("USER")
3738
.build();

0 commit comments

Comments
 (0)