DelegatingPasswordEncoder copies the provided Map. This ensures that
references to the Map do not update the state of DelegatingPasswordEncoder
and NullPointerException is avoided for implementations that do not allow
a null key.

Issue: gh-4936
This commit is contained in:
Rob Winch 2018-01-03 10:11:04 -06:00
parent 2b66793535
commit 22737dce7e
2 changed files with 6 additions and 13 deletions

View File

@ -16,6 +16,7 @@
package org.springframework.security.crypto.password;
import java.util.HashMap;
import java.util.Map;
/**
@ -155,7 +156,7 @@ public class DelegatingPasswordEncoder implements PasswordEncoder {
}
this.idForEncode = idForEncode;
this.passwordEncoderForEncode = idToPasswordEncoder.get(idForEncode);
this.idToPasswordEncoder = idToPasswordEncoder;
this.idToPasswordEncoder = new HashMap<>(idToPasswordEncoder);
}
/**
@ -191,11 +192,7 @@ public class DelegatingPasswordEncoder implements PasswordEncoder {
return true;
}
String id = extractId(prefixEncodedPassword);
PasswordEncoder delegate = null;
try {
delegate = this.idToPasswordEncoder.get(id);
} catch(NullPointerException e) {
}
PasswordEncoder delegate = this.idToPasswordEncoder.get(id);
if(delegate == null) {
return this.defaultPasswordEncoderForMatches
.matches(rawPassword, prefixEncodedPassword);

View File

@ -23,6 +23,7 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
@ -47,9 +48,6 @@ public class DelegatingPasswordEncoderTests {
@Mock
private PasswordEncoder invalidId;
@Mock
private Map<String, PasswordEncoder> throwingDelegates;
private String bcryptId = "bcrypt";
private String rawPassword = "password";
@ -173,11 +171,9 @@ public class DelegatingPasswordEncoderTests {
@Test
public void matchesWhenIdIsNullThenFalse() {
when(this.throwingDelegates.containsKey(this.bcryptId)).thenReturn(true);
when(this.throwingDelegates.get(this.bcryptId)).thenReturn(this.bcrypt);
when(this.throwingDelegates.get(null)).thenThrow(NullPointerException.class);
this.delegates = new Hashtable<>(this.delegates);
DelegatingPasswordEncoder passwordEncoder = new DelegatingPasswordEncoder(this.bcryptId, throwingDelegates);
DelegatingPasswordEncoder passwordEncoder = new DelegatingPasswordEncoder(this.bcryptId, this.delegates);
assertThatThrownBy(() -> passwordEncoder.matches(this.rawPassword, this.rawPassword))
.isInstanceOf(IllegalArgumentException.class)