Skip to content

Commit c631afc

Browse files
kse-musicrwinch
authored andcommitted
Avoid unnecessary instantiation of HttpSecurity when a SecurityFilterChain bean is provided
Signed-off-by: DingHao <[email protected]>
1 parent 6cfc372 commit c631afc

File tree

2 files changed

+42
-9
lines changed

2 files changed

+42
-9
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import jakarta.servlet.Filter;
2424

25+
import org.springframework.beans.factory.ObjectProvider;
2526
import org.springframework.beans.factory.annotation.Autowired;
2627
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
2728
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
@@ -74,9 +75,6 @@ public class WebSecurityConfiguration implements ImportAware {
7475

7576
private List<WebSecurityCustomizer> webSecurityCustomizers = Collections.emptyList();
7677

77-
@Autowired(required = false)
78-
private HttpSecurity httpSecurity;
79-
8078
@Bean
8179
public static DelegatingApplicationListener delegatingApplicationListener() {
8280
return new DelegatingApplicationListener();
@@ -94,14 +92,15 @@ public SecurityExpressionHandler<FilterInvocation> webSecurityExpressionHandler(
9492
* @throws Exception
9593
*/
9694
@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
97-
public Filter springSecurityFilterChain() throws Exception {
95+
public Filter springSecurityFilterChain(ObjectProvider<HttpSecurity> provider) throws Exception {
9896
boolean hasFilterChain = !this.securityFilterChains.isEmpty();
9997
if (!hasFilterChain) {
10098
this.webSecurity.addSecurityFilterChainBuilder(() -> {
101-
this.httpSecurity.authorizeHttpRequests((authorize) -> authorize.anyRequest().authenticated());
102-
this.httpSecurity.formLogin(Customizer.withDefaults());
103-
this.httpSecurity.httpBasic(Customizer.withDefaults());
104-
return this.httpSecurity.build();
99+
HttpSecurity httpSecurity = provider.getObject();
100+
httpSecurity.authorizeHttpRequests((authorize) -> authorize.anyRequest().authenticated());
101+
httpSecurity.formLogin(Customizer.withDefaults());
102+
httpSecurity.httpBasic(Customizer.withDefaults());
103+
return httpSecurity.build();
105104
});
106105
}
107106
for (SecurityFilterChain securityFilterChain : this.securityFilterChains) {

config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,8 +27,10 @@
2727
import org.junit.jupiter.api.Test;
2828
import org.junit.jupiter.api.extension.ExtendWith;
2929

30+
import org.springframework.beans.BeansException;
3031
import org.springframework.beans.factory.BeanCreationException;
3132
import org.springframework.beans.factory.annotation.Autowired;
33+
import org.springframework.beans.factory.config.BeanPostProcessor;
3234
import org.springframework.context.annotation.Bean;
3335
import org.springframework.context.annotation.Configuration;
3436
import org.springframework.context.annotation.Import;
@@ -326,6 +328,12 @@ public void loadConfigWhenTwoSecurityFilterChainsPresentAndSecondWithAnyRequestT
326328
.isInstanceOf(IllegalArgumentException.class);
327329
}
328330

331+
@Test
332+
public void avoidUnnecessaryHttpSecurityInstantiationWhenProvideOneSecurityFilterChain() {
333+
this.spring.register(SecurityFilterChainConfig.class).autowire();
334+
assertThat(this.spring.getContext().getBean(CustomBeanPostProcessor.class).instantiationCount).isEqualTo(1);
335+
}
336+
329337
private void assertAnotherUserPermission(WebInvocationPrivilegeEvaluator privilegeEvaluator) {
330338
Authentication anotherUser = new TestingAuthenticationToken("anotherUser", "password", "ROLE_ANOTHER");
331339
assertThat(privilegeEvaluator.isAllowed("/user", anotherUser)).isFalse();
@@ -347,6 +355,32 @@ private void assertUserPermissions(WebInvocationPrivilegeEvaluator privilegeEval
347355
assertThat(privilegeEvaluator.isAllowed("/another", user)).isTrue();
348356
}
349357

358+
@Configuration
359+
@EnableWebSecurity
360+
@Import(CustomBeanPostProcessor.class)
361+
static class SecurityFilterChainConfig {
362+
363+
@Bean
364+
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
365+
return http.authorizeHttpRequests((authorize) -> authorize.anyRequest().authenticated()).build();
366+
}
367+
368+
}
369+
370+
static class CustomBeanPostProcessor implements BeanPostProcessor {
371+
372+
int instantiationCount = 0;
373+
374+
@Override
375+
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
376+
if (bean instanceof HttpSecurity) {
377+
this.instantiationCount++;
378+
}
379+
return bean;
380+
}
381+
382+
}
383+
350384
@Configuration
351385
@EnableWebSecurity
352386
@Import(AuthenticationTestConfiguration.class)

0 commit comments

Comments
 (0)