Răsfoiți Sursa

Add PasswordEncoder.upgradeEncoding

Issue: gh-2778
Rob Winch 7 ani în urmă
părinte
comite
02b857d82a

+ 5 - 0
config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.java

@@ -289,6 +289,11 @@ public class AuthenticationConfiguration {
 			return getPasswordEncoder().matches(rawPassword, encodedPassword);
 		}
 
+		@Override
+		public boolean upgradeEncoding(String encodedPassword) {
+			return getPasswordEncoder().upgradeEncoding(encodedPassword);
+		}
+
 		private PasswordEncoder getPasswordEncoder() {
 			if (this.passwordEncoder != null) {
 				return this.passwordEncoder;

+ 5 - 0
config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java

@@ -593,6 +593,11 @@ public abstract class WebSecurityConfigurerAdapter implements
 			return getPasswordEncoder().matches(rawPassword, encodedPassword);
 		}
 
+		@Override
+		public boolean upgradeEncoding(String encodedPassword) {
+			return getPasswordEncoder().upgradeEncoding(encodedPassword);
+		}
+
 		private PasswordEncoder getPasswordEncoder() {
 			if (this.passwordEncoder != null) {
 				return this.passwordEncoder;

+ 6 - 0
crypto/src/main/java/org/springframework/security/crypto/password/DelegatingPasswordEncoder.java

@@ -216,6 +216,12 @@ public class DelegatingPasswordEncoder implements PasswordEncoder {
 		return prefixEncodedPassword.substring(start + 1, end);
 	}
 
+	@Override
+	public boolean upgradeEncoding(String encodedPassword) {
+		String id = extractId(encodedPassword);
+		return !this.idForEncode.equalsIgnoreCase(id);
+	}
+
 	private String extractEncodedPassword(String prefixEncodedPassword) {
 		int start = prefixEncodedPassword.indexOf(SUFFIX);
 		return prefixEncodedPassword.substring(start + 1);

+ 10 - 0
crypto/src/main/java/org/springframework/security/crypto/password/PasswordEncoder.java

@@ -42,4 +42,14 @@ public interface PasswordEncoder {
 	 */
 	boolean matches(CharSequence rawPassword, String encodedPassword);
 
+	/**
+	 * Returns true if the encoded password should be encoded again for better security,
+	 * else false. The default implementation always returns false.
+	 * @param encodedPassword the encoded password to check
+	 * @return true if the encoded password should be encoded again for better security,
+	 * else false.
+	 */
+	default boolean upgradeEncoding(String encodedPassword) {
+		return false;
+	}
 }

+ 25 - 0
crypto/src/test/java/org/springframework/security/crypto/password/DelegatingPasswordEncoderTests.java

@@ -198,4 +198,29 @@ public class DelegatingPasswordEncoderTests {
 	public void matchesWhenRawPasswordNotNullAndEncodedPasswordNullThenThrowsIllegalArgumentException() {
 		this.passwordEncoder.matches(this.rawPassword, null);
 	}
+
+	@Test
+	public void upgradeEncodingWhenEncodedPasswordNullThenTrue() {
+		assertThat(this.passwordEncoder.upgradeEncoding(null)).isTrue();
+	}
+
+	@Test
+	public void upgradeEncodingWhenNullIdThenTrue() {
+		assertThat(this.passwordEncoder.upgradeEncoding(this.encodedPassword)).isTrue();
+	}
+
+	@Test
+	public void upgradeEncodingWhenIdInvalidFormatThenTrue() {
+		assertThat(this.passwordEncoder.upgradeEncoding("{bcrypt"+ this.encodedPassword)).isTrue();
+	}
+
+	@Test
+	public void upgradeEncodingWhenSameIdThenFalse() {
+		assertThat(this.passwordEncoder.upgradeEncoding(this.bcryptEncodedPassword)).isFalse();
+	}
+
+	@Test
+	public void upgradeEncodingWhenDifferentIdThenTrue() {
+		assertThat(this.passwordEncoder.upgradeEncoding(this.noopEncodedPassword)).isTrue();
+	}
 }