Class DelegatingPasswordEncoder
java.lang.Object
org.springframework.security.crypto.password.AbstractValidatingPasswordEncoder
org.springframework.security.crypto.password.DelegatingPasswordEncoder
- All Implemented Interfaces:
PasswordEncoder
A password encoder that delegates to another PasswordEncoder based upon a prefixed
identifier.
Constructing an instance
You can easily construct an instance usingPasswordEncoderFactories.
Alternatively, you may create your own custom instance. For example:
String idForEncode = "bcrypt";
Map<String,PasswordEncoder> encoders = new HashMap<>();
encoders.put(idForEncode, new BCryptPasswordEncoder());
encoders.put("noop", NoOpPasswordEncoder.getInstance());
encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
encoders.put("scrypt", new SCryptPasswordEncoder());
encoders.put("sha256", new StandardPasswordEncoder());
PasswordEncoder passwordEncoder = new DelegatingPasswordEncoder(idForEncode, encoders);
Password Storage Format
The general format for a password is:
{id}encodedPassword
Such that "id" is an identifier used to look up which PasswordEncoder should be
used and "encodedPassword" is the original encoded password for the selected
PasswordEncoder. The "id" must be at the beginning of the password, start with
"{" (id prefix) and end with "}" (id suffix). Both id prefix and id suffix can be
customized via DelegatingPasswordEncoder(String, Map, String, String). If the
"id" cannot be found, the "id" will be null.
For example, the following might be a list of passwords encoded using different "id".
All of the original passwords are "password".
{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
{noop}password
{pbkdf2}5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc
{scrypt}$e0801$8bWJaSu2IKSn9Z9kM+TPXfOc/9bdYSrN1oD9qfVThWEwdRTnO7re7Ei+fUZRJ68k9lTyuTeUp4of4g24hHnazw==$OAOec05+bXxvuu/1qZ6NUR+xQYvYv7BeL1QxwRpY5Pc=
{sha256}97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0
For the DelegatingPasswordEncoder that we constructed above:
- The first password would have a
PasswordEncoderid of "bcrypt" and encodedPassword of "$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG". When matching it would delegate toBCryptPasswordEncoder - The second password would have a
PasswordEncoderid of "noop" and encodedPassword of "password". When matching it would delegate toNoOpPasswordEncoder - The third password would have a
PasswordEncoderid of "pbkdf2" and encodedPassword of "5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc". When matching it would delegate toPbkdf2PasswordEncoder - The fourth password would have a
PasswordEncoderid of "scrypt" and encodedPassword of "$e0801$8bWJaSu2IKSn9Z9kM+TPXfOc/9bdYSrN1oD9qfVThWEwdRTnO7re7Ei+fUZRJ68k9lTyuTeUp4of4g24hHnazw==$OAOec05+bXxvuu/1qZ6NUR+xQYvYv7BeL1QxwRpY5Pc=" When matching it would delegate toSCryptPasswordEncoder - The final password would have a
PasswordEncoderid of "sha256" and encodedPassword of "97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0". When matching it would delegate toStandardPasswordEncoder
Password Encoding
TheidForEncode passed into the constructor determines which
PasswordEncoder will be used for encoding passwords. In the
DelegatingPasswordEncoder we constructed above, that means that the result of
encoding "password" would be delegated to BCryptPasswordEncoder and be prefixed
with "{bcrypt}". The end result would look like:
{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
Password Matching
Matching is done based upon the "id" and the mapping of the "id" to thePasswordEncoder provided in the constructor. Our example in "Password Storage
Format" provides a working example of how this is done.
By default the result of invoking AbstractValidatingPasswordEncoder.matches(CharSequence, String) with a
password with an "id" that is not mapped (including a null id) will result in an
IllegalArgumentException. This behavior can be customized using
setDefaultPasswordEncoderForMatches(PasswordEncoder).- Since:
- 5.0
- See Also:
-
Constructor Summary
ConstructorsConstructorDescriptionDelegatingPasswordEncoder(String idForEncode, Map<String, PasswordEncoder> idToPasswordEncoder) Creates a new instanceDelegatingPasswordEncoder(String idForEncode, Map<String, PasswordEncoder> idToPasswordEncoder, String idPrefix, String idSuffix) Creates a new instance -
Method Summary
Modifier and TypeMethodDescriptionprotected StringencodeNonNullPassword(String rawPassword) protected booleanmatchesNonNull(String rawPassword, String prefixEncodedPassword) voidsetDefaultPasswordEncoderForMatches(PasswordEncoder defaultPasswordEncoderForMatches) Sets thePasswordEncoderto delegate to forAbstractValidatingPasswordEncoder.matches(CharSequence, String)if the id is not mapped to aPasswordEncoder.protected booleanupgradeEncodingNonNull(String prefixEncodedPassword) Methods inherited from class org.springframework.security.crypto.password.AbstractValidatingPasswordEncoder
encode, matches, upgradeEncoding
-
Constructor Details
-
DelegatingPasswordEncoder
public DelegatingPasswordEncoder(String idForEncode, Map<String, PasswordEncoder> idToPasswordEncoder) Creates a new instance- Parameters:
idForEncode- the id used to lookup whichPasswordEncodershould be used forAbstractValidatingPasswordEncoder.encode(CharSequence)idToPasswordEncoder- a Map of id toPasswordEncoderused to determine whichPasswordEncodershould be used forAbstractValidatingPasswordEncoder.matches(CharSequence, String)
-
DelegatingPasswordEncoder
public DelegatingPasswordEncoder(String idForEncode, Map<String, PasswordEncoder> idToPasswordEncoder, String idPrefix, String idSuffix) Creates a new instance- Parameters:
idForEncode- the id used to lookup whichPasswordEncodershould be used forAbstractValidatingPasswordEncoder.encode(CharSequence)idToPasswordEncoder- a Map of id toPasswordEncoderused to determine whichPasswordEncodershould be used foridPrefix- the prefix that denotes the start of the id in the encoded resultsidSuffix- the suffix that denotes the end of an id in the encoded resultsAbstractValidatingPasswordEncoder.matches(CharSequence, String)
-
-
Method Details
-
setDefaultPasswordEncoderForMatches
Sets thePasswordEncoderto delegate to forAbstractValidatingPasswordEncoder.matches(CharSequence, String)if the id is not mapped to aPasswordEncoder.The encodedPassword provided will be the full password passed in including the {"id"} portion.* For example, if the password of "{notmapped}foobar" was used, the "id" would be "notmapped" and the encodedPassword passed into the
PasswordEncoderwould be "{notmapped}foobar".- Parameters:
defaultPasswordEncoderForMatches- the encoder to use. The default is to throw anIllegalArgumentException
-
encodeNonNullPassword
- Specified by:
encodeNonNullPasswordin classAbstractValidatingPasswordEncoder
-
matchesNonNull
- Specified by:
matchesNonNullin classAbstractValidatingPasswordEncoder
-
upgradeEncodingNonNull
- Overrides:
upgradeEncodingNonNullin classAbstractValidatingPasswordEncoder
-