@ -1,5 +1,5 @@
@@ -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;
@@ -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
@@ -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 {
@@ -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 {
@@ -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 ) ;
}
}
}