Class DelegatingPasswordEncoder
- java.lang.Object
-
- org.springframework.security.crypto.password.DelegatingPasswordEncoder
-
- All Implemented Interfaces:
PasswordEncoder
public class DelegatingPasswordEncoder extends java.lang.Object implements 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 whichPasswordEncoder
should be used and "encodedPassword" is the original encoded password for the selectedPasswordEncoder
. The "id" must be at the beginning of the password, start with "{" and end with "}". 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
PasswordEncoder
id of "bcrypt" and encodedPassword of "$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG". When matching it would delegate toBCryptPasswordEncoder
- The second password would have a
PasswordEncoder
id of "noop" and encodedPassword of "password". When matching it would delegate toNoOpPasswordEncoder
- The third password would have a
PasswordEncoder
id of "pbkdf2" and encodedPassword of "5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc". When matching it would delegate toPbkdf2PasswordEncoder
- The fourth password would have a
PasswordEncoder
id 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
PasswordEncoder
id of "sha256" and encodedPassword of "97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0". When matching it would delegate toStandardPasswordEncoder
Password Encoding
TheidForEncode
passed into the constructor determines whichPasswordEncoder
will be used for encoding passwords. In theDelegatingPasswordEncoder
we constructed above, that means that the result of encoding "password" would be delegated toBCryptPasswordEncoder
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 invokingmatches(CharSequence, String)
with a password with an "id" that is not mapped (including a null id) will result in anIllegalArgumentException
. This behavior can be customized usingsetDefaultPasswordEncoderForMatches(PasswordEncoder)
.- Since:
- 5.0
- See Also:
PasswordEncoderFactories
-
-
Constructor Summary
Constructors Constructor Description DelegatingPasswordEncoder(java.lang.String idForEncode, java.util.Map<java.lang.String,PasswordEncoder> idToPasswordEncoder)
Creates a new instance
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description java.lang.String
encode(java.lang.CharSequence rawPassword)
Encode the raw password.boolean
matches(java.lang.CharSequence rawPassword, java.lang.String prefixEncodedPassword)
Verify the encoded password obtained from storage matches the submitted raw password after it too is encoded.void
setDefaultPasswordEncoderForMatches(PasswordEncoder defaultPasswordEncoderForMatches)
Sets thePasswordEncoder
to delegate to formatches(CharSequence, String)
if the id is not mapped to aPasswordEncoder
.boolean
upgradeEncoding(java.lang.String prefixEncodedPassword)
Returns true if the encoded password should be encoded again for better security, else false.
-
-
-
Constructor Detail
-
DelegatingPasswordEncoder
public DelegatingPasswordEncoder(java.lang.String idForEncode, java.util.Map<java.lang.String,PasswordEncoder> idToPasswordEncoder)
Creates a new instance- Parameters:
idForEncode
- the id used to lookup whichPasswordEncoder
should be used forencode(CharSequence)
idToPasswordEncoder
- a Map of id toPasswordEncoder
used to determine whichPasswordEncoder
should be used formatches(CharSequence, String)
-
-
Method Detail
-
setDefaultPasswordEncoderForMatches
public void setDefaultPasswordEncoderForMatches(PasswordEncoder defaultPasswordEncoderForMatches)
Sets thePasswordEncoder
to delegate to formatches(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
PasswordEncoder
would be "{notmapped}foobar".- Parameters:
defaultPasswordEncoderForMatches
- the encoder to use. The default is to throw anIllegalArgumentException
-
encode
public java.lang.String encode(java.lang.CharSequence rawPassword)
Description copied from interface:PasswordEncoder
Encode the raw password. Generally, a good encoding algorithm applies a SHA-1 or greater hash combined with an 8-byte or greater randomly generated salt.- Specified by:
encode
in interfacePasswordEncoder
-
matches
public boolean matches(java.lang.CharSequence rawPassword, java.lang.String prefixEncodedPassword)
Description copied from interface:PasswordEncoder
Verify the encoded password obtained from storage matches the submitted raw password after it too is encoded. Returns true if the passwords match, false if they do not. The stored password itself is never decoded.- Specified by:
matches
in interfacePasswordEncoder
- Parameters:
rawPassword
- the raw password to encode and matchprefixEncodedPassword
- the encoded password from storage to compare with- Returns:
- true if the raw password, after encoding, matches the encoded password from storage
-
upgradeEncoding
public boolean upgradeEncoding(java.lang.String prefixEncodedPassword)
Description copied from interface:PasswordEncoder
Returns true if the encoded password should be encoded again for better security, else false. The default implementation always returns false.- Specified by:
upgradeEncoding
in interfacePasswordEncoder
- Parameters:
prefixEncodedPassword
- the encoded password to check- Returns:
- true if the encoded password should be encoded again for better security, else false.
-
-