Package org.springframework.security.crypto.password

## 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 using `PasswordEncoderFactories`. 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:

1. 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 to `BCryptPasswordEncoder`
2. The second password would have a `PasswordEncoder` id of "noop" and encodedPassword of "password". When matching it would delegate to `NoOpPasswordEncoder`
3. The third password would have a `PasswordEncoder` id of "pbkdf2" and encodedPassword of "5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc". When matching it would delegate to `Pbkdf2PasswordEncoder`
4. 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 to `SCryptPasswordEncoder`
5. The final password would have a `PasswordEncoder` id of "sha256" and encodedPassword of "97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0". When matching it would delegate to `StandardPasswordEncoder`

## Password Encoding

The `idForEncode` 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 the `PasswordEncoder` 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 `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:
  `PasswordEncoderFactories`

### Field Summary

Fields
`static java.lang.String` `NO_PASSWORD_ENCODER_MAPPED`
`static java.lang.String` `NO_PASSWORD_ENCODER_PREFIX`

### Constructor Summary

Constructors
`DelegatingPasswordEncoder​(java.lang.String idForEncode, java.util.Map<java.lang.String,​PasswordEncoder> idToPasswordEncoder)` Creates a new instance
`DelegatingPasswordEncoder​(java.lang.String idForEncode, java.util.Map<java.lang.String,​PasswordEncoder> idToPasswordEncoder, java.lang.String idPrefix, java.lang.String idSuffix)` Creates a new instance

### Method Summary

All Methods Instance Methods Concrete Methods
`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 the `PasswordEncoder` to delegate to for `matches(CharSequence, String)` if the id is not mapped to a `PasswordEncoder`.
`boolean` `upgradeEncoding​(java.lang.String prefixEncodedPassword)` Returns true if the encoded password should be encoded again for better security, else false.

### Methods inherited from class java.lang.Object

`clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

### Field Detail

#### NO_PASSWORD_ENCODER_MAPPED

    public static final java.lang.String NO_PASSWORD_ENCODER_MAPPED

See Also:
  Constant Field Values

#### NO_PASSWORD_ENCODER_PREFIX

    public static final java.lang.String NO_PASSWORD_ENCODER_PREFIX

See Also:
  Constant Field Values

### 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 which `PasswordEncoder` should be used for `encode(CharSequence)`
  `idToPasswordEncoder` - a Map of id to `PasswordEncoder` used to determine which `PasswordEncoder` should be used for `matches(CharSequence, String)`

#### DelegatingPasswordEncoder

    public DelegatingPasswordEncoder​(java.lang.String idForEncode,
                                     java.util.Map<java.lang.String,​PasswordEncoder> idToPasswordEncoder,
                                     java.lang.String idPrefix,
                                     java.lang.String idSuffix)

Creates a new instance

Parameters:
  `idForEncode` - the id used to lookup which `PasswordEncoder` should be used for `encode(CharSequence)`
  `idToPasswordEncoder` - a Map of id to `PasswordEncoder` used to determine which `PasswordEncoder` should be used for
  `idPrefix` - the prefix that denotes the start of the id in the encoded results
  `idSuffix` - the suffix that denotes the end of an id in the encoded results `matches(CharSequence, String)`

### Method Detail

#### setDefaultPasswordEncoderForMatches

    public void setDefaultPasswordEncoderForMatches​(PasswordEncoder defaultPasswordEncoderForMatches)

Sets the `PasswordEncoder` to delegate to for `matches(CharSequence, String)` if the id is not mapped to a `PasswordEncoder`.

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 an `IllegalArgumentException`

#### 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 interface `PasswordEncoder`

#### 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 interface `PasswordEncoder`
Parameters:
  `rawPassword` - the raw password to encode and match
  `prefixEncodedPassword` - 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 interface `PasswordEncoder`
Parameters:
  `prefixEncodedPassword` - the encoded password to check
Returns:
  true if the encoded password should be encoded again for better security, else false.