parent
							
								
									4f02770aaa
								
							
						
					
					
						commit
						c3479ddb45
					
				| 
						 | 
					@ -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");
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 * you may not use this file except in compliance with 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.SubjectDnX509PrincipalExtractor;
 | 
				
			||||||
import org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter;
 | 
					import org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter;
 | 
				
			||||||
import org.springframework.security.web.authentication.preauth.x509.X509PrincipalExtractor;
 | 
					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
 | 
					 * 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) {
 | 
								if (this.authenticationDetailsSource != null) {
 | 
				
			||||||
				this.x509AuthenticationFilter.setAuthenticationDetailsSource(this.authenticationDetailsSource);
 | 
									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.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
 | 
				
			||||||
			this.x509AuthenticationFilter = postProcess(this.x509AuthenticationFilter);
 | 
								this.x509AuthenticationFilter = postProcess(this.x509AuthenticationFilter);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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");
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 * you may not use this file except in compliance with 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.SecurityContextChangedListenerConfig;
 | 
				
			||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 | 
					import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 | 
				
			||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 | 
					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.SpringTestContext;
 | 
				
			||||||
import org.springframework.security.config.test.SpringTestContextExtension;
 | 
					import org.springframework.security.config.test.SpringTestContextExtension;
 | 
				
			||||||
import org.springframework.security.core.context.SecurityContextChangedListener;
 | 
					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.security.web.authentication.preauth.x509.X509AuthenticationFilter;
 | 
				
			||||||
import org.springframework.test.web.servlet.MockMvc;
 | 
					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.ArgumentMatchers.any;
 | 
				
			||||||
import static org.mockito.Mockito.atLeastOnce;
 | 
					import static org.mockito.Mockito.atLeastOnce;
 | 
				
			||||||
import static org.mockito.Mockito.mock;
 | 
					import static org.mockito.Mockito.mock;
 | 
				
			||||||
| 
						 | 
					@ -141,6 +143,18 @@ public class X509ConfigurerTests {
 | 
				
			||||||
		// @formatter:on
 | 
							// @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) {
 | 
						private <T extends Certificate> T loadCert(String location) {
 | 
				
			||||||
		try (InputStream is = new ClassPathResource(location).getInputStream()) {
 | 
							try (InputStream is = new ClassPathResource(location).getInputStream()) {
 | 
				
			||||||
			CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
 | 
								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);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue