فهرست منبع

Merge branch '6.0.x'

Closes gh-13063
Josh Cummings 2 سال پیش
والد
کامیت
c79f04cd11

+ 9 - 1
config/src/main/java/org/springframework/security/config/annotation/web/configurers/X509Configurer.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2022 the original author or authors.
+ * Copyright 2002-2023 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@ import org.springframework.security.web.authentication.preauth.PreAuthenticatedG
 import org.springframework.security.web.authentication.preauth.x509.SubjectDnX509PrincipalExtractor;
 import org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter;
 import org.springframework.security.web.authentication.preauth.x509.X509PrincipalExtractor;
+import org.springframework.security.web.context.SecurityContextRepository;
 
 /**
  * Adds X509 based pre authentication to an application. Since validating the certificate
@@ -192,6 +193,13 @@ public final class X509Configurer<H extends HttpSecurityBuilder<H>>
 			if (this.authenticationDetailsSource != null) {
 				this.x509AuthenticationFilter.setAuthenticationDetailsSource(this.authenticationDetailsSource);
 			}
+			SecurityContextConfigurer<?> securityContextConfigurer = http
+					.getConfigurer(SecurityContextConfigurer.class);
+			if (securityContextConfigurer != null && securityContextConfigurer.isRequireExplicitSave()) {
+				SecurityContextRepository securityContextRepository = securityContextConfigurer
+						.getSecurityContextRepository();
+				this.x509AuthenticationFilter.setSecurityContextRepository(securityContextRepository);
+			}
 			this.x509AuthenticationFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
 			this.x509AuthenticationFilter = postProcess(this.x509AuthenticationFilter);
 		}

+ 38 - 1
config/src/test/java/org/springframework/security/config/annotation/web/configurers/X509ConfigurerTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2022 the original author or authors.
+ * Copyright 2002-2023 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -32,6 +32,7 @@ import org.springframework.security.config.annotation.ObjectPostProcessor;
 import org.springframework.security.config.annotation.SecurityContextChangedListenerConfig;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.http.SessionCreationPolicy;
 import org.springframework.security.config.test.SpringTestContext;
 import org.springframework.security.config.test.SpringTestContextExtension;
 import org.springframework.security.core.context.SecurityContextChangedListener;
@@ -45,6 +46,7 @@ import org.springframework.security.web.authentication.preauth.PreAuthenticatedA
 import org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter;
 import org.springframework.test.web.servlet.MockMvc;
 
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.mock;
@@ -141,6 +143,18 @@ public class X509ConfigurerTests {
 		// @formatter:on
 	}
 
+	// gh-13008
+	@Test
+	public void x509WhenStatelessSessionManagementThenDoesNotCreateSession() throws Exception {
+		this.spring.register(StatelessSessionManagementConfig.class).autowire();
+		X509Certificate certificate = loadCert("rodatexampledotcom.cer");
+		// @formatter:off
+		this.mvc.perform(get("/").with(x509(certificate)))
+				.andExpect((result) -> assertThat(result.getRequest().getSession(false)).isNull())
+				.andExpect(authenticated().withUsername("rod"));
+		// @formatter:on
+	}
+
 	private <T extends Certificate> T loadCert(String location) {
 		try (InputStream is = new ClassPathResource(location).getInputStream()) {
 			CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
@@ -311,4 +325,27 @@ public class X509ConfigurerTests {
 
 	}
 
+	@Configuration
+	@EnableWebSecurity
+	static class StatelessSessionManagementConfig {
+
+		@Bean
+		SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
+				.x509((x509) -> x509.subjectPrincipalRegex("CN=(.*?)@example.com(?:,|$)"));
+			// @formatter:on
+			return http.build();
+		}
+
+		@Bean
+		UserDetailsService userDetailsService() {
+			UserDetails user = User.withDefaultPasswordEncoder().username("rod").password("password")
+					.roles("USER", "ADMIN").build();
+			return new InMemoryUserDetailsManager(user);
+		}
+
+	}
+
 }