diff --git a/config/src/main/java/org/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.java b/config/src/main/java/org/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.java index f89e06ca796..2fd72457c24 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.java +++ b/config/src/main/java/org/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 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. @@ -50,6 +50,7 @@ * @param The object that this builder returns * @param The type of this builder (that is returned by the base class) * @author Rob Winch + * @author DingHao * @see WebSecurity */ public abstract class AbstractConfiguredSecurityBuilder> @@ -386,8 +387,10 @@ private void init() throws Exception { for (SecurityConfigurer configurer : configurers) { configurer.init((B) this); } - for (SecurityConfigurer configurer : this.configurersAddedInInitializing) { - configurer.init((B) this); + while (!this.configurersAddedInInitializing.isEmpty()) { + for (SecurityConfigurer configurer : getConfigurersInInitializing()) { + configurer.init((B) this); + } } } @@ -407,6 +410,12 @@ private Collection> getConfigurers() { return result; } + private List> getConfigurersInInitializing() { + List> result = new ArrayList<>(this.configurersAddedInInitializing); + this.configurersAddedInInitializing.clear(); + return result; + } + /** * Determines if the object is unbuilt. * @return true, if unbuilt else false diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/AbstractConfiguredSecurityBuilderTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/AbstractConfiguredSecurityBuilderTests.java index 322459e33ac..3dc572f2b40 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/AbstractConfiguredSecurityBuilderTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/AbstractConfiguredSecurityBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2025 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. @@ -163,6 +163,34 @@ public void withWhenDuplicateConfigurerAddedThenDuplicateConfigurerRemoved() thr assertThat(this.builder.getConfigurers(TestSecurityConfigurer.class)).hasSize(1); } + @Test + public void withWhenConfigurerAddInitializing() throws Exception { + this.builder.with(new FooConfigurer(), Customizer.withDefaults()); + assertThat(this.builder.build()).isEqualTo("success"); + } + + private static class FooConfigurer extends SecurityConfigurerAdapter { + + @Override + public void init(TestConfiguredSecurityBuilder builder) throws Exception { + builder.with(new BarConfigurer(), Customizer.withDefaults()); + } + + } + + private static class BarConfigurer extends SecurityConfigurerAdapter { + + @Override + public void init(TestConfiguredSecurityBuilder http) throws Exception { + http.with(new CooConfigurer(), Customizer.withDefaults()); + } + + } + + private static class CooConfigurer extends SecurityConfigurerAdapter { + + } + private static class ApplyAndRemoveSecurityConfigurer extends SecurityConfigurerAdapter {