From 9b2910cd4273ec3e87fc068ae8cf10af8456b82c Mon Sep 17 00:00:00 2001 From: Kyoungwoong Date: Sun, 12 May 2024 14:11:55 +0900 Subject: [PATCH] Add setter method for userDetailsChecker in CasAuthenticationProvider(#10277) This commit introduces a setter method for the userDetailsChecker property in the CasAuthenticationProvider class. Previously, the userDetailsChecker was initialized with a default AccountStatusUserDetailsChecker instance, limiting customization options. Now, users can inject their own UserDetailsChecker implementation through the setter method, providing greater flexibility in handling user details validation. --- .../CasAuthenticationProvider.java | 14 +++++++++- .../CasAuthenticationProviderTests.java | 27 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationProvider.java b/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationProvider.java index 5b390fe19b..0779a509a6 100644 --- a/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationProvider.java +++ b/cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationProvider.java @@ -56,6 +56,7 @@ import org.springframework.util.Assert; * * @author Ben Alex * @author Scott Battaglia + * @author Kim Youngwoong */ public class CasAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware { @@ -63,7 +64,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia private AuthenticationUserDetailsService authenticationUserDetailsService; - private final UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker(); + private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker(); protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); @@ -187,6 +188,17 @@ public class CasAuthenticationProvider implements AuthenticationProvider, Initia this.authenticationUserDetailsService = authenticationUserDetailsService; } + /** + * Sets the UserDetailsChecker to be used for checking the status of retrieved user + * details. This allows customization of the UserDetailsChecker implementation. + * @param userDetailsChecker the UserDetailsChecker to be set + * @since 6.4 + */ + public void setUserDetailsChecker(final UserDetailsChecker userDetailsChecker) { + Assert.notNull(userDetailsChecker, "userDetailsChecker cannot be null"); + this.userDetailsChecker = userDetailsChecker; + } + public void setServiceProperties(final ServiceProperties serviceProperties) { this.serviceProperties = serviceProperties; } diff --git a/cas/src/test/java/org/springframework/security/cas/authentication/CasAuthenticationProviderTests.java b/cas/src/test/java/org/springframework/security/cas/authentication/CasAuthenticationProviderTests.java index f11f191507..0e8b6fe862 100644 --- a/cas/src/test/java/org/springframework/security/cas/authentication/CasAuthenticationProviderTests.java +++ b/cas/src/test/java/org/springframework/security/cas/authentication/CasAuthenticationProviderTests.java @@ -18,6 +18,7 @@ package org.springframework.security.cas.authentication; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; import org.apereo.cas.client.validation.Assertion; import org.apereo.cas.client.validation.AssertionImpl; @@ -31,11 +32,13 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio import org.springframework.security.cas.ServiceProperties; import org.springframework.security.cas.web.authentication.ServiceAuthenticationDetails; import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.AuthenticationUserDetailsService; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsChecker; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.web.authentication.WebAuthenticationDetails; @@ -55,6 +58,7 @@ import static org.mockito.Mockito.verify; * * @author Ben Alex * @author Scott Battaglia + * @author Kim Youngwoong */ @SuppressWarnings("unchecked") public class CasAuthenticationProviderTests { @@ -320,6 +324,29 @@ public class CasAuthenticationProviderTests { assertThat(cap.supports(CasAuthenticationToken.class)).isTrue(); } + @Test + public void testSetUserDetailsChecker() throws AuthenticationException { + CasAuthenticationProvider cap = new CasAuthenticationProvider(); + cap.setAuthenticationUserDetailsService(new MockAuthoritiesPopulator()); + cap.setKey("qwerty"); + cap.setTicketValidator(new MockTicketValidator(true)); + cap.setServiceProperties(makeServiceProperties()); + cap.afterPropertiesSet(); + CasServiceTicketAuthenticationToken token = CasServiceTicketAuthenticationToken.stateful("ST-123"); + + AtomicInteger checkCount = new AtomicInteger(0); + UserDetailsChecker userDetailsChecker = new UserDetailsChecker() { + @Override + public void check(UserDetails user) { + checkCount.incrementAndGet(); + } + }; + cap.setUserDetailsChecker(userDetailsChecker); + cap.authenticate(token); + + assertThat(checkCount.get()).isEqualTo(1); + } + private class MockAuthoritiesPopulator implements AuthenticationUserDetailsService { @Override