浏览代码

SEC-1688: Allow injection of a PasswordEncoder from the crypto module into DaoAuthenticationProvider.

Luke Taylor 14 年之前
父节点
当前提交
5a6afbff95

+ 41 - 4
core/src/main/java/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java

@@ -99,12 +99,45 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
 
 
     /**
     /**
      * Sets the PasswordEncoder instance to be used to encode and validate passwords.
      * Sets the PasswordEncoder instance to be used to encode and validate passwords.
-     * If not set, {@link PlaintextPasswordEncoder} will be used by default.
+     * If not set, the password will be compared as plain text.
+     * <p>
+     * For systems which are already using salted password which are encoded with a previous release, the encoder
+     * should be of type {@code org.springframework.security.authentication.encoding.PasswordEncoder}. Otherwise,
+     * the recommended approach is to use {@code org.springframework.security.crypto.password.PasswordEncoder}.
      *
      *
-     * @param passwordEncoder The passwordEncoder to use
+     * @param passwordEncoder must be an instance of one of the {@code PasswordEncoder} types.
      */
      */
-    public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
-        this.passwordEncoder = passwordEncoder;
+    public void setPasswordEncoder(Object passwordEncoder) {
+        Assert.notNull(passwordEncoder, "passwordEncoder cannot be null");
+
+        if (passwordEncoder instanceof PasswordEncoder) {
+            this.passwordEncoder = (PasswordEncoder) passwordEncoder;
+            return;
+        }
+
+        if (passwordEncoder instanceof org.springframework.security.crypto.password.PasswordEncoder) {
+            final org.springframework.security.crypto.password.PasswordEncoder delegate =
+                    (org.springframework.security.crypto.password.PasswordEncoder)passwordEncoder;
+            this.passwordEncoder = new PasswordEncoder() {
+                public String encodePassword(String rawPass, Object salt) {
+                    checkSalt(salt);
+                    return delegate.encode(rawPass);
+                }
+
+                public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
+                    checkSalt(salt);
+                    return delegate.matches(rawPass, encPass);
+                }
+
+                private void checkSalt(Object salt) {
+                    Assert.isNull(salt, "Salt value must be null when used with crypto module PasswordEncoder");
+                }
+            };
+
+            return;
+        }
+
+        throw new IllegalArgumentException("passwordEncoder must be a PasswordEncoder instance");
     }
     }
 
 
     protected PasswordEncoder getPasswordEncoder() {
     protected PasswordEncoder getPasswordEncoder() {
@@ -115,6 +148,10 @@ public class DaoAuthenticationProvider extends AbstractUserDetailsAuthentication
      * The source of salts to use when decoding passwords. <code>null</code>
      * The source of salts to use when decoding passwords. <code>null</code>
      * is a valid value, meaning the <code>DaoAuthenticationProvider</code>
      * is a valid value, meaning the <code>DaoAuthenticationProvider</code>
      * will present <code>null</code> to the relevant <code>PasswordEncoder</code>.
      * will present <code>null</code> to the relevant <code>PasswordEncoder</code>.
+     * <p>
+     * Instead, it is recommended that you use an encoder which uses a random salt and combines it with
+     * the password field. This is the default approach taken in the
+     * {@code org.springframework.security.crypto.password} package.
      *
      *
      * @param saltSource to use when attempting to decode passwords via the <code>PasswordEncoder</code>
      * @param saltSource to use when attempting to decode passwords via the <code>PasswordEncoder</code>
      */
      */