This is an automated email from the ASF dual-hosted git repository. jamesfredley pushed a commit to branch fix/auto-exclude-security-autoconfig in repository https://gitbox.apache.org/repos/asf/grails-spring-security.git
commit db38e2c99ac03c5825180c433cb556cd484198c1 Author: James Fredley <[email protected]> AuthorDate: Thu Feb 19 09:41:28 2026 -0500 feat: add opt-out property for auto-configuration exclusion filter Users can now disable the automatic exclusion of Spring Boot security auto-configurations by setting: grails.plugin.springsecurity.excludeSpringSecurityAutoConfiguration: false in application.yml. The filter implements EnvironmentAware so it reads the property during the auto-configuration discovery phase. Defaults to true (exclusions active) for backward compatibility. Assisted-by: Claude Code <[email protected]> --- .../SecurityAutoConfigurationExcluder.groovy | 25 +++++++++- .../SecurityAutoConfigurationExcluderSpec.groovy | 54 ++++++++++++++++++++++ 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/plugin-core/plugin/src/main/groovy/grails/plugin/springsecurity/SecurityAutoConfigurationExcluder.groovy b/plugin-core/plugin/src/main/groovy/grails/plugin/springsecurity/SecurityAutoConfigurationExcluder.groovy index 798b86b31..21b2ce8c1 100644 --- a/plugin-core/plugin/src/main/groovy/grails/plugin/springsecurity/SecurityAutoConfigurationExcluder.groovy +++ b/plugin-core/plugin/src/main/groovy/grails/plugin/springsecurity/SecurityAutoConfigurationExcluder.groovy @@ -21,6 +21,8 @@ package grails.plugin.springsecurity import groovy.transform.CompileStatic import org.springframework.boot.autoconfigure.AutoConfigurationImportFilter import org.springframework.boot.autoconfigure.AutoConfigurationMetadata +import org.springframework.context.EnvironmentAware +import org.springframework.core.env.Environment /** * Automatically excludes Spring Boot security auto-configuration classes that @@ -38,6 +40,16 @@ import org.springframework.boot.autoconfigure.AutoConfigurationMetadata * automatically filtering them out during Spring Boot's auto-configuration * discovery phase.</p> * + * <p>To disable this filter and allow Spring Boot's security auto-configurations + * to run, set the following property in {@code application.yml}:</p> + * + * <pre> + * grails: + * plugin: + * springsecurity: + * excludeSpringSecurityAutoConfiguration: false + * </pre> + * * <p>Registered via {@code META-INF/spring.factories} as an * {@link AutoConfigurationImportFilter}. This runs before auto-configuration * bytecode is loaded, so there is no performance overhead from excluded classes.</p> @@ -46,7 +58,16 @@ import org.springframework.boot.autoconfigure.AutoConfigurationMetadata * @see AutoConfigurationImportFilter */ @CompileStatic -class SecurityAutoConfigurationExcluder implements AutoConfigurationImportFilter { +class SecurityAutoConfigurationExcluder implements AutoConfigurationImportFilter, EnvironmentAware { + + static final String ENABLED_PROPERTY = 'grails.plugin.springsecurity.excludeSpringSecurityAutoConfiguration' + + private boolean enabled = true + + @Override + void setEnvironment(Environment environment) { + this.enabled = environment.getProperty(ENABLED_PROPERTY, Boolean, true) + } /** * Spring Boot security auto-configuration classes that conflict with the @@ -86,7 +107,7 @@ class SecurityAutoConfigurationExcluder implements AutoConfigurationImportFilter boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) { boolean[] matches = new boolean[autoConfigurationClasses.length] for (int i = 0; i < autoConfigurationClasses.length; i++) { - matches[i] = !EXCLUDED_AUTO_CONFIGURATIONS.contains(autoConfigurationClasses[i]) + matches[i] = !enabled || !EXCLUDED_AUTO_CONFIGURATIONS.contains(autoConfigurationClasses[i]) } return matches } diff --git a/plugin-core/plugin/src/test/groovy/grails/plugin/springsecurity/SecurityAutoConfigurationExcluderSpec.groovy b/plugin-core/plugin/src/test/groovy/grails/plugin/springsecurity/SecurityAutoConfigurationExcluderSpec.groovy index 0a848d953..bab018283 100644 --- a/plugin-core/plugin/src/test/groovy/grails/plugin/springsecurity/SecurityAutoConfigurationExcluderSpec.groovy +++ b/plugin-core/plugin/src/test/groovy/grails/plugin/springsecurity/SecurityAutoConfigurationExcluderSpec.groovy @@ -18,6 +18,7 @@ */ package grails.plugin.springsecurity +import org.springframework.core.env.Environment import spock.lang.Specification import spock.lang.Subject import spock.lang.Unroll @@ -147,6 +148,59 @@ class SecurityAutoConfigurationExcluderSpec extends Specification { thrown(UnsupportedOperationException) } + def "match allows all auto-configurations when disabled via environment property"() { + given: + Environment env = Mock(Environment) + env.getProperty(SecurityAutoConfigurationExcluder.ENABLED_PROPERTY, Boolean, true) >> false + excluder.setEnvironment(env) + + and: + String[] autoConfigs = [ + 'org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration', + 'org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration', + 'org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration', + ] as String[] + + when: + boolean[] results = excluder.match(autoConfigs, null) + + then: 'all auto-configurations pass through when filter is disabled' + results[0] + results[1] + results[2] + } + + def "match excludes by default when environment has no property set"() { + given: + Environment env = Mock(Environment) + env.getProperty(SecurityAutoConfigurationExcluder.ENABLED_PROPERTY, Boolean, true) >> true + excluder.setEnvironment(env) + + and: + String[] autoConfigs = [ + 'org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration', + ] as String[] + + when: + boolean[] results = excluder.match(autoConfigs, null) + + then: 'exclusion is active by default' + !results[0] + } + + def "match excludes by default when no environment is set"() { + given: 'excluder without environment (e.g. unit test usage)' + String[] autoConfigs = [ + 'org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration', + ] as String[] + + when: + boolean[] results = excluder.match(autoConfigs, null) + + then: 'exclusion is active by default' + !results[0] + } + def "spring.factories registers the filter correctly"() { when: 'enumerating all spring.factories resources on the classpath' Enumeration<URL> resources = getClass().getClassLoader().getResources('META-INF/spring.factories')
