Detect UserDetailsService bean in X509 configuration

Closes gh-11174
This commit is contained in:
Eleftheria Stein
2022-04-28 14:47:18 +02:00
parent d40c15e09e
commit 5ac5edc2e6
2 changed files with 111 additions and 4 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2022 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.
@@ -34,10 +34,15 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.test.SpringTestContext;
import org.springframework.security.config.test.SpringTestContextExtension;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter;
import org.springframework.test.web.servlet.MockMvc;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.springframework.security.config.Customizer.withDefaults;
@@ -95,6 +100,26 @@ public class X509ConfigurerTests {
// @formatter:on
}
@Test
public void x509WhenUserDetailsServiceNotConfiguredThenUsesBean() throws Exception {
this.spring.register(UserDetailsServiceBeanConfig.class).autowire();
X509Certificate certificate = loadCert("rod.cer");
// @formatter:off
this.mvc.perform(get("/").with(x509(certificate)))
.andExpect(authenticated().withUsername("rod"));
// @formatter:on
}
@Test
public void x509WhenUserDetailsServiceAndBeanConfiguredThenDoesNotUseBean() throws Exception {
this.spring.register(UserDetailsServiceAndBeanConfig.class).autowire();
X509Certificate certificate = loadCert("rod.cer");
// @formatter:off
this.mvc.perform(get("/").with(x509(certificate)))
.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");
@@ -206,4 +231,59 @@ public class X509ConfigurerTests {
}
@EnableWebSecurity
static class UserDetailsServiceBeanConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// @formatter:off
http
.x509(withDefaults());
// @formatter:on
return http.build();
}
@Bean
UserDetailsService userDetailsService() {
// @formatter:off
return new InMemoryUserDetailsManager(
User.withDefaultPasswordEncoder()
.username("rod")
.password("password")
.roles("USER", "ADMIN")
.build()
);
// @formatter:on
}
}
@EnableWebSecurity
static class UserDetailsServiceAndBeanConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// @formatter:off
UserDetailsService customUserDetailsService = new InMemoryUserDetailsManager(
User.withDefaultPasswordEncoder()
.username("rod")
.password("password")
.roles("USER", "ADMIN")
.build());
http
.x509((x509) -> x509
.userDetailsService(customUserDetailsService)
);
// @formatter:on
return http.build();
}
@Bean
UserDetailsService userDetailsService() {
// @formatter:off
return mock(UserDetailsService.class);
}
}
}