Просмотр исходного кода

Move FACTOR_X509 into PreAuthenticatedAuthenticationProvider

Issue gh-17933
Josh Cummings 1 неделя назад
Родитель
Сommit
0f4e1f2a2a

+ 3 - 32
config/src/main/java/org/springframework/security/config/annotation/web/configurers/X509Configurer.java

@@ -17,18 +17,15 @@
 package org.springframework.security.config.annotation.web.configurers;
 
 import jakarta.servlet.http.HttpServletRequest;
-import org.jspecify.annotations.Nullable;
 
 import org.springframework.context.ApplicationContext;
 import org.springframework.security.authentication.AuthenticationDetailsSource;
 import org.springframework.security.authentication.AuthenticationManager;
-import org.springframework.security.authentication.AuthenticationProvider;
 import org.springframework.security.config.Customizer;
 import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.core.Authentication;
-import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.authority.AuthorityUtils;
 import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
 import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
 import org.springframework.security.core.userdetails.UserDetailsService;
@@ -182,7 +179,8 @@ public final class X509Configurer<H extends HttpSecurityBuilder<H>>
 	public void init(H http) {
 		PreAuthenticatedAuthenticationProvider authenticationProvider = new PreAuthenticatedAuthenticationProvider();
 		authenticationProvider.setPreAuthenticatedUserDetailsService(getAuthenticationUserDetailsService(http));
-		http.authenticationProvider(new AuthorityGrantingAuthenticationProvider(authenticationProvider))
+		authenticationProvider.setGrantedAuthoritySupplier(() -> AuthorityUtils.createAuthorityList("FACTOR_X509"));
+		http.authenticationProvider(authenticationProvider)
 			.setSharedObject(AuthenticationEntryPoint.class, new Http403ForbiddenEntryPoint());
 		ExceptionHandlingConfigurer<H> exceptions = http.getConfigurer(ExceptionHandlingConfigurer.class);
 		if (exceptions != null) {
@@ -234,31 +232,4 @@ public final class X509Configurer<H extends HttpSecurityBuilder<H>>
 		return context.getBeanProvider(type).getIfUnique();
 	}
 
-	private static final class AuthorityGrantingAuthenticationProvider implements AuthenticationProvider {
-
-		private final AuthenticationProvider delegate;
-
-		private AuthorityGrantingAuthenticationProvider(AuthenticationProvider delegate) {
-			this.delegate = delegate;
-		}
-
-		@Override
-		public @Nullable Authentication authenticate(Authentication authentication) throws AuthenticationException {
-			Authentication result = this.delegate.authenticate(authentication);
-			if (result == null) {
-				return result;
-			}
-			return result
-				.toBuilder()
-				.authorities((a) -> a.add(new SimpleGrantedAuthority("FACTOR_X509")))
-				.build();
-		}
-
-		@Override
-		public boolean supports(Class<?> authentication) {
-			return true;
-		}
-
-	}
-
 }

+ 19 - 1
web/src/main/java/org/springframework/security/web/authentication/preauth/PreAuthenticatedAuthenticationProvider.java

@@ -16,6 +16,11 @@
 
 package org.springframework.security.web.authentication.preauth;
 
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.function.Supplier;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.jspecify.annotations.Nullable;
@@ -28,6 +33,7 @@ import org.springframework.security.authentication.AuthenticationProvider;
 import org.springframework.security.authentication.BadCredentialsException;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
 import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.security.core.userdetails.UserDetailsChecker;
@@ -57,6 +63,8 @@ public class PreAuthenticatedAuthenticationProvider implements AuthenticationPro
 
 	private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker();
 
+	private Supplier<Collection<GrantedAuthority>> grantedAuthoritySupplier = List::of;
+
 	private boolean throwExceptionWhenTokenRejected;
 
 	private int order = -1; // default: same as non-ordered
@@ -98,8 +106,10 @@ public class PreAuthenticatedAuthenticationProvider implements AuthenticationPro
 		UserDetails userDetails = this.preAuthenticatedUserDetailsService
 			.loadUserDetails((PreAuthenticatedAuthenticationToken) authentication);
 		this.userDetailsChecker.check(userDetails);
+		Collection<GrantedAuthority> authorities = new LinkedHashSet<>(userDetails.getAuthorities());
+		authorities.addAll(this.grantedAuthoritySupplier.get());
 		PreAuthenticatedAuthenticationToken result = new PreAuthenticatedAuthenticationToken(userDetails,
-				authentication.getCredentials(), userDetails.getAuthorities());
+				authentication.getCredentials(), authorities);
 		result.setDetails(authentication.getDetails());
 		return result;
 	}
@@ -142,6 +152,14 @@ public class PreAuthenticatedAuthenticationProvider implements AuthenticationPro
 		this.userDetailsChecker = userDetailsChecker;
 	}
 
+	/**
+	 * Sets authorities that this provider should grant once authentication completes
+	 * @param grantedAuthoritySupplier the supplier that grants authorities
+	 */
+	public void setGrantedAuthoritySupplier(Supplier<Collection<GrantedAuthority>> grantedAuthoritySupplier) {
+		this.grantedAuthoritySupplier = grantedAuthoritySupplier;
+	}
+
 	@Override
 	public int getOrder() {
 		return this.order;