|
|
|
@ -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); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|