2
0
Эх сурвалжийг харах

Implement UserDetailsPasswordService in JdbcUserDetailsManager

Signed-off-by: Junhyeok Lee <jhl221123@naver.com>
Junhyeok Lee 3 сар өмнө
parent
commit
0722c2dc41

+ 29 - 1
core/src/main/java/org/springframework/security/provisioning/JdbcUserDetailsManager.java

@@ -46,6 +46,7 @@ import org.springframework.security.core.context.SecurityContextHolderStrategy;
 import org.springframework.security.core.userdetails.User;
 import org.springframework.security.core.userdetails.UserCache;
 import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsPasswordService;
 import org.springframework.security.core.userdetails.cache.NullUserCache;
 import org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl;
 import org.springframework.util.Assert;
@@ -65,7 +66,8 @@ import org.springframework.util.Assert;
  * @author Luke Taylor
  * @since 2.0
  */
-public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsManager, GroupManager {
+public class JdbcUserDetailsManager extends JdbcDaoImpl
+		implements UserDetailsManager, GroupManager, UserDetailsPasswordService {
 
 	public static final String DEF_CREATE_USER_SQL = "insert into users (username, password, enabled) values (?,?,?)";
 
@@ -162,6 +164,8 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
 
 	private RowMapper<GrantedAuthority> grantedAuthorityMapper = this::mapToGrantedAuthority;
 
+	private boolean enableUpdatePassword = false;
+
 	public JdbcUserDetailsManager() {
 	}
 
@@ -591,6 +595,20 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
 		this.userCache = userCache;
 	}
 
+	/**
+	 * Sets whether the {@link #updatePassword(UserDetails, String)} method should
+	 * actually update the password.
+	 * <p>
+	 * Defaults to {@code false} to prevent accidental password updates that might produce
+	 * passwords that are too large for the current database schema. Users must explicitly
+	 * set this to {@code true} to enable password updates.
+	 * @param enableUpdatePassword {@code true} to enable password updates, {@code false}
+	 * otherwise.
+	 */
+	public void setEnableUpdatePassword(boolean enableUpdatePassword) {
+		this.enableUpdatePassword = enableUpdatePassword;
+	}
+
 	private void validateUserDetails(UserDetails user) {
 		Assert.hasText(user.getUsername(), "Username may not be empty or null");
 		validateAuthorities(user.getAuthorities());
@@ -604,4 +622,14 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
 		}
 	}
 
+	@Override
+	public UserDetails updatePassword(UserDetails user, String newPassword) {
+		if (this.enableUpdatePassword) {
+			UserDetails updated = User.withUserDetails(user).password(newPassword).build();
+			updateUser(updated);
+			return updated;
+		}
+		return user;
+	}
+
 }

+ 17 - 0
core/src/test/java/org/springframework/security/provisioning/JdbcUserDetailsManagerTests.java

@@ -410,6 +410,23 @@ public class JdbcUserDetailsManagerTests {
 		verify(mockMapper).mapRow(any(), anyInt());
 	}
 
+	@Test
+	void updatePasswordWhenDisabledReturnOriginalUser() {
+		insertJoe();
+		this.manager.updatePassword(joe, "new");
+		UserDetails newJoe = this.manager.loadUserByUsername("joe");
+		assertThat(newJoe.getPassword()).isEqualTo("password");
+	}
+
+	@Test
+	void updatePasswordWhenEnabledShouldUpdatePassword() {
+		insertJoe();
+		this.manager.setEnableUpdatePassword(true);
+		this.manager.updatePassword(joe, "new");
+		UserDetails newJoe = this.manager.loadUserByUsername("joe");
+		assertThat(newJoe.getPassword()).isEqualTo("new");
+	}
+
 	private Authentication authenticateJoe() {
 		UsernamePasswordAuthenticationToken auth = UsernamePasswordAuthenticationToken.authenticated("joe", "password",
 				joe.getAuthorities());