From a2f2e9ac8db43226376538fbbb18c5927e224b36 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Sun, 26 Jul 2020 13:35:03 -0700 Subject: [PATCH] Move inner-types so that they are always last Move all inner-types so that they are consistently the last item defined. This aligns with the style used by Spring Framework and the consistency generally makes it easier to scan the source. Issue gh-8945 --- .../acls/jdbc/JdbcMutableAclServiceTests.java | 16 +- ...onProviderBuilderSecurityBuilderTests.java | 152 +- .../LdapAuthenticationProviderConfigurer.java | 30 +- .../annotation/rsocket/RSocketSecurity.java | 250 +- .../annotation/web/builders/HttpSecurity.java | 36 +- .../annotation/web/builders/WebSecurity.java | 60 +- .../WebSecurityConfiguration.java | 58 +- .../AbstractInterceptUrlConfigurer.java | 76 +- .../ExpressionUrlAuthorizationConfigurer.java | 110 +- .../web/configurers/HeadersConfigurer.java | 702 ++--- .../SessionManagementConfigurer.java | 276 +- .../UrlAuthorizationConfigurer.java | 84 +- .../oauth2/client/OAuth2ClientConfigurer.java | 20 +- .../oauth2/client/OAuth2LoginConfigurer.java | 422 +-- .../OAuth2ResourceServerConfigurer.java | 128 +- ...MessageSecurityMetadataSourceRegistry.java | 46 +- ...urityWebSocketMessageBrokerConfigurer.java | 38 +- .../config/web/server/ServerHttpSecurity.java | 2312 ++++++++--------- .../AuthenticationManagerBuilderTests.java | 104 +- .../NamespaceAuthenticationManagerTests.java | 42 +- .../NamespaceAuthenticationProviderTests.java | 16 +- .../NamespaceJdbcUserServiceTests.java | 14 +- .../NamespacePasswordEncoderTests.java | 28 +- .../PasswordEncoderConfigurerTests.java | 14 +- .../AuthenticationConfigurationTests.java | 393 ++- .../EnableGlobalAuthenticationTests.java | 40 +- ...reBeanFactoryObjectPostProcessorTests.java | 38 +- ...lobalMethodSecurityConfigurationTests.java | 431 ++- .../NamespaceGlobalMethodSecurityTests.java | 420 ++- ...ctiveMethodSecurityConfigurationTests.java | 22 +- ...SampleEnableGlobalMethodSecurityTests.java | 20 +- .../annotation/sec2758/Sec2758Tests.java | 24 +- ...RequestMatcherRegistryAnyMatcherTests.java | 66 +- ...mpleWebSecurityConfigurerAdapterTests.java | 200 +- ...curityConfigurerAdapterPowermockTests.java | 42 +- .../WebSecurityConfigurerAdapterTests.java | 258 +- .../web/builders/HttpConfigurationTests.java | 44 +- .../web/builders/NamespaceHttpTests.java | 412 +-- .../web/builders/WebSecurityTests.java | 88 +- .../configuration/EnableWebSecurityTests.java | 84 +- .../HttpSecurityConfigurationTests.java | 60 +- .../OAuth2ClientConfigurationTests.java | 166 +- .../web/configuration/Sec2515Tests.java | 55 +- .../WebSecurityConfigurationTests.java | 372 +-- .../configurers/AnonymousConfigurerTests.java | 42 +- .../configurers/AuthorizeRequestsTests.java | 642 ++--- .../ChannelSecurityConfigurerTests.java | 28 +- .../web/configurers/CorsConfigurerTests.java | 236 +- ...onfigurerIgnoringRequestMatchersTests.java | 68 +- .../CsrfConfigurerNoWebMvcTests.java | 14 +- .../web/configurers/CsrfConfigurerTests.java | 482 ++-- .../web/configurers/DefaultFiltersTests.java | 108 +- .../DefaultLoginPageConfigurerTests.java | 292 +-- ...ingConfigurerAccessDeniedHandlerTests.java | 40 +- .../ExceptionHandlingConfigurerTests.java | 130 +- ...essionUrlAuthorizationConfigurerTests.java | 742 +++--- .../configurers/FormLoginConfigurerTests.java | 384 +-- .../HeadersConfigurerEagerHeadersTests.java | 24 +- .../configurers/HeadersConfigurerTests.java | 816 +++--- .../configurers/HttpBasicConfigurerTests.java | 92 +- .../HttpSecurityAntMatchersTests.java | 38 +- .../configurers/HttpSecurityLogoutTests.java | 16 +- .../HttpSecurityRequestMatchersTests.java | 226 +- .../web/configurers/Issue55Tests.java | 60 +- .../web/configurers/JeeConfigurerTests.java | 114 +- .../configurers/LogoutConfigurerTests.java | 410 +-- .../web/configurers/NamespaceDebugTests.java | 20 +- .../NamespaceHttpAnonymousTests.java | 48 +- .../configurers/NamespaceHttpBasicTests.java | 168 +- .../NamespaceHttpCustomFilterTests.java | 62 +- .../NamespaceHttpExpressionHandlerTests.java | 8 +- .../NamespaceHttpFirewallTests.java | 24 +- .../NamespaceHttpFormLoginTests.java | 60 +- .../NamespaceHttpHeadersTests.java | 327 ++- .../NamespaceHttpInterceptUrlTests.java | 8 +- .../configurers/NamespaceHttpJeeTests.java | 50 +- .../configurers/NamespaceHttpLogoutTests.java | 134 +- .../NamespaceHttpOpenIDLoginTests.java | 106 +- .../NamespaceHttpRequestCacheTests.java | 30 +- ...aceHttpServerAccessDeniedHandlerTests.java | 68 +- .../configurers/NamespaceHttpX509Tests.java | 104 +- .../configurers/NamespaceRememberMeTests.java | 309 ++- .../NamespaceSessionManagementTests.java | 196 +- .../configurers/PermitAllSupportTests.java | 14 +- .../PortMapperConfigurerTests.java | 28 +- .../RememberMeConfigurerTests.java | 292 +-- .../RequestCacheConfigurerTests.java | 190 +- .../RequestMatcherConfigurerTests.java | 16 +- .../SecurityContextConfigurerTests.java | 90 +- .../ServletApiConfigurerTests.java | 242 +- ...ionManagementConfigurerServlet31Tests.java | 36 +- ...tConfigurerSessionCreationPolicyTests.java | 40 +- .../SessionManagementConfigurerTests.java | 432 +-- .../UrlAuthorizationConfigurerTests.java | 98 +- .../configurers/UrlAuthorizationsTests.java | 38 +- .../web/configurers/X509ConfigurerTests.java | 68 +- .../client/OAuth2LoginConfigurerTests.java | 62 +- .../OAuth2ResourceServerConfigurerTests.java | 168 +- .../openid/OpenIDLoginConfigurerTests.java | 214 +- .../saml2/Saml2LoginConfigurerTests.java | 76 +- .../reactive/EnableWebFluxSecurityTests.java | 162 +- ...WebSocketMessageBrokerConfigurerTests.java | 326 +-- .../security/config/http/CsrfConfigTests.java | 42 +- .../config/http/FormLoginConfigTests.java | 36 +- .../security/config/http/HttpConfigTests.java | 8 +- .../config/http/HttpCorsConfigTests.java | 46 +- .../config/http/HttpHeadersConfigTests.java | 20 +- .../config/http/InterceptUrlConfigTests.java | 28 +- .../config/http/MiscHttpConfigTests.java | 106 +- .../http/MultiHttpBlockConfigTests.java | 8 +- ...OAuth2ClientBeanDefinitionParserTests.java | 22 +- .../OAuth2LoginBeanDefinitionParserTests.java | 8 +- ...sourceServerBeanDefinitionParserTests.java | 152 +- .../config/http/OpenIDConfigTests.java | 20 +- .../http/PlaceHolderAndELConfigTests.java | 8 +- .../config/http/RememberMeConfigTests.java | 20 +- ...yContextHolderAwareRequestConfigTests.java | 8 +- .../http/SessionManagementConfigTests.java | 166 +- ...entConfigTransientAuthenticationTests.java | 8 +- ...thodSecurityBeanDefinitionParserTests.java | 16 +- .../config/web/server/FormLoginTests.java | 12 +- .../web/server/OAuth2ClientSpecTests.java | 152 +- .../config/web/server/OAuth2LoginTests.java | 342 +-- .../server/OAuth2ResourceServerSpecTests.java | 96 +- ...bTestClientHtmlUnitDriverBuilderTests.java | 28 +- .../security/core/userdetails/User.java | 46 +- .../dao/DaoAuthenticationProviderTests.java | 12 +- etc/checkstyle/checkstyle-suppressions.xml | 1 - .../server/UnboundIdContainerLdifTests.java | 80 +- ...icationPrincipalArgumentResolverTests.java | 12 +- .../handler/invocation/ResolvableMethod.java | 92 +- ...OAuth2AuthorizedClientProviderBuilder.java | 342 +-- ...OAuth2AuthorizedClientProviderBuilder.java | 250 +- ...ientOAuth2AuthorizationFailureHandler.java | 46 +- ...tiveOAuth2AuthorizationFailureHandler.java | 52 +- .../registration/ClientRegistration.java | 44 +- .../registration/ClientRegistrations.java | 14 +- ...uthorizedClientExchangeFilterFunction.java | 14 +- ...uthorizedClientExchangeFilterFunction.java | 14 +- .../oauth2/jwt/NimbusReactiveJwtDecoder.java | 26 +- .../OpenSamlAuthenticationProvider.java | 32 +- .../RelyingPartyRegistration.java | 90 +- .../ReactorContextTestExecutionListener.java | 16 +- .../showcase/WithUserDetailsTests.java | 8 +- ...ctorContextTestExecutionListenerTests.java | 40 +- .../support/WithAnonymousUserTests.java | 20 +- .../context/support/WithMockUserTests.java | 20 +- .../context/support/WithUserDetailsTests.java | 20 +- ...MockMvcRequestPostProcessorsCsrfTests.java | 8 +- .../HttpSessionSecurityContextRepository.java | 30 +- .../writers/ClearSiteDataHeaderWriter.java | 28 +- .../authentication/SwitchUserWebFilter.java | 16 +- ...geDelegatingServerAccessDeniedHandler.java | 10 +- .../web/reactive/server/WebTestHandler.java | 8 +- .../expression/WebExpressionVoterTests.java | 16 +- ...DefaultLoginPageGeneratingFilterTests.java | 39 +- ...icationPrincipalArgumentResolverTests.java | 12 +- ...ecurityWebApplicationInitializerTests.java | 10 +- .../security/web/method/ResolvableMethod.java | 92 +- ...icationPrincipalArgumentResolverTests.java | 12 +- ...tSecurityContextArgumentResolverTests.java | 34 +- ...tSecurityContextArgumentResolverTests.java | 8 +- .../web/util/ThrowableAnalyzerTests.java | 66 +- 163 files changed, 10287 insertions(+), 10332 deletions(-) diff --git a/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTests.java b/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTests.java index dd227be3c0..61f8388499 100644 --- a/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTests.java +++ b/acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTests.java @@ -544,6 +544,14 @@ public class JdbcMutableAclServiceTests extends AbstractTransactionalJUnit4Sprin assertThat(new Long(1L)).isEqualTo(result); } + protected Authentication getAuth() { + return this.auth; + } + + protected JdbcMutableAclService getJdbcMutableAclService() { + return this.jdbcMutableAclService; + } + /** * This class needed to show how to extend {@link JdbcMutableAclService} for * processing custom {@link Sid} implementations @@ -573,12 +581,4 @@ public class JdbcMutableAclServiceTests extends AbstractTransactionalJUnit4Sprin } - protected Authentication getAuth() { - return this.auth; - } - - protected JdbcMutableAclService getJdbcMutableAclService() { - return this.jdbcMutableAclService; - } - } diff --git a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderBuilderSecurityBuilderTests.java b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderBuilderSecurityBuilderTests.java index 0eefa06350..2e0ab5882d 100644 --- a/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderBuilderSecurityBuilderTests.java +++ b/config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderBuilderSecurityBuilderTests.java @@ -53,6 +53,8 @@ import static org.springframework.security.test.web.servlet.response.SecurityMoc public class LdapAuthenticationProviderBuilderSecurityBuilderTests { + static Integer port; + @Rule public final SpringTestRule spring = new SpringTestRule(); @@ -76,6 +78,80 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { assertThat(ReflectionTestUtils.getField(getAuthoritiesMapper(provider), "prefix")).isEqualTo("ROLE_"); } + @Test + public void groupRolesCustom() { + this.spring.register(GroupRolesConfig.class).autowire(); + LdapAuthenticationProvider provider = ldapProvider(); + + assertThat(ReflectionTestUtils.getField(getAuthoritiesPopulator(provider), "groupRoleAttribute")) + .isEqualTo("group"); + } + + @Test + public void groupSearchCustom() { + this.spring.register(GroupSearchConfig.class).autowire(); + LdapAuthenticationProvider provider = ldapProvider(); + + assertThat(ReflectionTestUtils.getField(getAuthoritiesPopulator(provider), "groupSearchFilter")) + .isEqualTo("ou=groupName"); + } + + @Test + public void groupSubtreeSearchCustom() { + this.spring.register(GroupSubtreeSearchConfig.class).autowire(); + LdapAuthenticationProvider provider = ldapProvider(); + + assertThat(ReflectionTestUtils.getField(getAuthoritiesPopulator(provider), "searchControls")) + .extracting("searchScope").isEqualTo(SearchControls.SUBTREE_SCOPE); + } + + @Test + public void rolePrefixCustom() { + this.spring.register(RolePrefixConfig.class).autowire(); + LdapAuthenticationProvider provider = ldapProvider(); + + assertThat(ReflectionTestUtils.getField(getAuthoritiesMapper(provider), "prefix")).isEqualTo("role_"); + } + + @Test + public void bindAuthentication() throws Exception { + this.spring.register(BindAuthenticationConfig.class).autowire(); + + this.mockMvc.perform(formLogin().user("bob").password("bobspassword")).andExpect(authenticated() + .withUsername("bob").withAuthorities(singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS")))); + } + + // SEC-2472 + @Test + public void canUseCryptoPasswordEncoder() throws Exception { + this.spring.register(PasswordEncoderConfig.class).autowire(); + + this.mockMvc.perform(formLogin().user("bcrypt").password("password")).andExpect(authenticated() + .withUsername("bcrypt").withAuthorities(singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS")))); + } + + private LdapAuthenticationProvider ldapProvider() { + return ((List) ReflectionTestUtils.getField(this.authenticationManager, + "providers")).get(0); + } + + private LdapAuthoritiesPopulator getAuthoritiesPopulator(LdapAuthenticationProvider provider) { + return (LdapAuthoritiesPopulator) ReflectionTestUtils.getField(provider, "authoritiesPopulator"); + } + + private GrantedAuthoritiesMapper getAuthoritiesMapper(LdapAuthenticationProvider provider) { + return (GrantedAuthoritiesMapper) ReflectionTestUtils.getField(provider, "authoritiesMapper"); + } + + static int getPort() throws IOException { + if (port == null) { + ServerSocket socket = new ServerSocket(0); + port = socket.getLocalPort(); + socket.close(); + } + return port; + } + @EnableWebSecurity static class DefaultLdapConfig extends BaseLdapProviderConfig { @@ -91,15 +167,6 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { } - @Test - public void groupRolesCustom() { - this.spring.register(GroupRolesConfig.class).autowire(); - LdapAuthenticationProvider provider = ldapProvider(); - - assertThat(ReflectionTestUtils.getField(getAuthoritiesPopulator(provider), "groupRoleAttribute")) - .isEqualTo("group"); - } - @EnableWebSecurity static class GroupRolesConfig extends BaseLdapProviderConfig { @@ -116,15 +183,6 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { } - @Test - public void groupSearchCustom() { - this.spring.register(GroupSearchConfig.class).autowire(); - LdapAuthenticationProvider provider = ldapProvider(); - - assertThat(ReflectionTestUtils.getField(getAuthoritiesPopulator(provider), "groupSearchFilter")) - .isEqualTo("ou=groupName"); - } - @EnableWebSecurity static class GroupSearchConfig extends BaseLdapProviderConfig { @@ -141,15 +199,6 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { } - @Test - public void groupSubtreeSearchCustom() { - this.spring.register(GroupSubtreeSearchConfig.class).autowire(); - LdapAuthenticationProvider provider = ldapProvider(); - - assertThat(ReflectionTestUtils.getField(getAuthoritiesPopulator(provider), "searchControls")) - .extracting("searchScope").isEqualTo(SearchControls.SUBTREE_SCOPE); - } - @EnableWebSecurity static class GroupSubtreeSearchConfig extends BaseLdapProviderConfig { @@ -167,14 +216,6 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { } - @Test - public void rolePrefixCustom() { - this.spring.register(RolePrefixConfig.class).autowire(); - LdapAuthenticationProvider provider = ldapProvider(); - - assertThat(ReflectionTestUtils.getField(getAuthoritiesMapper(provider), "prefix")).isEqualTo("role_"); - } - @EnableWebSecurity static class RolePrefixConfig extends BaseLdapProviderConfig { @@ -191,14 +232,6 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { } - @Test - public void bindAuthentication() throws Exception { - this.spring.register(BindAuthenticationConfig.class).autowire(); - - this.mockMvc.perform(formLogin().user("bob").password("bobspassword")).andExpect(authenticated() - .withUsername("bob").withAuthorities(singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS")))); - } - @EnableWebSecurity static class BindAuthenticationConfig extends BaseLdapServerConfig { @@ -216,15 +249,6 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { } - // SEC-2472 - @Test - public void canUseCryptoPasswordEncoder() throws Exception { - this.spring.register(PasswordEncoderConfig.class).autowire(); - - this.mockMvc.perform(formLogin().user("bcrypt").password("password")).andExpect(authenticated() - .withUsername("bcrypt").withAuthorities(singleton(new SimpleGrantedAuthority("ROLE_DEVELOPERS")))); - } - @EnableWebSecurity static class PasswordEncoderConfig extends BaseLdapServerConfig { @@ -243,19 +267,6 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { } - private LdapAuthenticationProvider ldapProvider() { - return ((List) ReflectionTestUtils.getField(this.authenticationManager, - "providers")).get(0); - } - - private LdapAuthoritiesPopulator getAuthoritiesPopulator(LdapAuthenticationProvider provider) { - return (LdapAuthoritiesPopulator) ReflectionTestUtils.getField(provider, "authoritiesPopulator"); - } - - private GrantedAuthoritiesMapper getAuthoritiesMapper(LdapAuthenticationProvider provider) { - return (GrantedAuthoritiesMapper) ReflectionTestUtils.getField(provider, "authoritiesMapper"); - } - @EnableWebSecurity static abstract class BaseLdapServerConfig extends BaseLdapProviderConfig { @@ -295,15 +306,4 @@ public class LdapAuthenticationProviderBuilderSecurityBuilderTests { } - static Integer port; - - static int getPort() throws IOException { - if (port == null) { - ServerSocket socket = new ServerSocket(0); - port = socket.getLocalPort(); - socket.close(); - } - return port; - } - } diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java index 60196d9fc7..0db78b0c52 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java @@ -379,6 +379,21 @@ public class LdapAuthenticationProviderConfigurer jwt) { if (this.jwtSpec == null) { this.jwtSpec = new JwtSpec(); @@ -244,45 +184,6 @@ public class RSocketSecurity { return this; } - public final class JwtSpec { - - private ReactiveAuthenticationManager authenticationManager; - - public JwtSpec authenticationManager(ReactiveAuthenticationManager authenticationManager) { - this.authenticationManager = authenticationManager; - return this; - } - - private ReactiveAuthenticationManager getAuthenticationManager() { - if (this.authenticationManager != null) { - return this.authenticationManager; - } - ReactiveJwtDecoder jwtDecoder = getBeanOrNull(ReactiveJwtDecoder.class); - if (jwtDecoder != null) { - this.authenticationManager = new JwtReactiveAuthenticationManager(jwtDecoder); - return this.authenticationManager; - } - return RSocketSecurity.this.authenticationManager; - } - - protected List build() { - ReactiveAuthenticationManager manager = getAuthenticationManager(); - AuthenticationPayloadInterceptor legacy = new AuthenticationPayloadInterceptor(manager); - legacy.setAuthenticationConverter(new BearerPayloadExchangeConverter()); - legacy.setOrder(PayloadInterceptorOrder.AUTHENTICATION.getOrder()); - - AuthenticationPayloadInterceptor standard = new AuthenticationPayloadInterceptor(manager); - standard.setAuthenticationConverter(new AuthenticationPayloadExchangeConverter()); - standard.setOrder(PayloadInterceptorOrder.AUTHENTICATION.getOrder()); - - return Arrays.asList(standard, legacy); - } - - private JwtSpec() { - } - - } - public RSocketSecurity authorizePayload(Customizer authorize) { if (this.authorizePayload == null) { this.authorizePayload = new AuthorizePayloadsSpec(); @@ -326,6 +227,131 @@ public class RSocketSecurity { return result; } + private T getBean(Class beanClass) { + if (this.context == null) { + return null; + } + return this.context.getBean(beanClass); + } + + private T getBeanOrNull(Class beanClass) { + return getBeanOrNull(ResolvableType.forClass(beanClass)); + } + + private T getBeanOrNull(ResolvableType type) { + if (this.context == null) { + return null; + } + String[] names = this.context.getBeanNamesForType(type); + if (names.length == 1) { + return (T) this.context.getBean(names[0]); + } + return null; + } + + protected void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.context = applicationContext; + } + + /** + * @since 5.3 + */ + public final class SimpleAuthenticationSpec { + + private ReactiveAuthenticationManager authenticationManager; + + public SimpleAuthenticationSpec authenticationManager(ReactiveAuthenticationManager authenticationManager) { + this.authenticationManager = authenticationManager; + return this; + } + + private ReactiveAuthenticationManager getAuthenticationManager() { + if (this.authenticationManager == null) { + return RSocketSecurity.this.authenticationManager; + } + return this.authenticationManager; + } + + protected AuthenticationPayloadInterceptor build() { + ReactiveAuthenticationManager manager = getAuthenticationManager(); + AuthenticationPayloadInterceptor result = new AuthenticationPayloadInterceptor(manager); + result.setAuthenticationConverter(new AuthenticationPayloadExchangeConverter()); + result.setOrder(PayloadInterceptorOrder.AUTHENTICATION.getOrder()); + return result; + } + + private SimpleAuthenticationSpec() { + } + + } + + public final class BasicAuthenticationSpec { + + private ReactiveAuthenticationManager authenticationManager; + + public BasicAuthenticationSpec authenticationManager(ReactiveAuthenticationManager authenticationManager) { + this.authenticationManager = authenticationManager; + return this; + } + + private ReactiveAuthenticationManager getAuthenticationManager() { + if (this.authenticationManager == null) { + return RSocketSecurity.this.authenticationManager; + } + return this.authenticationManager; + } + + protected AuthenticationPayloadInterceptor build() { + ReactiveAuthenticationManager manager = getAuthenticationManager(); + AuthenticationPayloadInterceptor result = new AuthenticationPayloadInterceptor(manager); + result.setOrder(PayloadInterceptorOrder.AUTHENTICATION.getOrder()); + return result; + } + + private BasicAuthenticationSpec() { + } + + } + + public final class JwtSpec { + + private ReactiveAuthenticationManager authenticationManager; + + public JwtSpec authenticationManager(ReactiveAuthenticationManager authenticationManager) { + this.authenticationManager = authenticationManager; + return this; + } + + private ReactiveAuthenticationManager getAuthenticationManager() { + if (this.authenticationManager != null) { + return this.authenticationManager; + } + ReactiveJwtDecoder jwtDecoder = getBeanOrNull(ReactiveJwtDecoder.class); + if (jwtDecoder != null) { + this.authenticationManager = new JwtReactiveAuthenticationManager(jwtDecoder); + return this.authenticationManager; + } + return RSocketSecurity.this.authenticationManager; + } + + protected List build() { + ReactiveAuthenticationManager manager = getAuthenticationManager(); + AuthenticationPayloadInterceptor legacy = new AuthenticationPayloadInterceptor(manager); + legacy.setAuthenticationConverter(new BearerPayloadExchangeConverter()); + legacy.setOrder(PayloadInterceptorOrder.AUTHENTICATION.getOrder()); + + AuthenticationPayloadInterceptor standard = new AuthenticationPayloadInterceptor(manager); + standard.setAuthenticationConverter(new AuthenticationPayloadExchangeConverter()); + standard.setOrder(PayloadInterceptorOrder.AUTHENTICATION.getOrder()); + + return Arrays.asList(standard, legacy); + } + + private JwtSpec() { + } + + } + public class AuthorizePayloadsSpec { private PayloadExchangeMatcherReactiveAuthorizationManager.Builder authzBuilder = PayloadExchangeMatcherReactiveAuthorizationManager @@ -417,30 +443,4 @@ public class RSocketSecurity { } - private T getBean(Class beanClass) { - if (this.context == null) { - return null; - } - return this.context.getBean(beanClass); - } - - private T getBeanOrNull(Class beanClass) { - return getBeanOrNull(ResolvableType.forClass(beanClass)); - } - - private T getBeanOrNull(ResolvableType type) { - if (this.context == null) { - return null; - } - String[] names = this.context.getBeanNamesForType(type); - if (names.length == 1) { - return (T) this.context.getBean(names[0]); - } - return null; - } - - protected void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.context = applicationContext; - } - } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java index 2b5825bcb4..89a89f6d1c 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java @@ -2912,6 +2912,24 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder> C getOrApply(C configurer) + throws Exception { + C existingConfig = (C) getConfigurer(configurer.getClass()); + if (existingConfig != null) { + return existingConfig; + } + return apply(configurer); + } + /** * An extension to {@link RequestMatcherConfigurer} that allows optionally configuring * the servlet path. @@ -2987,22 +3005,4 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder> C getOrApply(C configurer) - throws Exception { - C existingConfig = (C) getConfigurer(configurer.getClass()); - if (existingConfig != null) { - return existingConfig; - } - return apply(configurer); - } - } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java index 9bb3e2183c..1a42d57849 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java @@ -304,6 +304,36 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder enableWebSecurityAttrMap = importMetadata + .getAnnotationAttributes(EnableWebSecurity.class.getName()); + AnnotationAttributes enableWebSecurityAttrs = AnnotationAttributes.fromMap(enableWebSecurityAttrMap); + this.debugEnabled = enableWebSecurityAttrs.getBoolean("debug"); + if (this.webSecurity != null) { + this.webSecurity.debug(this.debugEnabled); + } + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader(java. + * lang.ClassLoader) + */ + @Override + public void setBeanClassLoader(ClassLoader classLoader) { + this.beanClassLoader = classLoader; + } + /** * A custom verision of the Spring provided AnnotationAwareOrderComparator that uses * {@link AnnotationUtils#findAnnotation(Class, Class)} to look on super class @@ -221,33 +250,4 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa } - /* - * (non-Javadoc) - * - * @see org.springframework.context.annotation.ImportAware#setImportMetadata(org. - * springframework.core.type.AnnotationMetadata) - */ - @Override - public void setImportMetadata(AnnotationMetadata importMetadata) { - Map enableWebSecurityAttrMap = importMetadata - .getAnnotationAttributes(EnableWebSecurity.class.getName()); - AnnotationAttributes enableWebSecurityAttrs = AnnotationAttributes.fromMap(enableWebSecurityAttrMap); - this.debugEnabled = enableWebSecurityAttrs.getBoolean("debug"); - if (this.webSecurity != null) { - this.webSecurity.debug(this.debugEnabled); - } - } - - /* - * (non-Javadoc) - * - * @see - * org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader(java. - * lang.ClassLoader) - */ - @Override - public void setBeanClassLoader(ClassLoader classLoader) { - this.beanClassLoader = classLoader; - } - } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractInterceptUrlConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractInterceptUrlConfigurer.java index dd1d6bc749..5927eb8be6 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractInterceptUrlConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractInterceptUrlConfigurer.java @@ -102,44 +102,6 @@ abstract class AbstractInterceptUrlConfigurer> getDecisionVoters(H http); - abstract class AbstractInterceptUrlRegistry, T> - extends AbstractConfigAttributeRequestMatcherRegistry { - - /** - * Allows setting the {@link AccessDecisionManager}. If none is provided, a - * default {@link AccessDecisionManager} is created. - * @param accessDecisionManager the {@link AccessDecisionManager} to use - * @return the {@link AbstractInterceptUrlConfigurer} for further customization - */ - public R accessDecisionManager(AccessDecisionManager accessDecisionManager) { - AbstractInterceptUrlConfigurer.this.accessDecisionManager = accessDecisionManager; - return getSelf(); - } - - /** - * Allows setting if the {@link FilterSecurityInterceptor} should be only applied - * once per request (i.e. if the filter intercepts on a forward, should it be - * applied again). - * @param filterSecurityInterceptorOncePerRequest if the - * {@link FilterSecurityInterceptor} should be only applied once per request - * @return the {@link AbstractInterceptUrlConfigurer} for further customization - */ - public R filterSecurityInterceptorOncePerRequest(boolean filterSecurityInterceptorOncePerRequest) { - AbstractInterceptUrlConfigurer.this.filterSecurityInterceptorOncePerRequest = filterSecurityInterceptorOncePerRequest; - return getSelf(); - } - - /** - * Returns a reference to the current object with a single suppression of the type - * @return a reference to the current object - */ - @SuppressWarnings("unchecked") - private R getSelf() { - return (R) this; - } - - } - /** * Creates the default {@code AccessDecisionManager} * @return the default {@code AccessDecisionManager} @@ -182,4 +144,42 @@ abstract class AbstractInterceptUrlConfigurer, T> + extends AbstractConfigAttributeRequestMatcherRegistry { + + /** + * Allows setting the {@link AccessDecisionManager}. If none is provided, a + * default {@link AccessDecisionManager} is created. + * @param accessDecisionManager the {@link AccessDecisionManager} to use + * @return the {@link AbstractInterceptUrlConfigurer} for further customization + */ + public R accessDecisionManager(AccessDecisionManager accessDecisionManager) { + AbstractInterceptUrlConfigurer.this.accessDecisionManager = accessDecisionManager; + return getSelf(); + } + + /** + * Allows setting if the {@link FilterSecurityInterceptor} should be only applied + * once per request (i.e. if the filter intercepts on a forward, should it be + * applied again). + * @param filterSecurityInterceptorOncePerRequest if the + * {@link FilterSecurityInterceptor} should be only applied once per request + * @return the {@link AbstractInterceptUrlConfigurer} for further customization + */ + public R filterSecurityInterceptorOncePerRequest(boolean filterSecurityInterceptorOncePerRequest) { + AbstractInterceptUrlConfigurer.this.filterSecurityInterceptorOncePerRequest = filterSecurityInterceptorOncePerRequest; + return getSelf(); + } + + /** + * Returns a reference to the current object with a single suppression of the type + * @return a reference to the current object + */ + @SuppressWarnings("unchecked") + private R getSelf() { + return (R) this; + } + + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java index d75c6d44b4..34844a74b2 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java @@ -109,61 +109,6 @@ public final class ExpressionUrlAuthorizationConfigurer.AbstractInterceptUrlRegistry { - - /** - * @param context - */ - private ExpressionInterceptUrlRegistry(ApplicationContext context) { - setApplicationContext(context); - } - - @Override - public MvcMatchersAuthorizedUrl mvcMatchers(HttpMethod method, String... mvcPatterns) { - return new MvcMatchersAuthorizedUrl(createMvcMatchers(method, mvcPatterns)); - } - - @Override - public MvcMatchersAuthorizedUrl mvcMatchers(String... patterns) { - return mvcMatchers(null, patterns); - } - - @Override - protected AuthorizedUrl chainRequestMatchersInternal(List requestMatchers) { - return new AuthorizedUrl(requestMatchers); - } - - /** - * Allows customization of the {@link SecurityExpressionHandler} to be used. The - * default is {@link DefaultWebSecurityExpressionHandler} - * @param expressionHandler the {@link SecurityExpressionHandler} to be used - * @return the {@link ExpressionUrlAuthorizationConfigurer} for further - * customization. - */ - public ExpressionInterceptUrlRegistry expressionHandler( - SecurityExpressionHandler expressionHandler) { - ExpressionUrlAuthorizationConfigurer.this.expressionHandler = expressionHandler; - return this; - } - - /** - * Adds an {@link ObjectPostProcessor} for this class. - * @param objectPostProcessor - * @return the {@link ExpressionUrlAuthorizationConfigurer} for further - * customizations - */ - public ExpressionInterceptUrlRegistry withObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { - addObjectPostProcessor(objectPostProcessor); - return this; - } - - public H and() { - return ExpressionUrlAuthorizationConfigurer.this.and(); - } - - } - /** * Allows registering multiple {@link RequestMatcher} instances to a collection of * {@link ConfigAttribute} instances @@ -261,6 +206,61 @@ public final class ExpressionUrlAuthorizationConfigurer.AbstractInterceptUrlRegistry { + + /** + * @param context + */ + private ExpressionInterceptUrlRegistry(ApplicationContext context) { + setApplicationContext(context); + } + + @Override + public MvcMatchersAuthorizedUrl mvcMatchers(HttpMethod method, String... mvcPatterns) { + return new MvcMatchersAuthorizedUrl(createMvcMatchers(method, mvcPatterns)); + } + + @Override + public MvcMatchersAuthorizedUrl mvcMatchers(String... patterns) { + return mvcMatchers(null, patterns); + } + + @Override + protected AuthorizedUrl chainRequestMatchersInternal(List requestMatchers) { + return new AuthorizedUrl(requestMatchers); + } + + /** + * Allows customization of the {@link SecurityExpressionHandler} to be used. The + * default is {@link DefaultWebSecurityExpressionHandler} + * @param expressionHandler the {@link SecurityExpressionHandler} to be used + * @return the {@link ExpressionUrlAuthorizationConfigurer} for further + * customization. + */ + public ExpressionInterceptUrlRegistry expressionHandler( + SecurityExpressionHandler expressionHandler) { + ExpressionUrlAuthorizationConfigurer.this.expressionHandler = expressionHandler; + return this; + } + + /** + * Adds an {@link ObjectPostProcessor} for this class. + * @param objectPostProcessor + * @return the {@link ExpressionUrlAuthorizationConfigurer} for further + * customizations + */ + public ExpressionInterceptUrlRegistry withObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { + addObjectPostProcessor(objectPostProcessor); + return this; + } + + public H and() { + return ExpressionUrlAuthorizationConfigurer.this.and(); + } + + } + /** * An {@link AuthorizedUrl} that allows optionally configuring the * {@link MvcRequestMatcher#setMethod(HttpMethod)} diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java index 5c9e997931..3a88e03e8f 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java @@ -145,6 +145,357 @@ public class HeadersConfigurer> return HeadersConfigurer.this; } + /** + * Note this is not comprehensive XSS protection! + * + *

+ * Allows customizing the {@link XXssProtectionHeaderWriter} which adds the X-XSS-Protection header + *

+ * @return the {@link XXssConfig} for additional customizations + */ + public XXssConfig xssProtection() { + return this.xssProtection.enable(); + } + + /** + * Note this is not comprehensive XSS protection! + * + *

+ * Allows customizing the {@link XXssProtectionHeaderWriter} which adds the X-XSS-Protection header + *

+ * @param xssCustomizer the {@link Customizer} to provide more options for the + * {@link XXssConfig} + * @return the {@link HeadersConfigurer} for additional customizations + */ + public HeadersConfigurer xssProtection(Customizer xssCustomizer) { + xssCustomizer.customize(this.xssProtection.enable()); + return HeadersConfigurer.this; + } + + /** + * Allows customizing the {@link CacheControlHeadersWriter}. Specifically it adds the + * following headers: + *
    + *
  • Cache-Control: no-cache, no-store, max-age=0, must-revalidate
  • + *
  • Pragma: no-cache
  • + *
  • Expires: 0
  • + *
+ * @return the {@link CacheControlConfig} for additional customizations + */ + public CacheControlConfig cacheControl() { + return this.cacheControl.enable(); + } + + /** + * Allows customizing the {@link CacheControlHeadersWriter}. Specifically it adds the + * following headers: + *
    + *
  • Cache-Control: no-cache, no-store, max-age=0, must-revalidate
  • + *
  • Pragma: no-cache
  • + *
  • Expires: 0
  • + *
+ * @param cacheControlCustomizer the {@link Customizer} to provide more options for + * the {@link CacheControlConfig} + * @return the {@link HeadersConfigurer} for additional customizations + */ + public HeadersConfigurer cacheControl(Customizer cacheControlCustomizer) { + cacheControlCustomizer.customize(this.cacheControl.enable()); + return HeadersConfigurer.this; + } + + /** + * Allows customizing the {@link HstsHeaderWriter} which provides support for + * HTTP Strict Transport Security + * (HSTS). + * @return the {@link HstsConfig} for additional customizations + */ + public HstsConfig httpStrictTransportSecurity() { + return this.hsts.enable(); + } + + /** + * Allows customizing the {@link HstsHeaderWriter} which provides support for + * HTTP Strict Transport Security + * (HSTS). + * @param hstsCustomizer the {@link Customizer} to provide more options for the + * {@link HstsConfig} + * @return the {@link HeadersConfigurer} for additional customizations + */ + public HeadersConfigurer httpStrictTransportSecurity(Customizer hstsCustomizer) { + hstsCustomizer.customize(this.hsts.enable()); + return HeadersConfigurer.this; + } + + /** + * Allows customizing the {@link XFrameOptionsHeaderWriter}. + * @return the {@link FrameOptionsConfig} for additional customizations + */ + public FrameOptionsConfig frameOptions() { + return this.frameOptions.enable(); + } + + /** + * Allows customizing the {@link XFrameOptionsHeaderWriter}. + * @param frameOptionsCustomizer the {@link Customizer} to provide more options for + * the {@link FrameOptionsConfig} + * @return the {@link HeadersConfigurer} for additional customizations + */ + public HeadersConfigurer frameOptions(Customizer frameOptionsCustomizer) { + frameOptionsCustomizer.customize(this.frameOptions.enable()); + return HeadersConfigurer.this; + } + + /** + * Allows customizing the {@link HpkpHeaderWriter} which provides support for + * HTTP Public Key Pinning (HPKP). + * @return the {@link HpkpConfig} for additional customizations + * + * @since 4.1 + */ + public HpkpConfig httpPublicKeyPinning() { + return this.hpkp.enable(); + } + + /** + * Allows customizing the {@link HpkpHeaderWriter} which provides support for + * HTTP Public Key Pinning (HPKP). + * @param hpkpCustomizer the {@link Customizer} to provide more options for the + * {@link HpkpConfig} + * @return the {@link HeadersConfigurer} for additional customizations + */ + public HeadersConfigurer httpPublicKeyPinning(Customizer hpkpCustomizer) { + hpkpCustomizer.customize(this.hpkp.enable()); + return HeadersConfigurer.this; + } + + /** + *

+ * Allows configuration for Content Security + * Policy (CSP) Level 2. + *

+ * + *

+ * Calling this method automatically enables (includes) the Content-Security-Policy + * header in the response using the supplied security policy directive(s). + *

+ * + *

+ * Configuration is provided to the {@link ContentSecurityPolicyHeaderWriter} which + * supports the writing of the two headers as detailed in the W3C Candidate + * Recommendation: + *

+ *
    + *
  • Content-Security-Policy
  • + *
  • Content-Security-Policy-Report-Only
  • + *
+ * @return the {@link ContentSecurityPolicyConfig} for additional configuration + * @throws IllegalArgumentException if policyDirectives is null or empty + * @since 4.1 + * @see ContentSecurityPolicyHeaderWriter + */ + public ContentSecurityPolicyConfig contentSecurityPolicy(String policyDirectives) { + this.contentSecurityPolicy.writer = new ContentSecurityPolicyHeaderWriter(policyDirectives); + return this.contentSecurityPolicy; + } + + /** + *

+ * Allows configuration for Content Security + * Policy (CSP) Level 2. + *

+ * + *

+ * Calling this method automatically enables (includes) the Content-Security-Policy + * header in the response using the supplied security policy directive(s). + *

+ * + *

+ * Configuration is provided to the {@link ContentSecurityPolicyHeaderWriter} which + * supports the writing of the two headers as detailed in the W3C Candidate + * Recommendation: + *

+ *
    + *
  • Content-Security-Policy
  • + *
  • Content-Security-Policy-Report-Only
  • + *
+ * @param contentSecurityCustomizer the {@link Customizer} to provide more options for + * the {@link ContentSecurityPolicyConfig} + * @return the {@link HeadersConfigurer} for additional customizations + * @see ContentSecurityPolicyHeaderWriter + */ + public HeadersConfigurer contentSecurityPolicy( + Customizer contentSecurityCustomizer) { + this.contentSecurityPolicy.writer = new ContentSecurityPolicyHeaderWriter(); + contentSecurityCustomizer.customize(this.contentSecurityPolicy); + + return HeadersConfigurer.this; + } + + /** + * Clears all of the default headers from the response. After doing so, one can add + * headers back. For example, if you only want to use Spring Security's cache control + * you can use the following: + * + *
+	 * http.headers().defaultsDisabled().cacheControl();
+	 * 
+ * @return the {@link HeadersConfigurer} for additional customization + */ + public HeadersConfigurer defaultsDisabled() { + this.contentTypeOptions.disable(); + this.xssProtection.disable(); + this.cacheControl.disable(); + this.hsts.disable(); + this.frameOptions.disable(); + return this; + } + + @Override + public void configure(H http) { + HeaderWriterFilter headersFilter = createHeaderWriterFilter(); + http.addFilter(headersFilter); + } + + /** + * Creates the {@link HeaderWriter} + * @return the {@link HeaderWriter} + */ + private HeaderWriterFilter createHeaderWriterFilter() { + List writers = getHeaderWriters(); + if (writers.isEmpty()) { + throw new IllegalStateException( + "Headers security is enabled, but no headers will be added. Either add headers or disable headers security"); + } + HeaderWriterFilter headersFilter = new HeaderWriterFilter(writers); + headersFilter = postProcess(headersFilter); + return headersFilter; + } + + /** + * Gets the {@link HeaderWriter} instances and possibly initializes with the defaults. + * @return + */ + private List getHeaderWriters() { + List writers = new ArrayList<>(); + addIfNotNull(writers, this.contentTypeOptions.writer); + addIfNotNull(writers, this.xssProtection.writer); + addIfNotNull(writers, this.cacheControl.writer); + addIfNotNull(writers, this.hsts.writer); + addIfNotNull(writers, this.frameOptions.writer); + addIfNotNull(writers, this.hpkp.writer); + addIfNotNull(writers, this.contentSecurityPolicy.writer); + addIfNotNull(writers, this.referrerPolicy.writer); + addIfNotNull(writers, this.featurePolicy.writer); + writers.addAll(this.headerWriters); + return writers; + } + + private void addIfNotNull(List values, T value) { + if (value != null) { + values.add(value); + } + } + + /** + *

+ * Allows configuration for Referrer + * Policy. + *

+ * + *

+ * Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support + * the writing of the header as detailed in the W3C Technical Report: + *

+ *
    + *
  • Referrer-Policy
  • + *
+ * + *

+ * Default value is: + *

+ * + *
+	 * Referrer-Policy: no-referrer
+	 * 
+ * @return the {@link ReferrerPolicyConfig} for additional configuration + * @since 4.2 + * @see ReferrerPolicyHeaderWriter + */ + public ReferrerPolicyConfig referrerPolicy() { + this.referrerPolicy.writer = new ReferrerPolicyHeaderWriter(); + return this.referrerPolicy; + } + + /** + *

+ * Allows configuration for Referrer + * Policy. + *

+ * + *

+ * Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support + * the writing of the header as detailed in the W3C Technical Report: + *

+ *
    + *
  • Referrer-Policy
  • + *
+ * @return the {@link ReferrerPolicyConfig} for additional configuration + * @throws IllegalArgumentException if policy is null or empty + * @since 4.2 + * @see ReferrerPolicyHeaderWriter + */ + public ReferrerPolicyConfig referrerPolicy(ReferrerPolicy policy) { + this.referrerPolicy.writer = new ReferrerPolicyHeaderWriter(policy); + return this.referrerPolicy; + } + + /** + *

+ * Allows configuration for Referrer + * Policy. + *

+ * + *

+ * Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support + * the writing of the header as detailed in the W3C Technical Report: + *

+ *
    + *
  • Referrer-Policy
  • + *
+ * @param referrerPolicyCustomizer the {@link Customizer} to provide more options for + * the {@link ReferrerPolicyConfig} + * @return the {@link HeadersConfigurer} for additional customizations + * @see ReferrerPolicyHeaderWriter + */ + public HeadersConfigurer referrerPolicy(Customizer referrerPolicyCustomizer) { + this.referrerPolicy.writer = new ReferrerPolicyHeaderWriter(); + referrerPolicyCustomizer.customize(this.referrerPolicy); + return HeadersConfigurer.this; + } + + /** + * Allows configuration for Feature + * Policy. + *

+ * Calling this method automatically enables (includes) the {@code Feature-Policy} + * header in the response using the supplied policy directive(s). + *

+ * Configuration is provided to the {@link FeaturePolicyHeaderWriter} which is + * responsible for writing the header. + * @return the {@link FeaturePolicyConfig} for additional configuration + * @throws IllegalArgumentException if policyDirectives is {@code null} or empty + * @since 5.1 + * @see FeaturePolicyHeaderWriter + */ + public FeaturePolicyConfig featurePolicy(String policyDirectives) { + this.featurePolicy.writer = new FeaturePolicyHeaderWriter(policyDirectives); + return this.featurePolicy; + } + public final class ContentTypeOptionsConfig { private XContentTypeOptionsHeaderWriter writer; @@ -183,37 +534,6 @@ public class HeadersConfigurer> } - /** - * Note this is not comprehensive XSS protection! - * - *

- * Allows customizing the {@link XXssProtectionHeaderWriter} which adds the X-XSS-Protection header - *

- * @return the {@link XXssConfig} for additional customizations - */ - public XXssConfig xssProtection() { - return this.xssProtection.enable(); - } - - /** - * Note this is not comprehensive XSS protection! - * - *

- * Allows customizing the {@link XXssProtectionHeaderWriter} which adds the X-XSS-Protection header - *

- * @param xssCustomizer the {@link Customizer} to provide more options for the - * {@link XXssConfig} - * @return the {@link HeadersConfigurer} for additional customizations - */ - public HeadersConfigurer xssProtection(Customizer xssCustomizer) { - xssCustomizer.customize(this.xssProtection.enable()); - return HeadersConfigurer.this; - } - public final class XXssConfig { private XXssProtectionHeaderWriter writer; @@ -291,37 +611,6 @@ public class HeadersConfigurer> } - /** - * Allows customizing the {@link CacheControlHeadersWriter}. Specifically it adds the - * following headers: - *
    - *
  • Cache-Control: no-cache, no-store, max-age=0, must-revalidate
  • - *
  • Pragma: no-cache
  • - *
  • Expires: 0
  • - *
- * @return the {@link CacheControlConfig} for additional customizations - */ - public CacheControlConfig cacheControl() { - return this.cacheControl.enable(); - } - - /** - * Allows customizing the {@link CacheControlHeadersWriter}. Specifically it adds the - * following headers: - *
    - *
  • Cache-Control: no-cache, no-store, max-age=0, must-revalidate
  • - *
  • Pragma: no-cache
  • - *
  • Expires: 0
  • - *
- * @param cacheControlCustomizer the {@link Customizer} to provide more options for - * the {@link CacheControlConfig} - * @return the {@link HeadersConfigurer} for additional customizations - */ - public HeadersConfigurer cacheControl(Customizer cacheControlCustomizer) { - cacheControlCustomizer.customize(this.cacheControl.enable()); - return HeadersConfigurer.this; - } - public final class CacheControlConfig { private CacheControlHeadersWriter writer; @@ -361,29 +650,6 @@ public class HeadersConfigurer> } - /** - * Allows customizing the {@link HstsHeaderWriter} which provides support for - * HTTP Strict Transport Security - * (HSTS). - * @return the {@link HstsConfig} for additional customizations - */ - public HstsConfig httpStrictTransportSecurity() { - return this.hsts.enable(); - } - - /** - * Allows customizing the {@link HstsHeaderWriter} which provides support for - * HTTP Strict Transport Security - * (HSTS). - * @param hstsCustomizer the {@link Customizer} to provide more options for the - * {@link HstsConfig} - * @return the {@link HeadersConfigurer} for additional customizations - */ - public HeadersConfigurer httpStrictTransportSecurity(Customizer hstsCustomizer) { - hstsCustomizer.customize(this.hsts.enable()); - return HeadersConfigurer.this; - } - public final class HstsConfig { private HstsHeaderWriter writer; @@ -491,25 +757,6 @@ public class HeadersConfigurer> } - /** - * Allows customizing the {@link XFrameOptionsHeaderWriter}. - * @return the {@link FrameOptionsConfig} for additional customizations - */ - public FrameOptionsConfig frameOptions() { - return this.frameOptions.enable(); - } - - /** - * Allows customizing the {@link XFrameOptionsHeaderWriter}. - * @param frameOptionsCustomizer the {@link Customizer} to provide more options for - * the {@link FrameOptionsConfig} - * @return the {@link HeadersConfigurer} for additional customizations - */ - public HeadersConfigurer frameOptions(Customizer frameOptionsCustomizer) { - frameOptionsCustomizer.customize(this.frameOptions.enable()); - return HeadersConfigurer.this; - } - public final class FrameOptionsConfig { private XFrameOptionsHeaderWriter writer; @@ -571,29 +818,6 @@ public class HeadersConfigurer> } - /** - * Allows customizing the {@link HpkpHeaderWriter} which provides support for - * HTTP Public Key Pinning (HPKP). - * @return the {@link HpkpConfig} for additional customizations - * - * @since 4.1 - */ - public HpkpConfig httpPublicKeyPinning() { - return this.hpkp.enable(); - } - - /** - * Allows customizing the {@link HpkpHeaderWriter} which provides support for - * HTTP Public Key Pinning (HPKP). - * @param hpkpCustomizer the {@link Customizer} to provide more options for the - * {@link HpkpConfig} - * @return the {@link HeadersConfigurer} for additional customizations - */ - public HeadersConfigurer httpPublicKeyPinning(Customizer hpkpCustomizer) { - hpkpCustomizer.customize(this.hpkp.enable()); - return HeadersConfigurer.this; - } - public final class HpkpConfig { private HpkpHeaderWriter writer; @@ -761,69 +985,6 @@ public class HeadersConfigurer> } - /** - *

- * Allows configuration for Content Security - * Policy (CSP) Level 2. - *

- * - *

- * Calling this method automatically enables (includes) the Content-Security-Policy - * header in the response using the supplied security policy directive(s). - *

- * - *

- * Configuration is provided to the {@link ContentSecurityPolicyHeaderWriter} which - * supports the writing of the two headers as detailed in the W3C Candidate - * Recommendation: - *

- *
    - *
  • Content-Security-Policy
  • - *
  • Content-Security-Policy-Report-Only
  • - *
- * @return the {@link ContentSecurityPolicyConfig} for additional configuration - * @throws IllegalArgumentException if policyDirectives is null or empty - * @since 4.1 - * @see ContentSecurityPolicyHeaderWriter - */ - public ContentSecurityPolicyConfig contentSecurityPolicy(String policyDirectives) { - this.contentSecurityPolicy.writer = new ContentSecurityPolicyHeaderWriter(policyDirectives); - return this.contentSecurityPolicy; - } - - /** - *

- * Allows configuration for Content Security - * Policy (CSP) Level 2. - *

- * - *

- * Calling this method automatically enables (includes) the Content-Security-Policy - * header in the response using the supplied security policy directive(s). - *

- * - *

- * Configuration is provided to the {@link ContentSecurityPolicyHeaderWriter} which - * supports the writing of the two headers as detailed in the W3C Candidate - * Recommendation: - *

- *
    - *
  • Content-Security-Policy
  • - *
  • Content-Security-Policy-Report-Only
  • - *
- * @param contentSecurityCustomizer the {@link Customizer} to provide more options for - * the {@link ContentSecurityPolicyConfig} - * @return the {@link HeadersConfigurer} for additional customizations - * @see ContentSecurityPolicyHeaderWriter - */ - public HeadersConfigurer contentSecurityPolicy( - Customizer contentSecurityCustomizer) { - this.contentSecurityPolicy.writer = new ContentSecurityPolicyHeaderWriter(); - contentSecurityCustomizer.customize(this.contentSecurityPolicy); - - return HeadersConfigurer.this; - } - public final class ContentSecurityPolicyConfig { private ContentSecurityPolicyHeaderWriter writer; @@ -863,148 +1024,6 @@ public class HeadersConfigurer> } - /** - * Clears all of the default headers from the response. After doing so, one can add - * headers back. For example, if you only want to use Spring Security's cache control - * you can use the following: - * - *
-	 * http.headers().defaultsDisabled().cacheControl();
-	 * 
- * @return the {@link HeadersConfigurer} for additional customization - */ - public HeadersConfigurer defaultsDisabled() { - this.contentTypeOptions.disable(); - this.xssProtection.disable(); - this.cacheControl.disable(); - this.hsts.disable(); - this.frameOptions.disable(); - return this; - } - - @Override - public void configure(H http) { - HeaderWriterFilter headersFilter = createHeaderWriterFilter(); - http.addFilter(headersFilter); - } - - /** - * Creates the {@link HeaderWriter} - * @return the {@link HeaderWriter} - */ - private HeaderWriterFilter createHeaderWriterFilter() { - List writers = getHeaderWriters(); - if (writers.isEmpty()) { - throw new IllegalStateException( - "Headers security is enabled, but no headers will be added. Either add headers or disable headers security"); - } - HeaderWriterFilter headersFilter = new HeaderWriterFilter(writers); - headersFilter = postProcess(headersFilter); - return headersFilter; - } - - /** - * Gets the {@link HeaderWriter} instances and possibly initializes with the defaults. - * @return - */ - private List getHeaderWriters() { - List writers = new ArrayList<>(); - addIfNotNull(writers, this.contentTypeOptions.writer); - addIfNotNull(writers, this.xssProtection.writer); - addIfNotNull(writers, this.cacheControl.writer); - addIfNotNull(writers, this.hsts.writer); - addIfNotNull(writers, this.frameOptions.writer); - addIfNotNull(writers, this.hpkp.writer); - addIfNotNull(writers, this.contentSecurityPolicy.writer); - addIfNotNull(writers, this.referrerPolicy.writer); - addIfNotNull(writers, this.featurePolicy.writer); - writers.addAll(this.headerWriters); - return writers; - } - - private void addIfNotNull(List values, T value) { - if (value != null) { - values.add(value); - } - } - - /** - *

- * Allows configuration for Referrer - * Policy. - *

- * - *

- * Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support - * the writing of the header as detailed in the W3C Technical Report: - *

- *
    - *
  • Referrer-Policy
  • - *
- * - *

- * Default value is: - *

- * - *
-	 * Referrer-Policy: no-referrer
-	 * 
- * @return the {@link ReferrerPolicyConfig} for additional configuration - * @since 4.2 - * @see ReferrerPolicyHeaderWriter - */ - public ReferrerPolicyConfig referrerPolicy() { - this.referrerPolicy.writer = new ReferrerPolicyHeaderWriter(); - return this.referrerPolicy; - } - - /** - *

- * Allows configuration for Referrer - * Policy. - *

- * - *

- * Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support - * the writing of the header as detailed in the W3C Technical Report: - *

- *
    - *
  • Referrer-Policy
  • - *
- * @return the {@link ReferrerPolicyConfig} for additional configuration - * @throws IllegalArgumentException if policy is null or empty - * @since 4.2 - * @see ReferrerPolicyHeaderWriter - */ - public ReferrerPolicyConfig referrerPolicy(ReferrerPolicy policy) { - this.referrerPolicy.writer = new ReferrerPolicyHeaderWriter(policy); - return this.referrerPolicy; - } - - /** - *

- * Allows configuration for Referrer - * Policy. - *

- * - *

- * Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support - * the writing of the header as detailed in the W3C Technical Report: - *

- *
    - *
  • Referrer-Policy
  • - *
- * @param referrerPolicyCustomizer the {@link Customizer} to provide more options for - * the {@link ReferrerPolicyConfig} - * @return the {@link HeadersConfigurer} for additional customizations - * @see ReferrerPolicyHeaderWriter - */ - public HeadersConfigurer referrerPolicy(Customizer referrerPolicyCustomizer) { - this.referrerPolicy.writer = new ReferrerPolicyHeaderWriter(); - referrerPolicyCustomizer.customize(this.referrerPolicy); - return HeadersConfigurer.this; - } - public final class ReferrerPolicyConfig { private ReferrerPolicyHeaderWriter writer; @@ -1029,25 +1048,6 @@ public class HeadersConfigurer> } - /** - * Allows configuration for Feature - * Policy. - *

- * Calling this method automatically enables (includes) the {@code Feature-Policy} - * header in the response using the supplied policy directive(s). - *

- * Configuration is provided to the {@link FeaturePolicyHeaderWriter} which is - * responsible for writing the header. - * @return the {@link FeaturePolicyConfig} for additional configuration - * @throws IllegalArgumentException if policyDirectives is {@code null} or empty - * @since 5.1 - * @see FeaturePolicyHeaderWriter - */ - public FeaturePolicyConfig featurePolicy(String policyDirectives) { - this.featurePolicy.writer = new FeaturePolicyHeaderWriter(policyDirectives); - return this.featurePolicy; - } - public final class FeaturePolicyConfig { private FeaturePolicyHeaderWriter writer; diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java index 4cd029d56a..c38d6fbc96 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java @@ -311,144 +311,6 @@ public final class SessionManagementConfigurer> this.sessionFixationAuthenticationStrategy = postProcess(sessionFixationAuthenticationStrategy); } - /** - * Allows configuring SessionFixation protection - * - * @author Rob Winch - */ - public final class SessionFixationConfigurer { - - /** - * Specifies that a new session should be created, but the session attributes from - * the original {@link HttpSession} should not be retained. - * @return the {@link SessionManagementConfigurer} for further customizations - */ - public SessionManagementConfigurer newSession() { - SessionFixationProtectionStrategy sessionFixationProtectionStrategy = new SessionFixationProtectionStrategy(); - sessionFixationProtectionStrategy.setMigrateSessionAttributes(false); - setSessionFixationAuthenticationStrategy(sessionFixationProtectionStrategy); - return SessionManagementConfigurer.this; - } - - /** - * Specifies that a new session should be created and the session attributes from - * the original {@link HttpSession} should be retained. - * @return the {@link SessionManagementConfigurer} for further customizations - */ - public SessionManagementConfigurer migrateSession() { - setSessionFixationAuthenticationStrategy(new SessionFixationProtectionStrategy()); - return SessionManagementConfigurer.this; - } - - /** - * Specifies that the Servlet container-provided session fixation protection - * should be used. When a session authenticates, the Servlet method - * {@code HttpServletRequest#changeSessionId()} is called to change the session ID - * and retain all session attributes. - * @return the {@link SessionManagementConfigurer} for further customizations - */ - public SessionManagementConfigurer changeSessionId() { - setSessionFixationAuthenticationStrategy(new ChangeSessionIdAuthenticationStrategy()); - return SessionManagementConfigurer.this; - } - - /** - * Specifies that no session fixation protection should be enabled. This may be - * useful when utilizing other mechanisms for protecting against session fixation. - * For example, if application container session fixation protection is already in - * use. Otherwise, this option is not recommended. - * @return the {@link SessionManagementConfigurer} for further customizations - */ - public SessionManagementConfigurer none() { - setSessionFixationAuthenticationStrategy(new NullAuthenticatedSessionStrategy()); - return SessionManagementConfigurer.this; - } - - } - - /** - * Allows configuring controlling of multiple sessions. - * - * @author Rob Winch - */ - public final class ConcurrencyControlConfigurer { - - /** - * Controls the maximum number of sessions for a user. The default is to allow any - * number of users. - * @param maximumSessions the maximum number of sessions for a user - * @return the {@link ConcurrencyControlConfigurer} for further customizations - */ - public ConcurrencyControlConfigurer maximumSessions(int maximumSessions) { - SessionManagementConfigurer.this.maximumSessions = maximumSessions; - return this; - } - - /** - * The URL to redirect to if a user tries to access a resource and their session - * has been expired due to too many sessions for the current user. The default is - * to write a simple error message to the response. - * @param expiredUrl the URL to redirect to - * @return the {@link ConcurrencyControlConfigurer} for further customizations - */ - public ConcurrencyControlConfigurer expiredUrl(String expiredUrl) { - SessionManagementConfigurer.this.expiredUrl = expiredUrl; - return this; - } - - /** - * Determines the behaviour when an expired session is detected. - * @param expiredSessionStrategy the {@link SessionInformationExpiredStrategy} to - * use when an expired session is detected. - * @return the {@link ConcurrencyControlConfigurer} for further customizations - */ - public ConcurrencyControlConfigurer expiredSessionStrategy( - SessionInformationExpiredStrategy expiredSessionStrategy) { - SessionManagementConfigurer.this.expiredSessionStrategy = expiredSessionStrategy; - return this; - } - - /** - * If true, prevents a user from authenticating when the - * {@link #maximumSessions(int)} has been reached. Otherwise (default), the user - * who authenticates is allowed access and an existing user's session is expired. - * The user's who's session is forcibly expired is sent to - * {@link #expiredUrl(String)}. The advantage of this approach is if a user - * accidentally does not log out, there is no need for an administrator to - * intervene or wait till their session expires. - * @param maxSessionsPreventsLogin true to have an error at time of - * authentication, else false (default) - * @return the {@link ConcurrencyControlConfigurer} for further customizations - */ - public ConcurrencyControlConfigurer maxSessionsPreventsLogin(boolean maxSessionsPreventsLogin) { - SessionManagementConfigurer.this.maxSessionsPreventsLogin = maxSessionsPreventsLogin; - return this; - } - - /** - * Controls the {@link SessionRegistry} implementation used. The default is - * {@link SessionRegistryImpl} which is an in memory implementation. - * @param sessionRegistry the {@link SessionRegistry} to use - * @return the {@link ConcurrencyControlConfigurer} for further customizations - */ - public ConcurrencyControlConfigurer sessionRegistry(SessionRegistry sessionRegistry) { - SessionManagementConfigurer.this.sessionRegistry = sessionRegistry; - return this; - } - - /** - * Used to chain back to the {@link SessionManagementConfigurer} - * @return the {@link SessionManagementConfigurer} for further customizations - */ - public SessionManagementConfigurer and() { - return SessionManagementConfigurer.this; - } - - private ConcurrencyControlConfigurer() { - } - - } - @Override public void init(H http) { SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class); @@ -703,4 +565,142 @@ public final class SessionManagementConfigurer> } } + /** + * Allows configuring SessionFixation protection + * + * @author Rob Winch + */ + public final class SessionFixationConfigurer { + + /** + * Specifies that a new session should be created, but the session attributes from + * the original {@link HttpSession} should not be retained. + * @return the {@link SessionManagementConfigurer} for further customizations + */ + public SessionManagementConfigurer newSession() { + SessionFixationProtectionStrategy sessionFixationProtectionStrategy = new SessionFixationProtectionStrategy(); + sessionFixationProtectionStrategy.setMigrateSessionAttributes(false); + setSessionFixationAuthenticationStrategy(sessionFixationProtectionStrategy); + return SessionManagementConfigurer.this; + } + + /** + * Specifies that a new session should be created and the session attributes from + * the original {@link HttpSession} should be retained. + * @return the {@link SessionManagementConfigurer} for further customizations + */ + public SessionManagementConfigurer migrateSession() { + setSessionFixationAuthenticationStrategy(new SessionFixationProtectionStrategy()); + return SessionManagementConfigurer.this; + } + + /** + * Specifies that the Servlet container-provided session fixation protection + * should be used. When a session authenticates, the Servlet method + * {@code HttpServletRequest#changeSessionId()} is called to change the session ID + * and retain all session attributes. + * @return the {@link SessionManagementConfigurer} for further customizations + */ + public SessionManagementConfigurer changeSessionId() { + setSessionFixationAuthenticationStrategy(new ChangeSessionIdAuthenticationStrategy()); + return SessionManagementConfigurer.this; + } + + /** + * Specifies that no session fixation protection should be enabled. This may be + * useful when utilizing other mechanisms for protecting against session fixation. + * For example, if application container session fixation protection is already in + * use. Otherwise, this option is not recommended. + * @return the {@link SessionManagementConfigurer} for further customizations + */ + public SessionManagementConfigurer none() { + setSessionFixationAuthenticationStrategy(new NullAuthenticatedSessionStrategy()); + return SessionManagementConfigurer.this; + } + + } + + /** + * Allows configuring controlling of multiple sessions. + * + * @author Rob Winch + */ + public final class ConcurrencyControlConfigurer { + + /** + * Controls the maximum number of sessions for a user. The default is to allow any + * number of users. + * @param maximumSessions the maximum number of sessions for a user + * @return the {@link ConcurrencyControlConfigurer} for further customizations + */ + public ConcurrencyControlConfigurer maximumSessions(int maximumSessions) { + SessionManagementConfigurer.this.maximumSessions = maximumSessions; + return this; + } + + /** + * The URL to redirect to if a user tries to access a resource and their session + * has been expired due to too many sessions for the current user. The default is + * to write a simple error message to the response. + * @param expiredUrl the URL to redirect to + * @return the {@link ConcurrencyControlConfigurer} for further customizations + */ + public ConcurrencyControlConfigurer expiredUrl(String expiredUrl) { + SessionManagementConfigurer.this.expiredUrl = expiredUrl; + return this; + } + + /** + * Determines the behaviour when an expired session is detected. + * @param expiredSessionStrategy the {@link SessionInformationExpiredStrategy} to + * use when an expired session is detected. + * @return the {@link ConcurrencyControlConfigurer} for further customizations + */ + public ConcurrencyControlConfigurer expiredSessionStrategy( + SessionInformationExpiredStrategy expiredSessionStrategy) { + SessionManagementConfigurer.this.expiredSessionStrategy = expiredSessionStrategy; + return this; + } + + /** + * If true, prevents a user from authenticating when the + * {@link #maximumSessions(int)} has been reached. Otherwise (default), the user + * who authenticates is allowed access and an existing user's session is expired. + * The user's who's session is forcibly expired is sent to + * {@link #expiredUrl(String)}. The advantage of this approach is if a user + * accidentally does not log out, there is no need for an administrator to + * intervene or wait till their session expires. + * @param maxSessionsPreventsLogin true to have an error at time of + * authentication, else false (default) + * @return the {@link ConcurrencyControlConfigurer} for further customizations + */ + public ConcurrencyControlConfigurer maxSessionsPreventsLogin(boolean maxSessionsPreventsLogin) { + SessionManagementConfigurer.this.maxSessionsPreventsLogin = maxSessionsPreventsLogin; + return this; + } + + /** + * Controls the {@link SessionRegistry} implementation used. The default is + * {@link SessionRegistryImpl} which is an in memory implementation. + * @param sessionRegistry the {@link SessionRegistry} to use + * @return the {@link ConcurrencyControlConfigurer} for further customizations + */ + public ConcurrencyControlConfigurer sessionRegistry(SessionRegistry sessionRegistry) { + SessionManagementConfigurer.this.sessionRegistry = sessionRegistry; + return this; + } + + /** + * Used to chain back to the {@link SessionManagementConfigurer} + * @return the {@link SessionManagementConfigurer} for further customizations + */ + public SessionManagementConfigurer and() { + return SessionManagementConfigurer.this; + } + + private ConcurrencyControlConfigurer() { + } + + } + } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurer.java index b9a47da77e..149a7e79ac 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurer.java @@ -114,48 +114,6 @@ public final class UrlAuthorizationConfigurer> return this; } - public final class StandardInterceptUrlRegistry extends - ExpressionUrlAuthorizationConfigurer.AbstractInterceptUrlRegistry { - - /** - * @param context - */ - private StandardInterceptUrlRegistry(ApplicationContext context) { - setApplicationContext(context); - } - - @Override - public MvcMatchersAuthorizedUrl mvcMatchers(HttpMethod method, String... mvcPatterns) { - return new MvcMatchersAuthorizedUrl(createMvcMatchers(method, mvcPatterns)); - } - - @Override - public MvcMatchersAuthorizedUrl mvcMatchers(String... patterns) { - return mvcMatchers(null, patterns); - } - - @Override - protected AuthorizedUrl chainRequestMatchersInternal(List requestMatchers) { - return new AuthorizedUrl(requestMatchers); - } - - /** - * Adds an {@link ObjectPostProcessor} for this class. - * @param objectPostProcessor - * @return the {@link ExpressionUrlAuthorizationConfigurer} for further - * customizations - */ - public StandardInterceptUrlRegistry withObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { - addObjectPostProcessor(objectPostProcessor); - return this; - } - - public H and() { - return UrlAuthorizationConfigurer.this.and(); - } - - } - /** * Creates the default {@link AccessDecisionVoter} instances used if an * {@link AccessDecisionManager} was not specified. @@ -234,6 +192,48 @@ public final class UrlAuthorizationConfigurer> return authorities; } + public final class StandardInterceptUrlRegistry extends + ExpressionUrlAuthorizationConfigurer.AbstractInterceptUrlRegistry { + + /** + * @param context + */ + private StandardInterceptUrlRegistry(ApplicationContext context) { + setApplicationContext(context); + } + + @Override + public MvcMatchersAuthorizedUrl mvcMatchers(HttpMethod method, String... mvcPatterns) { + return new MvcMatchersAuthorizedUrl(createMvcMatchers(method, mvcPatterns)); + } + + @Override + public MvcMatchersAuthorizedUrl mvcMatchers(String... patterns) { + return mvcMatchers(null, patterns); + } + + @Override + protected AuthorizedUrl chainRequestMatchersInternal(List requestMatchers) { + return new AuthorizedUrl(requestMatchers); + } + + /** + * Adds an {@link ObjectPostProcessor} for this class. + * @param objectPostProcessor + * @return the {@link ExpressionUrlAuthorizationConfigurer} for further + * customizations + */ + public StandardInterceptUrlRegistry withObjectPostProcessor(ObjectPostProcessor objectPostProcessor) { + addObjectPostProcessor(objectPostProcessor); + return this; + } + + public H and() { + return UrlAuthorizationConfigurer.this.and(); + } + + } + /** * An {@link AuthorizedUrl} that allows optionally configuring the * {@link MvcRequestMatcher#setMethod(HttpMethod)} diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurer.java index 64e9205359..96fe913fc6 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurer.java @@ -151,6 +151,16 @@ public final class OAuth2ClientConfigurer> return this; } + @Override + public void init(B builder) { + this.authorizationCodeGrantConfigurer.init(builder); + } + + @Override + public void configure(B builder) { + this.authorizationCodeGrantConfigurer.configure(builder); + } + /** * Configuration options for the OAuth 2.0 Authorization Code Grant. */ @@ -281,14 +291,4 @@ public final class OAuth2ClientConfigurer> } - @Override - public void init(B builder) { - this.authorizationCodeGrantConfigurer.init(builder); - } - - @Override - public void configure(B builder) { - this.authorizationCodeGrantConfigurer.configure(builder); - } - } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java index 01c8d1625d..9944dedfa3 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java @@ -221,69 +221,6 @@ public final class OAuth2LoginConfigurer> return this; } - /** - * Configuration options for the Authorization Server's Authorization Endpoint. - */ - public final class AuthorizationEndpointConfig { - - private String authorizationRequestBaseUri; - - private OAuth2AuthorizationRequestResolver authorizationRequestResolver; - - private AuthorizationRequestRepository authorizationRequestRepository; - - private AuthorizationEndpointConfig() { - } - - /** - * Sets the base {@code URI} used for authorization requests. - * @param authorizationRequestBaseUri the base {@code URI} used for authorization - * requests - * @return the {@link AuthorizationEndpointConfig} for further configuration - */ - public AuthorizationEndpointConfig baseUri(String authorizationRequestBaseUri) { - Assert.hasText(authorizationRequestBaseUri, "authorizationRequestBaseUri cannot be empty"); - this.authorizationRequestBaseUri = authorizationRequestBaseUri; - return this; - } - - /** - * Sets the resolver used for resolving {@link OAuth2AuthorizationRequest}'s. - * @param authorizationRequestResolver the resolver used for resolving - * {@link OAuth2AuthorizationRequest}'s - * @return the {@link AuthorizationEndpointConfig} for further configuration - * @since 5.1 - */ - public AuthorizationEndpointConfig authorizationRequestResolver( - OAuth2AuthorizationRequestResolver authorizationRequestResolver) { - Assert.notNull(authorizationRequestResolver, "authorizationRequestResolver cannot be null"); - this.authorizationRequestResolver = authorizationRequestResolver; - return this; - } - - /** - * Sets the repository used for storing {@link OAuth2AuthorizationRequest}'s. - * @param authorizationRequestRepository the repository used for storing - * {@link OAuth2AuthorizationRequest}'s - * @return the {@link AuthorizationEndpointConfig} for further configuration - */ - public AuthorizationEndpointConfig authorizationRequestRepository( - AuthorizationRequestRepository authorizationRequestRepository) { - Assert.notNull(authorizationRequestRepository, "authorizationRequestRepository cannot be null"); - this.authorizationRequestRepository = authorizationRequestRepository; - return this; - } - - /** - * Returns the {@link OAuth2LoginConfigurer} for further configuration. - * @return the {@link OAuth2LoginConfigurer} - */ - public OAuth2LoginConfigurer and() { - return OAuth2LoginConfigurer.this; - } - - } - /** * Returns the {@link TokenEndpointConfig} for configuring the Authorization Server's * Token Endpoint. @@ -305,41 +242,6 @@ public final class OAuth2LoginConfigurer> return this; } - /** - * Configuration options for the Authorization Server's Token Endpoint. - */ - public final class TokenEndpointConfig { - - private OAuth2AccessTokenResponseClient accessTokenResponseClient; - - private TokenEndpointConfig() { - } - - /** - * Sets the client used for requesting the access token credential from the Token - * Endpoint. - * @param accessTokenResponseClient the client used for requesting the access - * token credential from the Token Endpoint - * @return the {@link TokenEndpointConfig} for further configuration - */ - public TokenEndpointConfig accessTokenResponseClient( - OAuth2AccessTokenResponseClient accessTokenResponseClient) { - - Assert.notNull(accessTokenResponseClient, "accessTokenResponseClient cannot be null"); - this.accessTokenResponseClient = accessTokenResponseClient; - return this; - } - - /** - * Returns the {@link OAuth2LoginConfigurer} for further configuration. - * @return the {@link OAuth2LoginConfigurer} - */ - public OAuth2LoginConfigurer and() { - return OAuth2LoginConfigurer.this; - } - - } - /** * Returns the {@link RedirectionEndpointConfig} for configuring the Client's * Redirection Endpoint. @@ -361,38 +263,6 @@ public final class OAuth2LoginConfigurer> return this; } - /** - * Configuration options for the Client's Redirection Endpoint. - */ - public final class RedirectionEndpointConfig { - - private String authorizationResponseBaseUri; - - private RedirectionEndpointConfig() { - } - - /** - * Sets the {@code URI} where the authorization response will be processed. - * @param authorizationResponseBaseUri the {@code URI} where the authorization - * response will be processed - * @return the {@link RedirectionEndpointConfig} for further configuration - */ - public RedirectionEndpointConfig baseUri(String authorizationResponseBaseUri) { - Assert.hasText(authorizationResponseBaseUri, "authorizationResponseBaseUri cannot be empty"); - this.authorizationResponseBaseUri = authorizationResponseBaseUri; - return this; - } - - /** - * Returns the {@link OAuth2LoginConfigurer} for further configuration. - * @return the {@link OAuth2LoginConfigurer} - */ - public OAuth2LoginConfigurer and() { - return OAuth2LoginConfigurer.this; - } - - } - /** * Returns the {@link UserInfoEndpointConfig} for configuring the Authorization * Server's UserInfo Endpoint. @@ -413,87 +283,6 @@ public final class OAuth2LoginConfigurer> return this; } - /** - * Configuration options for the Authorization Server's UserInfo Endpoint. - */ - public final class UserInfoEndpointConfig { - - private OAuth2UserService userService; - - private OAuth2UserService oidcUserService; - - private Map> customUserTypes = new HashMap<>(); - - private UserInfoEndpointConfig() { - } - - /** - * Sets the OAuth 2.0 service used for obtaining the user attributes of the - * End-User from the UserInfo Endpoint. - * @param userService the OAuth 2.0 service used for obtaining the user attributes - * of the End-User from the UserInfo Endpoint - * @return the {@link UserInfoEndpointConfig} for further configuration - */ - public UserInfoEndpointConfig userService(OAuth2UserService userService) { - Assert.notNull(userService, "userService cannot be null"); - this.userService = userService; - return this; - } - - /** - * Sets the OpenID Connect 1.0 service used for obtaining the user attributes of - * the End-User from the UserInfo Endpoint. - * @param oidcUserService the OpenID Connect 1.0 service used for obtaining the - * user attributes of the End-User from the UserInfo Endpoint - * @return the {@link UserInfoEndpointConfig} for further configuration - */ - public UserInfoEndpointConfig oidcUserService(OAuth2UserService oidcUserService) { - Assert.notNull(oidcUserService, "oidcUserService cannot be null"); - this.oidcUserService = oidcUserService; - return this; - } - - /** - * Sets a custom {@link OAuth2User} type and associates it to the provided client - * {@link ClientRegistration#getRegistrationId() registration identifier}. - * @deprecated See {@link CustomUserTypesOAuth2UserService} for alternative usage. - * @param customUserType a custom {@link OAuth2User} type - * @param clientRegistrationId the client registration identifier - * @return the {@link UserInfoEndpointConfig} for further configuration - */ - @Deprecated - public UserInfoEndpointConfig customUserType(Class customUserType, - String clientRegistrationId) { - Assert.notNull(customUserType, "customUserType cannot be null"); - Assert.hasText(clientRegistrationId, "clientRegistrationId cannot be empty"); - this.customUserTypes.put(clientRegistrationId, customUserType); - return this; - } - - /** - * Sets the {@link GrantedAuthoritiesMapper} used for mapping - * {@link OAuth2User#getAuthorities()}. - * @param userAuthoritiesMapper the {@link GrantedAuthoritiesMapper} used for - * mapping the user's authorities - * @return the {@link UserInfoEndpointConfig} for further configuration - */ - public UserInfoEndpointConfig userAuthoritiesMapper(GrantedAuthoritiesMapper userAuthoritiesMapper) { - Assert.notNull(userAuthoritiesMapper, "userAuthoritiesMapper cannot be null"); - OAuth2LoginConfigurer.this.getBuilder().setSharedObject(GrantedAuthoritiesMapper.class, - userAuthoritiesMapper); - return this; - } - - /** - * Returns the {@link OAuth2LoginConfigurer} for further configuration. - * @return the {@link OAuth2LoginConfigurer} - */ - public OAuth2LoginConfigurer and() { - return OAuth2LoginConfigurer.this; - } - - } - @Override public void init(B http) throws Exception { OAuth2LoginAuthenticationFilter authenticationFilter = new OAuth2LoginAuthenticationFilter( @@ -740,6 +529,217 @@ public final class OAuth2LoginConfigurer> return loginEntryPoint; } + /** + * Configuration options for the Authorization Server's Authorization Endpoint. + */ + public final class AuthorizationEndpointConfig { + + private String authorizationRequestBaseUri; + + private OAuth2AuthorizationRequestResolver authorizationRequestResolver; + + private AuthorizationRequestRepository authorizationRequestRepository; + + private AuthorizationEndpointConfig() { + } + + /** + * Sets the base {@code URI} used for authorization requests. + * @param authorizationRequestBaseUri the base {@code URI} used for authorization + * requests + * @return the {@link AuthorizationEndpointConfig} for further configuration + */ + public AuthorizationEndpointConfig baseUri(String authorizationRequestBaseUri) { + Assert.hasText(authorizationRequestBaseUri, "authorizationRequestBaseUri cannot be empty"); + this.authorizationRequestBaseUri = authorizationRequestBaseUri; + return this; + } + + /** + * Sets the resolver used for resolving {@link OAuth2AuthorizationRequest}'s. + * @param authorizationRequestResolver the resolver used for resolving + * {@link OAuth2AuthorizationRequest}'s + * @return the {@link AuthorizationEndpointConfig} for further configuration + * @since 5.1 + */ + public AuthorizationEndpointConfig authorizationRequestResolver( + OAuth2AuthorizationRequestResolver authorizationRequestResolver) { + Assert.notNull(authorizationRequestResolver, "authorizationRequestResolver cannot be null"); + this.authorizationRequestResolver = authorizationRequestResolver; + return this; + } + + /** + * Sets the repository used for storing {@link OAuth2AuthorizationRequest}'s. + * @param authorizationRequestRepository the repository used for storing + * {@link OAuth2AuthorizationRequest}'s + * @return the {@link AuthorizationEndpointConfig} for further configuration + */ + public AuthorizationEndpointConfig authorizationRequestRepository( + AuthorizationRequestRepository authorizationRequestRepository) { + Assert.notNull(authorizationRequestRepository, "authorizationRequestRepository cannot be null"); + this.authorizationRequestRepository = authorizationRequestRepository; + return this; + } + + /** + * Returns the {@link OAuth2LoginConfigurer} for further configuration. + * @return the {@link OAuth2LoginConfigurer} + */ + public OAuth2LoginConfigurer and() { + return OAuth2LoginConfigurer.this; + } + + } + + /** + * Configuration options for the Authorization Server's Token Endpoint. + */ + public final class TokenEndpointConfig { + + private OAuth2AccessTokenResponseClient accessTokenResponseClient; + + private TokenEndpointConfig() { + } + + /** + * Sets the client used for requesting the access token credential from the Token + * Endpoint. + * @param accessTokenResponseClient the client used for requesting the access + * token credential from the Token Endpoint + * @return the {@link TokenEndpointConfig} for further configuration + */ + public TokenEndpointConfig accessTokenResponseClient( + OAuth2AccessTokenResponseClient accessTokenResponseClient) { + + Assert.notNull(accessTokenResponseClient, "accessTokenResponseClient cannot be null"); + this.accessTokenResponseClient = accessTokenResponseClient; + return this; + } + + /** + * Returns the {@link OAuth2LoginConfigurer} for further configuration. + * @return the {@link OAuth2LoginConfigurer} + */ + public OAuth2LoginConfigurer and() { + return OAuth2LoginConfigurer.this; + } + + } + + /** + * Configuration options for the Client's Redirection Endpoint. + */ + public final class RedirectionEndpointConfig { + + private String authorizationResponseBaseUri; + + private RedirectionEndpointConfig() { + } + + /** + * Sets the {@code URI} where the authorization response will be processed. + * @param authorizationResponseBaseUri the {@code URI} where the authorization + * response will be processed + * @return the {@link RedirectionEndpointConfig} for further configuration + */ + public RedirectionEndpointConfig baseUri(String authorizationResponseBaseUri) { + Assert.hasText(authorizationResponseBaseUri, "authorizationResponseBaseUri cannot be empty"); + this.authorizationResponseBaseUri = authorizationResponseBaseUri; + return this; + } + + /** + * Returns the {@link OAuth2LoginConfigurer} for further configuration. + * @return the {@link OAuth2LoginConfigurer} + */ + public OAuth2LoginConfigurer and() { + return OAuth2LoginConfigurer.this; + } + + } + + /** + * Configuration options for the Authorization Server's UserInfo Endpoint. + */ + public final class UserInfoEndpointConfig { + + private OAuth2UserService userService; + + private OAuth2UserService oidcUserService; + + private Map> customUserTypes = new HashMap<>(); + + private UserInfoEndpointConfig() { + } + + /** + * Sets the OAuth 2.0 service used for obtaining the user attributes of the + * End-User from the UserInfo Endpoint. + * @param userService the OAuth 2.0 service used for obtaining the user attributes + * of the End-User from the UserInfo Endpoint + * @return the {@link UserInfoEndpointConfig} for further configuration + */ + public UserInfoEndpointConfig userService(OAuth2UserService userService) { + Assert.notNull(userService, "userService cannot be null"); + this.userService = userService; + return this; + } + + /** + * Sets the OpenID Connect 1.0 service used for obtaining the user attributes of + * the End-User from the UserInfo Endpoint. + * @param oidcUserService the OpenID Connect 1.0 service used for obtaining the + * user attributes of the End-User from the UserInfo Endpoint + * @return the {@link UserInfoEndpointConfig} for further configuration + */ + public UserInfoEndpointConfig oidcUserService(OAuth2UserService oidcUserService) { + Assert.notNull(oidcUserService, "oidcUserService cannot be null"); + this.oidcUserService = oidcUserService; + return this; + } + + /** + * Sets a custom {@link OAuth2User} type and associates it to the provided client + * {@link ClientRegistration#getRegistrationId() registration identifier}. + * @deprecated See {@link CustomUserTypesOAuth2UserService} for alternative usage. + * @param customUserType a custom {@link OAuth2User} type + * @param clientRegistrationId the client registration identifier + * @return the {@link UserInfoEndpointConfig} for further configuration + */ + @Deprecated + public UserInfoEndpointConfig customUserType(Class customUserType, + String clientRegistrationId) { + Assert.notNull(customUserType, "customUserType cannot be null"); + Assert.hasText(clientRegistrationId, "clientRegistrationId cannot be empty"); + this.customUserTypes.put(clientRegistrationId, customUserType); + return this; + } + + /** + * Sets the {@link GrantedAuthoritiesMapper} used for mapping + * {@link OAuth2User#getAuthorities()}. + * @param userAuthoritiesMapper the {@link GrantedAuthoritiesMapper} used for + * mapping the user's authorities + * @return the {@link UserInfoEndpointConfig} for further configuration + */ + public UserInfoEndpointConfig userAuthoritiesMapper(GrantedAuthoritiesMapper userAuthoritiesMapper) { + Assert.notNull(userAuthoritiesMapper, "userAuthoritiesMapper cannot be null"); + OAuth2LoginConfigurer.this.getBuilder().setSharedObject(GrantedAuthoritiesMapper.class, + userAuthoritiesMapper); + return this; + } + + /** + * Returns the {@link OAuth2LoginConfigurer} for further configuration. + * @return the {@link OAuth2LoginConfigurer} + */ + public OAuth2LoginConfigurer and() { + return OAuth2LoginConfigurer.this; + } + + } + private static class OidcAuthenticationRequestChecker implements AuthenticationProvider { @Override diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java index f22c68ab83..9b45741903 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java @@ -277,6 +277,70 @@ public final class OAuth2ResourceServerConfigurer exceptionHandling = http.getConfigurer(ExceptionHandlingConfigurer.class); + if (exceptionHandling == null) { + return; + } + + exceptionHandling.defaultAccessDeniedHandlerFor(this.accessDeniedHandler, this.requestMatcher); + } + + private void registerDefaultEntryPoint(H http) { + ExceptionHandlingConfigurer exceptionHandling = http.getConfigurer(ExceptionHandlingConfigurer.class); + if (exceptionHandling == null) { + return; + } + + exceptionHandling.defaultAuthenticationEntryPointFor(this.authenticationEntryPoint, this.requestMatcher); + } + + private void registerDefaultCsrfOverride(H http) { + CsrfConfigurer csrf = http.getConfigurer(CsrfConfigurer.class); + if (csrf == null) { + return; + } + + csrf.ignoringRequestMatchers(this.requestMatcher); + } + + AuthenticationProvider getAuthenticationProvider() { + if (this.jwtConfigurer != null) { + return this.jwtConfigurer.getAuthenticationProvider(); + } + + if (this.opaqueTokenConfigurer != null) { + return this.opaqueTokenConfigurer.getAuthenticationProvider(); + } + + return null; + } + + AuthenticationManager getAuthenticationManager(H http) { + if (this.jwtConfigurer != null) { + return this.jwtConfigurer.getAuthenticationManager(http); + } + + if (this.opaqueTokenConfigurer != null) { + return this.opaqueTokenConfigurer.getAuthenticationManager(http); + } + + return http.getSharedObject(AuthenticationManager.class); + } + + BearerTokenResolver getBearerTokenResolver() { + if (this.bearerTokenResolver == null) { + if (this.context.getBeanNamesForType(BearerTokenResolver.class).length > 0) { + this.bearerTokenResolver = this.context.getBean(BearerTokenResolver.class); + } + else { + this.bearerTokenResolver = new DefaultBearerTokenResolver(); + } + } + + return this.bearerTokenResolver; + } + public class JwtConfigurer { private final ApplicationContext context; @@ -435,70 +499,6 @@ public final class OAuth2ResourceServerConfigurer exceptionHandling = http.getConfigurer(ExceptionHandlingConfigurer.class); - if (exceptionHandling == null) { - return; - } - - exceptionHandling.defaultAccessDeniedHandlerFor(this.accessDeniedHandler, this.requestMatcher); - } - - private void registerDefaultEntryPoint(H http) { - ExceptionHandlingConfigurer exceptionHandling = http.getConfigurer(ExceptionHandlingConfigurer.class); - if (exceptionHandling == null) { - return; - } - - exceptionHandling.defaultAuthenticationEntryPointFor(this.authenticationEntryPoint, this.requestMatcher); - } - - private void registerDefaultCsrfOverride(H http) { - CsrfConfigurer csrf = http.getConfigurer(CsrfConfigurer.class); - if (csrf == null) { - return; - } - - csrf.ignoringRequestMatchers(this.requestMatcher); - } - - AuthenticationProvider getAuthenticationProvider() { - if (this.jwtConfigurer != null) { - return this.jwtConfigurer.getAuthenticationProvider(); - } - - if (this.opaqueTokenConfigurer != null) { - return this.opaqueTokenConfigurer.getAuthenticationProvider(); - } - - return null; - } - - AuthenticationManager getAuthenticationManager(H http) { - if (this.jwtConfigurer != null) { - return this.jwtConfigurer.getAuthenticationManager(http); - } - - if (this.opaqueTokenConfigurer != null) { - return this.opaqueTokenConfigurer.getAuthenticationManager(http); - } - - return http.getSharedObject(AuthenticationManager.class); - } - - BearerTokenResolver getBearerTokenResolver() { - if (this.bearerTokenResolver == null) { - if (this.context.getBeanNamesForType(BearerTokenResolver.class).length > 0) { - this.bearerTokenResolver = this.context.getBean(BearerTokenResolver.class); - } - else { - this.bearerTokenResolver = new DefaultBearerTokenResolver(); - } - } - - return this.bearerTokenResolver; - } - private static final class BearerTokenRequestMatcher implements RequestMatcher { private BearerTokenResolver bearerTokenResolver; diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/messaging/MessageSecurityMetadataSourceRegistry.java b/config/src/main/java/org/springframework/security/config/annotation/web/messaging/MessageSecurityMetadataSourceRegistry.java index 4507c9d845..ec3a1ba2b6 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/messaging/MessageSecurityMetadataSourceRegistry.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/messaging/MessageSecurityMetadataSourceRegistry.java @@ -247,6 +247,29 @@ public class MessageSecurityMetadataSourceRegistry { return !this.matcherToExpression.isEmpty(); } + private static String hasAnyRole(String... authorities) { + String anyAuthorities = StringUtils.arrayToDelimitedString(authorities, "','ROLE_"); + return "hasAnyRole('ROLE_" + anyAuthorities + "')"; + } + + private static String hasRole(String role) { + Assert.notNull(role, "role cannot be null"); + if (role.startsWith("ROLE_")) { + throw new IllegalArgumentException( + "role should not start with 'ROLE_' since it is automatically inserted. Got '" + role + "'"); + } + return "hasRole('ROLE_" + role + "')"; + } + + private static String hasAuthority(String authority) { + return "hasAuthority('" + authority + "')"; + } + + private static String hasAnyAuthority(String... authorities) { + String anyAuthorities = StringUtils.arrayToDelimitedString(authorities, "','"); + return "hasAnyAuthority('" + anyAuthorities + "')"; + } + /** * Represents the security constraint to be applied to the {@link MessageMatcher} * instances. @@ -386,29 +409,6 @@ public class MessageSecurityMetadataSourceRegistry { } - private static String hasAnyRole(String... authorities) { - String anyAuthorities = StringUtils.arrayToDelimitedString(authorities, "','ROLE_"); - return "hasAnyRole('ROLE_" + anyAuthorities + "')"; - } - - private static String hasRole(String role) { - Assert.notNull(role, "role cannot be null"); - if (role.startsWith("ROLE_")) { - throw new IllegalArgumentException( - "role should not start with 'ROLE_' since it is automatically inserted. Got '" + role + "'"); - } - return "hasRole('ROLE_" + role + "')"; - } - - private static String hasAuthority(String authority) { - return "hasAuthority('" + authority + "')"; - } - - private static String hasAnyAuthority(String... authorities) { - String anyAuthorities = StringUtils.arrayToDelimitedString(authorities, "','"); - return "hasAnyAuthority('" + anyAuthorities + "')"; - } - private final static class PreBuiltMatcherBuilder implements MatcherBuilder { private MessageMatcher matcher; diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurer.java index 25bec814d6..4e2334e98e 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurer.java @@ -186,25 +186,6 @@ public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends A protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) { } - private static class WebSocketMessageSecurityMetadataSourceRegistry extends MessageSecurityMetadataSourceRegistry { - - @Override - public MessageSecurityMetadataSource createMetadataSource() { - return super.createMetadataSource(); - } - - @Override - protected boolean containsMapping() { - return super.containsMapping(); - } - - @Override - protected boolean isSimpDestPathMatcherConfigured() { - return super.isSimpDestPathMatcherConfigured(); - } - - } - @Autowired public void setApplicationContext(ApplicationContext context) { this.context = context; @@ -283,4 +264,23 @@ public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends A } } + private static class WebSocketMessageSecurityMetadataSourceRegistry extends MessageSecurityMetadataSourceRegistry { + + @Override + public MessageSecurityMetadataSource createMetadataSource() { + return super.createMetadataSource(); + } + + @Override + protected boolean containsMapping() { + return super.containsMapping(); + } + + @Override + protected boolean isSimpDestPathMatcherConfigured() { + return super.isSimpDestPathMatcherConfigured(); + } + + } + } diff --git a/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java b/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java index 759228c707..5d87cbfa9e 100644 --- a/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java +++ b/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java @@ -296,6 +296,9 @@ public class ServerHttpSecurity { private AnonymousSpec anonymous; + protected ServerHttpSecurity() { + } + /** * The ServerExchangeMatcher that determines which requests apply to this HttpSecurity * instance. @@ -624,70 +627,6 @@ public class ServerHttpSecurity { return this; } - /** - * Configures CORS support within Spring Security. This ensures that the - * {@link CorsWebFilter} is place in the correct order. - */ - public final class CorsSpec { - - private CorsWebFilter corsFilter; - - private CorsSpec() { - } - - /** - * Configures the {@link CorsConfigurationSource} to be used - * @param source the source to use - * @return the {@link CorsSpec} for additional configuration - */ - public CorsSpec configurationSource(CorsConfigurationSource source) { - this.corsFilter = new CorsWebFilter(source); - return this; - } - - /** - * Disables CORS support within Spring Security. - * @return the {@link ServerHttpSecurity} to continue configuring - */ - public ServerHttpSecurity disable() { - ServerHttpSecurity.this.cors = null; - return ServerHttpSecurity.this; - } - - /** - * Allows method chaining to continue configuring the {@link ServerHttpSecurity} - * @return the {@link ServerHttpSecurity} to continue configuring - */ - public ServerHttpSecurity and() { - return ServerHttpSecurity.this; - } - - protected void configure(ServerHttpSecurity http) { - CorsWebFilter corsFilter = getCorsFilter(); - if (corsFilter != null) { - http.addFilterAt(this.corsFilter, SecurityWebFiltersOrder.CORS); - } - } - - private CorsWebFilter getCorsFilter() { - if (this.corsFilter != null) { - return this.corsFilter; - } - - CorsConfigurationSource source = getBeanOrNull(CorsConfigurationSource.class); - if (source == null) { - return null; - } - CorsProcessor processor = getBeanOrNull(CorsProcessor.class); - if (processor == null) { - processor = new DefaultCorsProcessor(); - } - this.corsFilter = new CorsWebFilter(source, processor); - return this.corsFilter; - } - - } - /** * Configures HTTP Basic authentication. An example configuration is provided below: * @@ -867,67 +806,6 @@ public class ServerHttpSecurity { return this; } - /** - * Configures X509 authentication - * - * @author Alexey Nesterov - * @since 5.2 - * @see #x509() - */ - public final class X509Spec { - - private X509PrincipalExtractor principalExtractor; - - private ReactiveAuthenticationManager authenticationManager; - - private X509Spec() { - } - - public X509Spec principalExtractor(X509PrincipalExtractor principalExtractor) { - this.principalExtractor = principalExtractor; - return this; - } - - public X509Spec authenticationManager(ReactiveAuthenticationManager authenticationManager) { - this.authenticationManager = authenticationManager; - return this; - } - - public ServerHttpSecurity and() { - return ServerHttpSecurity.this; - } - - protected void configure(ServerHttpSecurity http) { - ReactiveAuthenticationManager authenticationManager = getAuthenticationManager(); - X509PrincipalExtractor principalExtractor = getPrincipalExtractor(); - - AuthenticationWebFilter filter = new AuthenticationWebFilter(authenticationManager); - filter.setServerAuthenticationConverter(new ServerX509AuthenticationConverter(principalExtractor)); - http.addFilterAt(filter, SecurityWebFiltersOrder.AUTHENTICATION); - } - - private X509PrincipalExtractor getPrincipalExtractor() { - if (this.principalExtractor != null) { - return this.principalExtractor; - } - - return new SubjectDnX509PrincipalExtractor(); - } - - private ReactiveAuthenticationManager getAuthenticationManager() { - if (this.authenticationManager != null) { - return this.authenticationManager; - } - - ReactiveUserDetailsService userDetailsService = getBean(ReactiveUserDetailsService.class); - ReactivePreAuthenticatedAuthenticationManager authenticationManager = new ReactivePreAuthenticatedAuthenticationManager( - userDetailsService); - - return authenticationManager; - } - - } - /** * Configures authentication support using an OAuth 2.0 and/or OpenID Connect 1.0 * Provider. @@ -981,408 +859,6 @@ public class ServerHttpSecurity { return this; } - public final class OAuth2LoginSpec { - - private ReactiveClientRegistrationRepository clientRegistrationRepository; - - private ServerOAuth2AuthorizedClientRepository authorizedClientRepository; - - private ServerAuthorizationRequestRepository authorizationRequestRepository; - - private ReactiveAuthenticationManager authenticationManager; - - private ServerSecurityContextRepository securityContextRepository; - - private ServerAuthenticationConverter authenticationConverter; - - private ServerOAuth2AuthorizationRequestResolver authorizationRequestResolver; - - private ServerWebExchangeMatcher authenticationMatcher; - - private ServerAuthenticationSuccessHandler authenticationSuccessHandler; - - private ServerAuthenticationFailureHandler authenticationFailureHandler; - - private OAuth2LoginSpec() { - } - - /** - * Configures the {@link ReactiveAuthenticationManager} to use. The default is - * {@link OAuth2AuthorizationCodeReactiveAuthenticationManager} - * @param authenticationManager the manager to use - * @return the {@link OAuth2LoginSpec} to customize - */ - public OAuth2LoginSpec authenticationManager(ReactiveAuthenticationManager authenticationManager) { - this.authenticationManager = authenticationManager; - return this; - } - - /** - * The {@link ServerSecurityContextRepository} used to save the - * {@code Authentication}. Defaults to - * {@link WebSessionServerSecurityContextRepository}. - * @param securityContextRepository the repository to use - * @return the {@link OAuth2LoginSpec} to continue configuring - * @since 5.2 - */ - public OAuth2LoginSpec securityContextRepository(ServerSecurityContextRepository securityContextRepository) { - this.securityContextRepository = securityContextRepository; - return this; - } - - /** - * The {@link ServerAuthenticationSuccessHandler} used after authentication - * success. Defaults to {@link RedirectServerAuthenticationSuccessHandler} - * redirecting to "/". - * @param authenticationSuccessHandler the success handler to use - * @return the {@link OAuth2LoginSpec} to customize - * @since 5.2 - */ - public OAuth2LoginSpec authenticationSuccessHandler( - ServerAuthenticationSuccessHandler authenticationSuccessHandler) { - Assert.notNull(authenticationSuccessHandler, "authenticationSuccessHandler cannot be null"); - this.authenticationSuccessHandler = authenticationSuccessHandler; - return this; - } - - /** - * The {@link ServerAuthenticationFailureHandler} used after authentication - * failure. Defaults to {@link RedirectServerAuthenticationFailureHandler} - * redirecting to "/login?error". - * @param authenticationFailureHandler the failure handler to use - * @return the {@link OAuth2LoginSpec} to customize - * @since 5.2 - */ - public OAuth2LoginSpec authenticationFailureHandler( - ServerAuthenticationFailureHandler authenticationFailureHandler) { - Assert.notNull(authenticationFailureHandler, "authenticationFailureHandler cannot be null"); - this.authenticationFailureHandler = authenticationFailureHandler; - return this; - } - - /** - * Gets the {@link ReactiveAuthenticationManager} to use. First tries an - * explicitly configured manager, and defaults to - * {@link OAuth2AuthorizationCodeReactiveAuthenticationManager} - * @return the {@link ReactiveAuthenticationManager} to use - */ - private ReactiveAuthenticationManager getAuthenticationManager() { - if (this.authenticationManager == null) { - this.authenticationManager = createDefault(); - } - return this.authenticationManager; - } - - private ReactiveAuthenticationManager createDefault() { - ReactiveOAuth2AccessTokenResponseClient client = getAccessTokenResponseClient(); - OAuth2LoginReactiveAuthenticationManager oauth2Manager = new OAuth2LoginReactiveAuthenticationManager( - client, getOauth2UserService()); - GrantedAuthoritiesMapper authoritiesMapper = getBeanOrNull(GrantedAuthoritiesMapper.class); - if (authoritiesMapper != null) { - oauth2Manager.setAuthoritiesMapper(authoritiesMapper); - } - boolean oidcAuthenticationProviderEnabled = ClassUtils - .isPresent("org.springframework.security.oauth2.jwt.JwtDecoder", this.getClass().getClassLoader()); - if (oidcAuthenticationProviderEnabled) { - OidcAuthorizationCodeReactiveAuthenticationManager oidc = new OidcAuthorizationCodeReactiveAuthenticationManager( - client, getOidcUserService()); - ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveJwtDecoderFactory.class, - ClientRegistration.class); - ReactiveJwtDecoderFactory jwtDecoderFactory = getBeanOrNull(type); - if (jwtDecoderFactory != null) { - oidc.setJwtDecoderFactory(jwtDecoderFactory); - } - if (authoritiesMapper != null) { - oidc.setAuthoritiesMapper(authoritiesMapper); - } - return new DelegatingReactiveAuthenticationManager(oidc, oauth2Manager); - } - return oauth2Manager; - } - - /** - * Sets the converter to use - * @param authenticationConverter the converter to use - * @return the {@link OAuth2LoginSpec} to customize - */ - public OAuth2LoginSpec authenticationConverter(ServerAuthenticationConverter authenticationConverter) { - this.authenticationConverter = authenticationConverter; - return this; - } - - private ServerAuthenticationConverter getAuthenticationConverter( - ReactiveClientRegistrationRepository clientRegistrationRepository) { - if (this.authenticationConverter == null) { - ServerOAuth2AuthorizationCodeAuthenticationTokenConverter delegate = new ServerOAuth2AuthorizationCodeAuthenticationTokenConverter( - clientRegistrationRepository); - delegate.setAuthorizationRequestRepository(getAuthorizationRequestRepository()); - ServerAuthenticationConverter authenticationConverter = exchange -> delegate.convert(exchange) - .onErrorMap(OAuth2AuthorizationException.class, - e -> new OAuth2AuthenticationException(e.getError(), e.getError().toString())); - this.authenticationConverter = authenticationConverter; - return authenticationConverter; - } - return this.authenticationConverter; - } - - public OAuth2LoginSpec clientRegistrationRepository( - ReactiveClientRegistrationRepository clientRegistrationRepository) { - this.clientRegistrationRepository = clientRegistrationRepository; - return this; - } - - public OAuth2LoginSpec authorizedClientService(ReactiveOAuth2AuthorizedClientService authorizedClientService) { - this.authorizedClientRepository = new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository( - authorizedClientService); - return this; - } - - public OAuth2LoginSpec authorizedClientRepository( - ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { - this.authorizedClientRepository = authorizedClientRepository; - return this; - } - - /** - * Sets the repository to use for storing {@link OAuth2AuthorizationRequest}'s. - * @param authorizationRequestRepository the repository to use for storing - * {@link OAuth2AuthorizationRequest}'s - * @return the {@link OAuth2LoginSpec} for further configuration - * @since 5.2 - */ - public OAuth2LoginSpec authorizationRequestRepository( - ServerAuthorizationRequestRepository authorizationRequestRepository) { - this.authorizationRequestRepository = authorizationRequestRepository; - return this; - } - - /** - * Sets the resolver used for resolving {@link OAuth2AuthorizationRequest}'s. - * @param authorizationRequestResolver the resolver used for resolving - * {@link OAuth2AuthorizationRequest}'s - * @return the {@link OAuth2LoginSpec} for further configuration - * @since 5.2 - */ - public OAuth2LoginSpec authorizationRequestResolver( - ServerOAuth2AuthorizationRequestResolver authorizationRequestResolver) { - this.authorizationRequestResolver = authorizationRequestResolver; - return this; - } - - /** - * Sets the {@link ServerWebExchangeMatcher matcher} used for determining if the - * request is an authentication request. - * @param authenticationMatcher the {@link ServerWebExchangeMatcher matcher} used - * for determining if the request is an authentication request - * @return the {@link OAuth2LoginSpec} for further configuration - * @since 5.2 - */ - public OAuth2LoginSpec authenticationMatcher(ServerWebExchangeMatcher authenticationMatcher) { - this.authenticationMatcher = authenticationMatcher; - return this; - } - - private ServerWebExchangeMatcher getAuthenticationMatcher() { - if (this.authenticationMatcher == null) { - this.authenticationMatcher = createAttemptAuthenticationRequestMatcher(); - } - return this.authenticationMatcher; - } - - /** - * Allows method chaining to continue configuring the {@link ServerHttpSecurity} - * @return the {@link ServerHttpSecurity} to continue configuring - */ - public ServerHttpSecurity and() { - return ServerHttpSecurity.this; - } - - protected void configure(ServerHttpSecurity http) { - ReactiveClientRegistrationRepository clientRegistrationRepository = getClientRegistrationRepository(); - ServerOAuth2AuthorizedClientRepository authorizedClientRepository = getAuthorizedClientRepository(); - OAuth2AuthorizationRequestRedirectWebFilter oauthRedirectFilter = getRedirectWebFilter(); - ServerAuthorizationRequestRepository authorizationRequestRepository = getAuthorizationRequestRepository(); - oauthRedirectFilter.setAuthorizationRequestRepository(authorizationRequestRepository); - oauthRedirectFilter.setRequestCache(http.requestCache.requestCache); - - ReactiveAuthenticationManager manager = getAuthenticationManager(); - - AuthenticationWebFilter authenticationFilter = new OAuth2LoginAuthenticationWebFilter(manager, - authorizedClientRepository); - authenticationFilter.setRequiresAuthenticationMatcher(getAuthenticationMatcher()); - authenticationFilter - .setServerAuthenticationConverter(getAuthenticationConverter(clientRegistrationRepository)); - - authenticationFilter.setAuthenticationSuccessHandler(getAuthenticationSuccessHandler(http)); - authenticationFilter.setAuthenticationFailureHandler(getAuthenticationFailureHandler()); - authenticationFilter.setSecurityContextRepository(this.securityContextRepository); - - setDefaultEntryPoints(http); - - http.addFilterAt(oauthRedirectFilter, SecurityWebFiltersOrder.HTTP_BASIC); - http.addFilterAt(authenticationFilter, SecurityWebFiltersOrder.AUTHENTICATION); - } - - private void setDefaultEntryPoints(ServerHttpSecurity http) { - String defaultLoginPage = "/login"; - Map urlToText = http.oauth2Login.getLinks(); - String providerLoginPage = null; - if (urlToText.size() == 1) { - providerLoginPage = urlToText.keySet().iterator().next(); - } - - MediaTypeServerWebExchangeMatcher htmlMatcher = new MediaTypeServerWebExchangeMatcher( - MediaType.APPLICATION_XHTML_XML, new MediaType("image", "*"), MediaType.TEXT_HTML, - MediaType.TEXT_PLAIN); - htmlMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL)); - - ServerWebExchangeMatcher xhrMatcher = exchange -> { - if (exchange.getRequest().getHeaders().getOrEmpty("X-Requested-With").contains("XMLHttpRequest")) { - return ServerWebExchangeMatcher.MatchResult.match(); - } - return ServerWebExchangeMatcher.MatchResult.notMatch(); - }; - ServerWebExchangeMatcher notXhrMatcher = new NegatedServerWebExchangeMatcher(xhrMatcher); - - ServerWebExchangeMatcher defaultEntryPointMatcher = new AndServerWebExchangeMatcher(notXhrMatcher, - htmlMatcher); - - if (providerLoginPage != null) { - ServerWebExchangeMatcher loginPageMatcher = new PathPatternParserServerWebExchangeMatcher( - defaultLoginPage); - ServerWebExchangeMatcher faviconMatcher = new PathPatternParserServerWebExchangeMatcher("/favicon.ico"); - ServerWebExchangeMatcher defaultLoginPageMatcher = new AndServerWebExchangeMatcher( - new OrServerWebExchangeMatcher(loginPageMatcher, faviconMatcher), defaultEntryPointMatcher); - - ServerWebExchangeMatcher matcher = new AndServerWebExchangeMatcher(notXhrMatcher, - new NegatedServerWebExchangeMatcher(defaultLoginPageMatcher)); - RedirectServerAuthenticationEntryPoint entryPoint = new RedirectServerAuthenticationEntryPoint( - providerLoginPage); - entryPoint.setRequestCache(http.requestCache.requestCache); - http.defaultEntryPoints.add(new DelegateEntry(matcher, entryPoint)); - } - - RedirectServerAuthenticationEntryPoint defaultEntryPoint = new RedirectServerAuthenticationEntryPoint( - defaultLoginPage); - defaultEntryPoint.setRequestCache(http.requestCache.requestCache); - http.defaultEntryPoints.add(new DelegateEntry(defaultEntryPointMatcher, defaultEntryPoint)); - } - - private ServerAuthenticationSuccessHandler getAuthenticationSuccessHandler(ServerHttpSecurity http) { - if (this.authenticationSuccessHandler == null) { - RedirectServerAuthenticationSuccessHandler handler = new RedirectServerAuthenticationSuccessHandler(); - handler.setRequestCache(http.requestCache.requestCache); - this.authenticationSuccessHandler = handler; - } - return this.authenticationSuccessHandler; - } - - private ServerAuthenticationFailureHandler getAuthenticationFailureHandler() { - if (this.authenticationFailureHandler == null) { - this.authenticationFailureHandler = new RedirectServerAuthenticationFailureHandler("/login?error"); - } - return this.authenticationFailureHandler; - } - - private ServerWebExchangeMatcher createAttemptAuthenticationRequestMatcher() { - return new PathPatternParserServerWebExchangeMatcher("/login/oauth2/code/{registrationId}"); - } - - private ReactiveOAuth2UserService getOidcUserService() { - ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveOAuth2UserService.class, - OidcUserRequest.class, OidcUser.class); - ReactiveOAuth2UserService bean = getBeanOrNull(type); - if (bean == null) { - return new OidcReactiveOAuth2UserService(); - } - - return bean; - } - - private ReactiveOAuth2UserService getOauth2UserService() { - ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveOAuth2UserService.class, - OAuth2UserRequest.class, OAuth2User.class); - ReactiveOAuth2UserService bean = getBeanOrNull(type); - if (bean == null) { - return new DefaultReactiveOAuth2UserService(); - } - - return bean; - } - - private Map getLinks() { - Iterable registrations = getBeanOrNull( - ResolvableType.forClassWithGenerics(Iterable.class, ClientRegistration.class)); - if (registrations == null) { - return Collections.emptyMap(); - } - Map result = new HashMap<>(); - registrations.iterator().forEachRemaining( - r -> result.put("/oauth2/authorization/" + r.getRegistrationId(), r.getClientName())); - return result; - } - - private ReactiveOAuth2AccessTokenResponseClient getAccessTokenResponseClient() { - ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveOAuth2AccessTokenResponseClient.class, - OAuth2AuthorizationCodeGrantRequest.class); - ReactiveOAuth2AccessTokenResponseClient bean = getBeanOrNull(type); - if (bean == null) { - return new WebClientReactiveAuthorizationCodeTokenResponseClient(); - } - return bean; - } - - private ReactiveClientRegistrationRepository getClientRegistrationRepository() { - if (this.clientRegistrationRepository == null) { - this.clientRegistrationRepository = getBeanOrNull(ReactiveClientRegistrationRepository.class); - } - return this.clientRegistrationRepository; - } - - private OAuth2AuthorizationRequestRedirectWebFilter getRedirectWebFilter() { - OAuth2AuthorizationRequestRedirectWebFilter oauthRedirectFilter; - if (this.authorizationRequestResolver == null) { - oauthRedirectFilter = new OAuth2AuthorizationRequestRedirectWebFilter( - getClientRegistrationRepository()); - } - else { - oauthRedirectFilter = new OAuth2AuthorizationRequestRedirectWebFilter( - this.authorizationRequestResolver); - } - return oauthRedirectFilter; - } - - private ServerOAuth2AuthorizedClientRepository getAuthorizedClientRepository() { - ServerOAuth2AuthorizedClientRepository result = this.authorizedClientRepository; - if (result == null) { - result = getBeanOrNull(ServerOAuth2AuthorizedClientRepository.class); - } - if (result == null) { - ReactiveOAuth2AuthorizedClientService authorizedClientService = getAuthorizedClientService(); - if (authorizedClientService != null) { - result = new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(authorizedClientService); - } - } - return result; - } - - private ServerAuthorizationRequestRepository getAuthorizationRequestRepository() { - if (this.authorizationRequestRepository == null) { - this.authorizationRequestRepository = new WebSessionOAuth2ServerAuthorizationRequestRepository(); - } - return this.authorizationRequestRepository; - } - - private ReactiveOAuth2AuthorizedClientService getAuthorizedClientService() { - ReactiveOAuth2AuthorizedClientService service = getBeanOrNull(ReactiveOAuth2AuthorizedClientService.class); - if (service == null) { - service = new InMemoryReactiveOAuth2AuthorizedClientService(getClientRegistrationRepository()); - } - return service; - } - - } - /** * Configures the OAuth2 client. * @@ -1434,172 +910,6 @@ public class ServerHttpSecurity { return this; } - public final class OAuth2ClientSpec { - - private ReactiveClientRegistrationRepository clientRegistrationRepository; - - private ServerAuthenticationConverter authenticationConverter; - - private ServerOAuth2AuthorizedClientRepository authorizedClientRepository; - - private ReactiveAuthenticationManager authenticationManager; - - private ServerAuthorizationRequestRepository authorizationRequestRepository; - - private OAuth2ClientSpec() { - } - - /** - * Sets the converter to use - * @param authenticationConverter the converter to use - * @return the {@link OAuth2ClientSpec} to customize - */ - public OAuth2ClientSpec authenticationConverter(ServerAuthenticationConverter authenticationConverter) { - this.authenticationConverter = authenticationConverter; - return this; - } - - private ServerAuthenticationConverter getAuthenticationConverter() { - if (this.authenticationConverter == null) { - ServerOAuth2AuthorizationCodeAuthenticationTokenConverter authenticationConverter = new ServerOAuth2AuthorizationCodeAuthenticationTokenConverter( - getClientRegistrationRepository()); - authenticationConverter.setAuthorizationRequestRepository(getAuthorizationRequestRepository()); - this.authenticationConverter = authenticationConverter; - } - return this.authenticationConverter; - } - - /** - * Configures the {@link ReactiveAuthenticationManager} to use. The default is - * {@link OAuth2AuthorizationCodeReactiveAuthenticationManager} - * @param authenticationManager the manager to use - * @return the {@link OAuth2ClientSpec} to customize - */ - public OAuth2ClientSpec authenticationManager(ReactiveAuthenticationManager authenticationManager) { - this.authenticationManager = authenticationManager; - return this; - } - - /** - * Gets the {@link ReactiveAuthenticationManager} to use. First tries an - * explicitly configured manager, and defaults to - * {@link OAuth2AuthorizationCodeReactiveAuthenticationManager} - * @return the {@link ReactiveAuthenticationManager} to use - */ - private ReactiveAuthenticationManager getAuthenticationManager() { - if (this.authenticationManager == null) { - this.authenticationManager = new OAuth2AuthorizationCodeReactiveAuthenticationManager( - new WebClientReactiveAuthorizationCodeTokenResponseClient()); - } - return this.authenticationManager; - } - - /** - * Configures the {@link ReactiveClientRegistrationRepository}. Default is to look - * the value up as a Bean. - * @param clientRegistrationRepository the repository to use - * @return the {@link OAuth2ClientSpec} to customize - */ - public OAuth2ClientSpec clientRegistrationRepository( - ReactiveClientRegistrationRepository clientRegistrationRepository) { - this.clientRegistrationRepository = clientRegistrationRepository; - return this; - } - - /** - * Configures the {@link ReactiveClientRegistrationRepository}. Default is to look - * the value up as a Bean. - * @param authorizedClientRepository the repository to use - * @return the {@link OAuth2ClientSpec} to customize - */ - public OAuth2ClientSpec authorizedClientRepository( - ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { - this.authorizedClientRepository = authorizedClientRepository; - return this; - } - - /** - * Sets the repository to use for storing {@link OAuth2AuthorizationRequest}'s. - * @param authorizationRequestRepository the repository to use for storing - * {@link OAuth2AuthorizationRequest}'s - * @return the {@link OAuth2ClientSpec} to customize - * @since 5.2 - */ - public OAuth2ClientSpec authorizationRequestRepository( - ServerAuthorizationRequestRepository authorizationRequestRepository) { - this.authorizationRequestRepository = authorizationRequestRepository; - return this; - } - - private ServerAuthorizationRequestRepository getAuthorizationRequestRepository() { - if (this.authorizationRequestRepository == null) { - this.authorizationRequestRepository = new WebSessionOAuth2ServerAuthorizationRequestRepository(); - } - return this.authorizationRequestRepository; - } - - /** - * Allows method chaining to continue configuring the {@link ServerHttpSecurity} - * @return the {@link ServerHttpSecurity} to continue configuring - */ - public ServerHttpSecurity and() { - return ServerHttpSecurity.this; - } - - protected void configure(ServerHttpSecurity http) { - ReactiveClientRegistrationRepository clientRegistrationRepository = getClientRegistrationRepository(); - ServerOAuth2AuthorizedClientRepository authorizedClientRepository = getAuthorizedClientRepository(); - ServerAuthenticationConverter authenticationConverter = getAuthenticationConverter(); - ReactiveAuthenticationManager authenticationManager = getAuthenticationManager(); - OAuth2AuthorizationCodeGrantWebFilter codeGrantWebFilter = new OAuth2AuthorizationCodeGrantWebFilter( - authenticationManager, authenticationConverter, authorizedClientRepository); - codeGrantWebFilter.setAuthorizationRequestRepository(getAuthorizationRequestRepository()); - if (http.requestCache != null) { - codeGrantWebFilter.setRequestCache(http.requestCache.requestCache); - } - - OAuth2AuthorizationRequestRedirectWebFilter oauthRedirectFilter = new OAuth2AuthorizationRequestRedirectWebFilter( - clientRegistrationRepository); - oauthRedirectFilter.setAuthorizationRequestRepository(getAuthorizationRequestRepository()); - if (http.requestCache != null) { - oauthRedirectFilter.setRequestCache(http.requestCache.requestCache); - } - - http.addFilterAt(codeGrantWebFilter, SecurityWebFiltersOrder.OAUTH2_AUTHORIZATION_CODE); - http.addFilterAt(oauthRedirectFilter, SecurityWebFiltersOrder.HTTP_BASIC); - } - - private ReactiveClientRegistrationRepository getClientRegistrationRepository() { - if (this.clientRegistrationRepository != null) { - return this.clientRegistrationRepository; - } - return getBeanOrNull(ReactiveClientRegistrationRepository.class); - } - - private ServerOAuth2AuthorizedClientRepository getAuthorizedClientRepository() { - if (this.authorizedClientRepository != null) { - return this.authorizedClientRepository; - } - ServerOAuth2AuthorizedClientRepository result = getBeanOrNull(ServerOAuth2AuthorizedClientRepository.class); - if (result == null) { - ReactiveOAuth2AuthorizedClientService authorizedClientService = getAuthorizedClientService(); - if (authorizedClientService != null) { - result = new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(authorizedClientService); - } - } - return result; - } - - private ReactiveOAuth2AuthorizedClientService getAuthorizedClientService() { - ReactiveOAuth2AuthorizedClientService service = getBeanOrNull(ReactiveOAuth2AuthorizedClientService.class); - if (service == null) { - service = new InMemoryReactiveOAuth2AuthorizedClientService(getClientRegistrationRepository()); - } - return service; - } - - } - /** * Configures OAuth 2.0 Resource Server support. * @@ -1654,442 +964,6 @@ public class ServerHttpSecurity { return this; } - /** - * Configures OAuth2 Resource Server Support - */ - public class OAuth2ResourceServerSpec { - - private ServerAuthenticationEntryPoint entryPoint = new BearerTokenServerAuthenticationEntryPoint(); - - private ServerAccessDeniedHandler accessDeniedHandler = new BearerTokenServerAccessDeniedHandler(); - - private ServerAuthenticationConverter bearerTokenConverter = new ServerBearerTokenAuthenticationConverter(); - - private AuthenticationConverterServerWebExchangeMatcher authenticationConverterServerWebExchangeMatcher; - - private JwtSpec jwt; - - private OpaqueTokenSpec opaqueToken; - - private ReactiveAuthenticationManagerResolver authenticationManagerResolver; - - /** - * Configures the {@link ServerAccessDeniedHandler} to use for requests - * authenticating with - * Bearer Tokens. requests. - * @param accessDeniedHandler the {@link ServerAccessDeniedHandler} to use - * @return the {@link OAuth2ResourceServerSpec} for additional configuration - * @since 5.2 - */ - public OAuth2ResourceServerSpec accessDeniedHandler(ServerAccessDeniedHandler accessDeniedHandler) { - Assert.notNull(accessDeniedHandler, "accessDeniedHandler cannot be null"); - this.accessDeniedHandler = accessDeniedHandler; - return this; - } - - /** - * Configures the {@link ServerAuthenticationEntryPoint} to use for requests - * authenticating with - * Bearer Tokens. - * @param entryPoint the {@link ServerAuthenticationEntryPoint} to use - * @return the {@link OAuth2ResourceServerSpec} for additional configuration - * @since 5.2 - */ - public OAuth2ResourceServerSpec authenticationEntryPoint(ServerAuthenticationEntryPoint entryPoint) { - Assert.notNull(entryPoint, "entryPoint cannot be null"); - this.entryPoint = entryPoint; - return this; - } - - /** - * Configures the {@link ServerAuthenticationConverter} to use for requests - * authenticating with - * Bearer Tokens. - * @param bearerTokenConverter The {@link ServerAuthenticationConverter} to use - * @return The {@link OAuth2ResourceServerSpec} for additional configuration - * @since 5.2 - */ - public OAuth2ResourceServerSpec bearerTokenConverter(ServerAuthenticationConverter bearerTokenConverter) { - Assert.notNull(bearerTokenConverter, "bearerTokenConverter cannot be null"); - this.bearerTokenConverter = bearerTokenConverter; - return this; - } - - /** - * Configures the {@link ReactiveAuthenticationManagerResolver} - * @param authenticationManagerResolver the - * {@link ReactiveAuthenticationManagerResolver} - * @return the {@link OAuth2ResourceServerSpec} for additional configuration - * @since 5.3 - */ - public OAuth2ResourceServerSpec authenticationManagerResolver( - ReactiveAuthenticationManagerResolver authenticationManagerResolver) { - Assert.notNull(authenticationManagerResolver, "authenticationManagerResolver cannot be null"); - this.authenticationManagerResolver = authenticationManagerResolver; - return this; - } - - /** - * Enables JWT Resource Server support. - * @return the {@link JwtSpec} for additional configuration - */ - public JwtSpec jwt() { - if (this.jwt == null) { - this.jwt = new JwtSpec(); - } - return this.jwt; - } - - /** - * Enables JWT Resource Server support. - * @param jwtCustomizer the {@link Customizer} to provide more options for the - * {@link JwtSpec} - * @return the {@link OAuth2ResourceServerSpec} to customize - */ - public OAuth2ResourceServerSpec jwt(Customizer jwtCustomizer) { - if (this.jwt == null) { - this.jwt = new JwtSpec(); - } - jwtCustomizer.customize(this.jwt); - return this; - } - - /** - * Enables Opaque Token Resource Server support. - * @return the {@link OpaqueTokenSpec} for additional configuration - */ - public OpaqueTokenSpec opaqueToken() { - if (this.opaqueToken == null) { - this.opaqueToken = new OpaqueTokenSpec(); - } - return this.opaqueToken; - } - - /** - * Enables Opaque Token Resource Server support. - * @param opaqueTokenCustomizer the {@link Customizer} to provide more options for - * the {@link OpaqueTokenSpec} - * @return the {@link OAuth2ResourceServerSpec} to customize - */ - public OAuth2ResourceServerSpec opaqueToken(Customizer opaqueTokenCustomizer) { - if (this.opaqueToken == null) { - this.opaqueToken = new OpaqueTokenSpec(); - } - opaqueTokenCustomizer.customize(this.opaqueToken); - return this; - } - - protected void configure(ServerHttpSecurity http) { - this.authenticationConverterServerWebExchangeMatcher = new AuthenticationConverterServerWebExchangeMatcher( - this.bearerTokenConverter); - - registerDefaultAccessDeniedHandler(http); - registerDefaultAuthenticationEntryPoint(http); - registerDefaultCsrfOverride(http); - - validateConfiguration(); - - if (this.authenticationManagerResolver != null) { - AuthenticationWebFilter oauth2 = new AuthenticationWebFilter(this.authenticationManagerResolver); - oauth2.setServerAuthenticationConverter(this.bearerTokenConverter); - oauth2.setAuthenticationFailureHandler( - new ServerAuthenticationEntryPointFailureHandler(this.entryPoint)); - http.addFilterAt(oauth2, SecurityWebFiltersOrder.AUTHENTICATION); - } - else if (this.jwt != null) { - this.jwt.configure(http); - } - else if (this.opaqueToken != null) { - this.opaqueToken.configure(http); - } - } - - private void validateConfiguration() { - if (this.authenticationManagerResolver == null) { - if (this.jwt == null && this.opaqueToken == null) { - throw new IllegalStateException( - "Jwt and Opaque Token are the only supported formats for bearer tokens " - + "in Spring Security and neither was found. Make sure to configure JWT " - + "via http.oauth2ResourceServer().jwt() or Opaque Tokens via " - + "http.oauth2ResourceServer().opaqueToken()."); - } - - if (this.jwt != null && this.opaqueToken != null) { - throw new IllegalStateException( - "Spring Security only supports JWTs or Opaque Tokens, not both at the " + "same time."); - } - } - else { - if (this.jwt != null || this.opaqueToken != null) { - throw new IllegalStateException( - "If an authenticationManagerResolver() is configured, then it takes " - + "precedence over any jwt() or opaqueToken() configuration."); - } - } - } - - private void registerDefaultAccessDeniedHandler(ServerHttpSecurity http) { - if (http.exceptionHandling != null) { - http.defaultAccessDeniedHandlers - .add(new ServerWebExchangeDelegatingServerAccessDeniedHandler.DelegateEntry( - this.authenticationConverterServerWebExchangeMatcher, - OAuth2ResourceServerSpec.this.accessDeniedHandler)); - } - } - - private void registerDefaultAuthenticationEntryPoint(ServerHttpSecurity http) { - if (http.exceptionHandling != null) { - http.defaultEntryPoints.add(new DelegateEntry(this.authenticationConverterServerWebExchangeMatcher, - OAuth2ResourceServerSpec.this.entryPoint)); - } - } - - private void registerDefaultCsrfOverride(ServerHttpSecurity http) { - if (http.csrf != null && !http.csrf.specifiedRequireCsrfProtectionMatcher) { - // @formatter:off - http - .csrf() - .requireCsrfProtectionMatcher( - new AndServerWebExchangeMatcher( - CsrfWebFilter.DEFAULT_CSRF_MATCHER, - new NegatedServerWebExchangeMatcher( - this.authenticationConverterServerWebExchangeMatcher))); - // @formatter:on - } - } - - private class BearerTokenAuthenticationWebFilter extends AuthenticationWebFilter { - - private ServerAuthenticationFailureHandler authenticationFailureHandler; - - BearerTokenAuthenticationWebFilter(ReactiveAuthenticationManager authenticationManager) { - super(authenticationManager); - } - - @Override - public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { - WebFilterExchange webFilterExchange = new WebFilterExchange(exchange, chain); - return super.filter(exchange, chain).onErrorResume(AuthenticationException.class, - e -> this.authenticationFailureHandler.onAuthenticationFailure(webFilterExchange, e)); - } - - @Override - public void setAuthenticationFailureHandler( - ServerAuthenticationFailureHandler authenticationFailureHandler) { - super.setAuthenticationFailureHandler(authenticationFailureHandler); - this.authenticationFailureHandler = authenticationFailureHandler; - } - - } - - /** - * Configures JWT Resource Server Support - */ - public class JwtSpec { - - private ReactiveAuthenticationManager authenticationManager; - - private ReactiveJwtDecoder jwtDecoder; - - private Converter> jwtAuthenticationConverter = new ReactiveJwtAuthenticationConverterAdapter( - new JwtAuthenticationConverter()); - - /** - * Configures the {@link ReactiveAuthenticationManager} to use - * @param authenticationManager the authentication manager to use - * @return the {@code JwtSpec} for additional configuration - */ - public JwtSpec authenticationManager(ReactiveAuthenticationManager authenticationManager) { - Assert.notNull(authenticationManager, "authenticationManager cannot be null"); - this.authenticationManager = authenticationManager; - return this; - } - - /** - * Configures the {@link Converter} to use for converting a {@link Jwt} into - * an {@link AbstractAuthenticationToken}. - * @param jwtAuthenticationConverter the converter to use - * @return the {@code JwtSpec} for additional configuration - * @since 5.1.1 - */ - public JwtSpec jwtAuthenticationConverter( - Converter> jwtAuthenticationConverter) { - Assert.notNull(jwtAuthenticationConverter, "jwtAuthenticationConverter cannot be null"); - this.jwtAuthenticationConverter = jwtAuthenticationConverter; - return this; - } - - /** - * Configures the {@link ReactiveJwtDecoder} to use - * @param jwtDecoder the decoder to use - * @return the {@code JwtSpec} for additional configuration - */ - public JwtSpec jwtDecoder(ReactiveJwtDecoder jwtDecoder) { - this.jwtDecoder = jwtDecoder; - return this; - } - - /** - * Configures a {@link ReactiveJwtDecoder} that leverages the provided - * {@link RSAPublicKey} - * @param publicKey the public key to use. - * @return the {@code JwtSpec} for additional configuration - */ - public JwtSpec publicKey(RSAPublicKey publicKey) { - this.jwtDecoder = new NimbusReactiveJwtDecoder(publicKey); - return this; - } - - /** - * Configures a {@link ReactiveJwtDecoder} using - * JSON Web Key - * (JWK) URL - * @param jwkSetUri the URL to use. - * @return the {@code JwtSpec} for additional configuration - */ - public JwtSpec jwkSetUri(String jwkSetUri) { - this.jwtDecoder = new NimbusReactiveJwtDecoder(jwkSetUri); - return this; - } - - public OAuth2ResourceServerSpec and() { - return OAuth2ResourceServerSpec.this; - } - - protected void configure(ServerHttpSecurity http) { - ReactiveAuthenticationManager authenticationManager = getAuthenticationManager(); - AuthenticationWebFilter oauth2 = new BearerTokenAuthenticationWebFilter(authenticationManager); - oauth2.setServerAuthenticationConverter(OAuth2ResourceServerSpec.this.bearerTokenConverter); - oauth2.setAuthenticationFailureHandler( - new ServerAuthenticationEntryPointFailureHandler(OAuth2ResourceServerSpec.this.entryPoint)); - // @formatter:off - http - .addFilterAt(oauth2, SecurityWebFiltersOrder.AUTHENTICATION); - // @formatter:on - } - - protected ReactiveJwtDecoder getJwtDecoder() { - if (this.jwtDecoder == null) { - return getBean(ReactiveJwtDecoder.class); - } - return this.jwtDecoder; - } - - protected Converter> getJwtAuthenticationConverter() { - - return this.jwtAuthenticationConverter; - } - - private ReactiveAuthenticationManager getAuthenticationManager() { - if (this.authenticationManager != null) { - return this.authenticationManager; - } - - ReactiveJwtDecoder jwtDecoder = getJwtDecoder(); - Converter> jwtAuthenticationConverter = getJwtAuthenticationConverter(); - JwtReactiveAuthenticationManager authenticationManager = new JwtReactiveAuthenticationManager( - jwtDecoder); - authenticationManager.setJwtAuthenticationConverter(jwtAuthenticationConverter); - - return authenticationManager; - } - - } - - /** - * Configures Opaque Token Resource Server support - * - * @author Josh Cummings - * @since 5.2 - */ - public final class OpaqueTokenSpec { - - private String introspectionUri; - - private String clientId; - - private String clientSecret; - - private Supplier introspector; - - private OpaqueTokenSpec() { - } - - /** - * Configures the URI of the Introspection endpoint - * @param introspectionUri The URI of the Introspection endpoint - * @return the {@code OpaqueTokenSpec} for additional configuration - */ - public OpaqueTokenSpec introspectionUri(String introspectionUri) { - Assert.hasText(introspectionUri, "introspectionUri cannot be empty"); - this.introspectionUri = introspectionUri; - this.introspector = () -> new NimbusReactiveOpaqueTokenIntrospector(this.introspectionUri, - this.clientId, this.clientSecret); - return this; - } - - /** - * Configures the credentials for Introspection endpoint - * @param clientId The clientId part of the credentials - * @param clientSecret The clientSecret part of the credentials - * @return the {@code OpaqueTokenSpec} for additional configuration - */ - public OpaqueTokenSpec introspectionClientCredentials(String clientId, String clientSecret) { - Assert.hasText(clientId, "clientId cannot be empty"); - Assert.notNull(clientSecret, "clientSecret cannot be null"); - this.clientId = clientId; - this.clientSecret = clientSecret; - this.introspector = () -> new NimbusReactiveOpaqueTokenIntrospector(this.introspectionUri, - this.clientId, this.clientSecret); - return this; - } - - public OpaqueTokenSpec introspector(ReactiveOpaqueTokenIntrospector introspector) { - Assert.notNull(introspector, "introspector cannot be null"); - this.introspector = () -> introspector; - return this; - } - - /** - * Allows method chaining to continue configuring the - * {@link ServerHttpSecurity} - * @return the {@link ServerHttpSecurity} to continue configuring - */ - public OAuth2ResourceServerSpec and() { - return OAuth2ResourceServerSpec.this; - } - - protected ReactiveAuthenticationManager getAuthenticationManager() { - return new OpaqueTokenReactiveAuthenticationManager(getIntrospector()); - } - - protected ReactiveOpaqueTokenIntrospector getIntrospector() { - if (this.introspector != null) { - return this.introspector.get(); - } - return getBean(ReactiveOpaqueTokenIntrospector.class); - } - - protected void configure(ServerHttpSecurity http) { - ReactiveAuthenticationManager authenticationManager = getAuthenticationManager(); - AuthenticationWebFilter oauth2 = new BearerTokenAuthenticationWebFilter(authenticationManager); - oauth2.setServerAuthenticationConverter(OAuth2ResourceServerSpec.this.bearerTokenConverter); - oauth2.setAuthenticationFailureHandler( - new ServerAuthenticationEntryPointFailureHandler(OAuth2ResourceServerSpec.this.entryPoint)); - http.addFilterAt(oauth2, SecurityWebFiltersOrder.AUTHENTICATION); - } - - } - - public ServerHttpSecurity and() { - return ServerHttpSecurity.this; - } - - } - /** * Configures HTTP Response Headers. The default headers are: * @@ -2599,7 +1473,30 @@ public class ServerHttpSecurity { return new OrderedWebFilter(result, SecurityWebFiltersOrder.REACTOR_CONTEXT.getOrder()); } - protected ServerHttpSecurity() { + private T getBean(Class beanClass) { + if (this.context == null) { + return null; + } + return this.context.getBean(beanClass); + } + + private T getBeanOrNull(Class beanClass) { + return getBeanOrNull(ResolvableType.forClass(beanClass)); + } + + private T getBeanOrNull(ResolvableType type) { + if (this.context == null) { + return null; + } + String[] names = this.context.getBeanNamesForType(type); + if (names.length == 1) { + return (T) this.context.getBean(names[0]); + } + return null; + } + + protected void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.context = applicationContext; } /** @@ -3931,32 +2828,6 @@ public class ServerHttpSecurity { } - private T getBean(Class beanClass) { - if (this.context == null) { - return null; - } - return this.context.getBean(beanClass); - } - - private T getBeanOrNull(Class beanClass) { - return getBeanOrNull(ResolvableType.forClass(beanClass)); - } - - private T getBeanOrNull(ResolvableType type) { - if (this.context == null) { - return null; - } - String[] names = this.context.getBeanNamesForType(type); - if (names.length == 1) { - return (T) this.context.getBean(names[0]); - } - return null; - } - - protected void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.context = applicationContext; - } - private static class OrderedWebFilter implements WebFilter, Ordered { private final WebFilter webFilter; @@ -3997,6 +2868,1135 @@ public class ServerHttpSecurity { } + /** + * Configures CORS support within Spring Security. This ensures that the + * {@link CorsWebFilter} is place in the correct order. + */ + public final class CorsSpec { + + private CorsWebFilter corsFilter; + + private CorsSpec() { + } + + /** + * Configures the {@link CorsConfigurationSource} to be used + * @param source the source to use + * @return the {@link CorsSpec} for additional configuration + */ + public CorsSpec configurationSource(CorsConfigurationSource source) { + this.corsFilter = new CorsWebFilter(source); + return this; + } + + /** + * Disables CORS support within Spring Security. + * @return the {@link ServerHttpSecurity} to continue configuring + */ + public ServerHttpSecurity disable() { + ServerHttpSecurity.this.cors = null; + return ServerHttpSecurity.this; + } + + /** + * Allows method chaining to continue configuring the {@link ServerHttpSecurity} + * @return the {@link ServerHttpSecurity} to continue configuring + */ + public ServerHttpSecurity and() { + return ServerHttpSecurity.this; + } + + protected void configure(ServerHttpSecurity http) { + CorsWebFilter corsFilter = getCorsFilter(); + if (corsFilter != null) { + http.addFilterAt(this.corsFilter, SecurityWebFiltersOrder.CORS); + } + } + + private CorsWebFilter getCorsFilter() { + if (this.corsFilter != null) { + return this.corsFilter; + } + + CorsConfigurationSource source = getBeanOrNull(CorsConfigurationSource.class); + if (source == null) { + return null; + } + CorsProcessor processor = getBeanOrNull(CorsProcessor.class); + if (processor == null) { + processor = new DefaultCorsProcessor(); + } + this.corsFilter = new CorsWebFilter(source, processor); + return this.corsFilter; + } + + } + + /** + * Configures X509 authentication + * + * @author Alexey Nesterov + * @since 5.2 + * @see #x509() + */ + public final class X509Spec { + + private X509PrincipalExtractor principalExtractor; + + private ReactiveAuthenticationManager authenticationManager; + + private X509Spec() { + } + + public X509Spec principalExtractor(X509PrincipalExtractor principalExtractor) { + this.principalExtractor = principalExtractor; + return this; + } + + public X509Spec authenticationManager(ReactiveAuthenticationManager authenticationManager) { + this.authenticationManager = authenticationManager; + return this; + } + + public ServerHttpSecurity and() { + return ServerHttpSecurity.this; + } + + protected void configure(ServerHttpSecurity http) { + ReactiveAuthenticationManager authenticationManager = getAuthenticationManager(); + X509PrincipalExtractor principalExtractor = getPrincipalExtractor(); + + AuthenticationWebFilter filter = new AuthenticationWebFilter(authenticationManager); + filter.setServerAuthenticationConverter(new ServerX509AuthenticationConverter(principalExtractor)); + http.addFilterAt(filter, SecurityWebFiltersOrder.AUTHENTICATION); + } + + private X509PrincipalExtractor getPrincipalExtractor() { + if (this.principalExtractor != null) { + return this.principalExtractor; + } + + return new SubjectDnX509PrincipalExtractor(); + } + + private ReactiveAuthenticationManager getAuthenticationManager() { + if (this.authenticationManager != null) { + return this.authenticationManager; + } + + ReactiveUserDetailsService userDetailsService = getBean(ReactiveUserDetailsService.class); + ReactivePreAuthenticatedAuthenticationManager authenticationManager = new ReactivePreAuthenticatedAuthenticationManager( + userDetailsService); + + return authenticationManager; + } + + } + + public final class OAuth2LoginSpec { + + private ReactiveClientRegistrationRepository clientRegistrationRepository; + + private ServerOAuth2AuthorizedClientRepository authorizedClientRepository; + + private ServerAuthorizationRequestRepository authorizationRequestRepository; + + private ReactiveAuthenticationManager authenticationManager; + + private ServerSecurityContextRepository securityContextRepository; + + private ServerAuthenticationConverter authenticationConverter; + + private ServerOAuth2AuthorizationRequestResolver authorizationRequestResolver; + + private ServerWebExchangeMatcher authenticationMatcher; + + private ServerAuthenticationSuccessHandler authenticationSuccessHandler; + + private ServerAuthenticationFailureHandler authenticationFailureHandler; + + private OAuth2LoginSpec() { + } + + /** + * Configures the {@link ReactiveAuthenticationManager} to use. The default is + * {@link OAuth2AuthorizationCodeReactiveAuthenticationManager} + * @param authenticationManager the manager to use + * @return the {@link OAuth2LoginSpec} to customize + */ + public OAuth2LoginSpec authenticationManager(ReactiveAuthenticationManager authenticationManager) { + this.authenticationManager = authenticationManager; + return this; + } + + /** + * The {@link ServerSecurityContextRepository} used to save the + * {@code Authentication}. Defaults to + * {@link WebSessionServerSecurityContextRepository}. + * @param securityContextRepository the repository to use + * @return the {@link OAuth2LoginSpec} to continue configuring + * @since 5.2 + */ + public OAuth2LoginSpec securityContextRepository(ServerSecurityContextRepository securityContextRepository) { + this.securityContextRepository = securityContextRepository; + return this; + } + + /** + * The {@link ServerAuthenticationSuccessHandler} used after authentication + * success. Defaults to {@link RedirectServerAuthenticationSuccessHandler} + * redirecting to "/". + * @param authenticationSuccessHandler the success handler to use + * @return the {@link OAuth2LoginSpec} to customize + * @since 5.2 + */ + public OAuth2LoginSpec authenticationSuccessHandler( + ServerAuthenticationSuccessHandler authenticationSuccessHandler) { + Assert.notNull(authenticationSuccessHandler, "authenticationSuccessHandler cannot be null"); + this.authenticationSuccessHandler = authenticationSuccessHandler; + return this; + } + + /** + * The {@link ServerAuthenticationFailureHandler} used after authentication + * failure. Defaults to {@link RedirectServerAuthenticationFailureHandler} + * redirecting to "/login?error". + * @param authenticationFailureHandler the failure handler to use + * @return the {@link OAuth2LoginSpec} to customize + * @since 5.2 + */ + public OAuth2LoginSpec authenticationFailureHandler( + ServerAuthenticationFailureHandler authenticationFailureHandler) { + Assert.notNull(authenticationFailureHandler, "authenticationFailureHandler cannot be null"); + this.authenticationFailureHandler = authenticationFailureHandler; + return this; + } + + /** + * Gets the {@link ReactiveAuthenticationManager} to use. First tries an + * explicitly configured manager, and defaults to + * {@link OAuth2AuthorizationCodeReactiveAuthenticationManager} + * @return the {@link ReactiveAuthenticationManager} to use + */ + private ReactiveAuthenticationManager getAuthenticationManager() { + if (this.authenticationManager == null) { + this.authenticationManager = createDefault(); + } + return this.authenticationManager; + } + + private ReactiveAuthenticationManager createDefault() { + ReactiveOAuth2AccessTokenResponseClient client = getAccessTokenResponseClient(); + OAuth2LoginReactiveAuthenticationManager oauth2Manager = new OAuth2LoginReactiveAuthenticationManager( + client, getOauth2UserService()); + GrantedAuthoritiesMapper authoritiesMapper = getBeanOrNull(GrantedAuthoritiesMapper.class); + if (authoritiesMapper != null) { + oauth2Manager.setAuthoritiesMapper(authoritiesMapper); + } + boolean oidcAuthenticationProviderEnabled = ClassUtils + .isPresent("org.springframework.security.oauth2.jwt.JwtDecoder", this.getClass().getClassLoader()); + if (oidcAuthenticationProviderEnabled) { + OidcAuthorizationCodeReactiveAuthenticationManager oidc = new OidcAuthorizationCodeReactiveAuthenticationManager( + client, getOidcUserService()); + ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveJwtDecoderFactory.class, + ClientRegistration.class); + ReactiveJwtDecoderFactory jwtDecoderFactory = getBeanOrNull(type); + if (jwtDecoderFactory != null) { + oidc.setJwtDecoderFactory(jwtDecoderFactory); + } + if (authoritiesMapper != null) { + oidc.setAuthoritiesMapper(authoritiesMapper); + } + return new DelegatingReactiveAuthenticationManager(oidc, oauth2Manager); + } + return oauth2Manager; + } + + /** + * Sets the converter to use + * @param authenticationConverter the converter to use + * @return the {@link OAuth2LoginSpec} to customize + */ + public OAuth2LoginSpec authenticationConverter(ServerAuthenticationConverter authenticationConverter) { + this.authenticationConverter = authenticationConverter; + return this; + } + + private ServerAuthenticationConverter getAuthenticationConverter( + ReactiveClientRegistrationRepository clientRegistrationRepository) { + if (this.authenticationConverter == null) { + ServerOAuth2AuthorizationCodeAuthenticationTokenConverter delegate = new ServerOAuth2AuthorizationCodeAuthenticationTokenConverter( + clientRegistrationRepository); + delegate.setAuthorizationRequestRepository(getAuthorizationRequestRepository()); + ServerAuthenticationConverter authenticationConverter = exchange -> delegate.convert(exchange) + .onErrorMap(OAuth2AuthorizationException.class, + e -> new OAuth2AuthenticationException(e.getError(), e.getError().toString())); + this.authenticationConverter = authenticationConverter; + return authenticationConverter; + } + return this.authenticationConverter; + } + + public OAuth2LoginSpec clientRegistrationRepository( + ReactiveClientRegistrationRepository clientRegistrationRepository) { + this.clientRegistrationRepository = clientRegistrationRepository; + return this; + } + + public OAuth2LoginSpec authorizedClientService(ReactiveOAuth2AuthorizedClientService authorizedClientService) { + this.authorizedClientRepository = new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository( + authorizedClientService); + return this; + } + + public OAuth2LoginSpec authorizedClientRepository( + ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { + this.authorizedClientRepository = authorizedClientRepository; + return this; + } + + /** + * Sets the repository to use for storing {@link OAuth2AuthorizationRequest}'s. + * @param authorizationRequestRepository the repository to use for storing + * {@link OAuth2AuthorizationRequest}'s + * @return the {@link OAuth2LoginSpec} for further configuration + * @since 5.2 + */ + public OAuth2LoginSpec authorizationRequestRepository( + ServerAuthorizationRequestRepository authorizationRequestRepository) { + this.authorizationRequestRepository = authorizationRequestRepository; + return this; + } + + /** + * Sets the resolver used for resolving {@link OAuth2AuthorizationRequest}'s. + * @param authorizationRequestResolver the resolver used for resolving + * {@link OAuth2AuthorizationRequest}'s + * @return the {@link OAuth2LoginSpec} for further configuration + * @since 5.2 + */ + public OAuth2LoginSpec authorizationRequestResolver( + ServerOAuth2AuthorizationRequestResolver authorizationRequestResolver) { + this.authorizationRequestResolver = authorizationRequestResolver; + return this; + } + + /** + * Sets the {@link ServerWebExchangeMatcher matcher} used for determining if the + * request is an authentication request. + * @param authenticationMatcher the {@link ServerWebExchangeMatcher matcher} used + * for determining if the request is an authentication request + * @return the {@link OAuth2LoginSpec} for further configuration + * @since 5.2 + */ + public OAuth2LoginSpec authenticationMatcher(ServerWebExchangeMatcher authenticationMatcher) { + this.authenticationMatcher = authenticationMatcher; + return this; + } + + private ServerWebExchangeMatcher getAuthenticationMatcher() { + if (this.authenticationMatcher == null) { + this.authenticationMatcher = createAttemptAuthenticationRequestMatcher(); + } + return this.authenticationMatcher; + } + + /** + * Allows method chaining to continue configuring the {@link ServerHttpSecurity} + * @return the {@link ServerHttpSecurity} to continue configuring + */ + public ServerHttpSecurity and() { + return ServerHttpSecurity.this; + } + + protected void configure(ServerHttpSecurity http) { + ReactiveClientRegistrationRepository clientRegistrationRepository = getClientRegistrationRepository(); + ServerOAuth2AuthorizedClientRepository authorizedClientRepository = getAuthorizedClientRepository(); + OAuth2AuthorizationRequestRedirectWebFilter oauthRedirectFilter = getRedirectWebFilter(); + ServerAuthorizationRequestRepository authorizationRequestRepository = getAuthorizationRequestRepository(); + oauthRedirectFilter.setAuthorizationRequestRepository(authorizationRequestRepository); + oauthRedirectFilter.setRequestCache(http.requestCache.requestCache); + + ReactiveAuthenticationManager manager = getAuthenticationManager(); + + AuthenticationWebFilter authenticationFilter = new OAuth2LoginAuthenticationWebFilter(manager, + authorizedClientRepository); + authenticationFilter.setRequiresAuthenticationMatcher(getAuthenticationMatcher()); + authenticationFilter + .setServerAuthenticationConverter(getAuthenticationConverter(clientRegistrationRepository)); + + authenticationFilter.setAuthenticationSuccessHandler(getAuthenticationSuccessHandler(http)); + authenticationFilter.setAuthenticationFailureHandler(getAuthenticationFailureHandler()); + authenticationFilter.setSecurityContextRepository(this.securityContextRepository); + + setDefaultEntryPoints(http); + + http.addFilterAt(oauthRedirectFilter, SecurityWebFiltersOrder.HTTP_BASIC); + http.addFilterAt(authenticationFilter, SecurityWebFiltersOrder.AUTHENTICATION); + } + + private void setDefaultEntryPoints(ServerHttpSecurity http) { + String defaultLoginPage = "/login"; + Map urlToText = http.oauth2Login.getLinks(); + String providerLoginPage = null; + if (urlToText.size() == 1) { + providerLoginPage = urlToText.keySet().iterator().next(); + } + + MediaTypeServerWebExchangeMatcher htmlMatcher = new MediaTypeServerWebExchangeMatcher( + MediaType.APPLICATION_XHTML_XML, new MediaType("image", "*"), MediaType.TEXT_HTML, + MediaType.TEXT_PLAIN); + htmlMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL)); + + ServerWebExchangeMatcher xhrMatcher = exchange -> { + if (exchange.getRequest().getHeaders().getOrEmpty("X-Requested-With").contains("XMLHttpRequest")) { + return ServerWebExchangeMatcher.MatchResult.match(); + } + return ServerWebExchangeMatcher.MatchResult.notMatch(); + }; + ServerWebExchangeMatcher notXhrMatcher = new NegatedServerWebExchangeMatcher(xhrMatcher); + + ServerWebExchangeMatcher defaultEntryPointMatcher = new AndServerWebExchangeMatcher(notXhrMatcher, + htmlMatcher); + + if (providerLoginPage != null) { + ServerWebExchangeMatcher loginPageMatcher = new PathPatternParserServerWebExchangeMatcher( + defaultLoginPage); + ServerWebExchangeMatcher faviconMatcher = new PathPatternParserServerWebExchangeMatcher("/favicon.ico"); + ServerWebExchangeMatcher defaultLoginPageMatcher = new AndServerWebExchangeMatcher( + new OrServerWebExchangeMatcher(loginPageMatcher, faviconMatcher), defaultEntryPointMatcher); + + ServerWebExchangeMatcher matcher = new AndServerWebExchangeMatcher(notXhrMatcher, + new NegatedServerWebExchangeMatcher(defaultLoginPageMatcher)); + RedirectServerAuthenticationEntryPoint entryPoint = new RedirectServerAuthenticationEntryPoint( + providerLoginPage); + entryPoint.setRequestCache(http.requestCache.requestCache); + http.defaultEntryPoints.add(new DelegateEntry(matcher, entryPoint)); + } + + RedirectServerAuthenticationEntryPoint defaultEntryPoint = new RedirectServerAuthenticationEntryPoint( + defaultLoginPage); + defaultEntryPoint.setRequestCache(http.requestCache.requestCache); + http.defaultEntryPoints.add(new DelegateEntry(defaultEntryPointMatcher, defaultEntryPoint)); + } + + private ServerAuthenticationSuccessHandler getAuthenticationSuccessHandler(ServerHttpSecurity http) { + if (this.authenticationSuccessHandler == null) { + RedirectServerAuthenticationSuccessHandler handler = new RedirectServerAuthenticationSuccessHandler(); + handler.setRequestCache(http.requestCache.requestCache); + this.authenticationSuccessHandler = handler; + } + return this.authenticationSuccessHandler; + } + + private ServerAuthenticationFailureHandler getAuthenticationFailureHandler() { + if (this.authenticationFailureHandler == null) { + this.authenticationFailureHandler = new RedirectServerAuthenticationFailureHandler("/login?error"); + } + return this.authenticationFailureHandler; + } + + private ServerWebExchangeMatcher createAttemptAuthenticationRequestMatcher() { + return new PathPatternParserServerWebExchangeMatcher("/login/oauth2/code/{registrationId}"); + } + + private ReactiveOAuth2UserService getOidcUserService() { + ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveOAuth2UserService.class, + OidcUserRequest.class, OidcUser.class); + ReactiveOAuth2UserService bean = getBeanOrNull(type); + if (bean == null) { + return new OidcReactiveOAuth2UserService(); + } + + return bean; + } + + private ReactiveOAuth2UserService getOauth2UserService() { + ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveOAuth2UserService.class, + OAuth2UserRequest.class, OAuth2User.class); + ReactiveOAuth2UserService bean = getBeanOrNull(type); + if (bean == null) { + return new DefaultReactiveOAuth2UserService(); + } + + return bean; + } + + private Map getLinks() { + Iterable registrations = getBeanOrNull( + ResolvableType.forClassWithGenerics(Iterable.class, ClientRegistration.class)); + if (registrations == null) { + return Collections.emptyMap(); + } + Map result = new HashMap<>(); + registrations.iterator().forEachRemaining( + r -> result.put("/oauth2/authorization/" + r.getRegistrationId(), r.getClientName())); + return result; + } + + private ReactiveOAuth2AccessTokenResponseClient getAccessTokenResponseClient() { + ResolvableType type = ResolvableType.forClassWithGenerics(ReactiveOAuth2AccessTokenResponseClient.class, + OAuth2AuthorizationCodeGrantRequest.class); + ReactiveOAuth2AccessTokenResponseClient bean = getBeanOrNull(type); + if (bean == null) { + return new WebClientReactiveAuthorizationCodeTokenResponseClient(); + } + return bean; + } + + private ReactiveClientRegistrationRepository getClientRegistrationRepository() { + if (this.clientRegistrationRepository == null) { + this.clientRegistrationRepository = getBeanOrNull(ReactiveClientRegistrationRepository.class); + } + return this.clientRegistrationRepository; + } + + private OAuth2AuthorizationRequestRedirectWebFilter getRedirectWebFilter() { + OAuth2AuthorizationRequestRedirectWebFilter oauthRedirectFilter; + if (this.authorizationRequestResolver == null) { + oauthRedirectFilter = new OAuth2AuthorizationRequestRedirectWebFilter( + getClientRegistrationRepository()); + } + else { + oauthRedirectFilter = new OAuth2AuthorizationRequestRedirectWebFilter( + this.authorizationRequestResolver); + } + return oauthRedirectFilter; + } + + private ServerOAuth2AuthorizedClientRepository getAuthorizedClientRepository() { + ServerOAuth2AuthorizedClientRepository result = this.authorizedClientRepository; + if (result == null) { + result = getBeanOrNull(ServerOAuth2AuthorizedClientRepository.class); + } + if (result == null) { + ReactiveOAuth2AuthorizedClientService authorizedClientService = getAuthorizedClientService(); + if (authorizedClientService != null) { + result = new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(authorizedClientService); + } + } + return result; + } + + private ServerAuthorizationRequestRepository getAuthorizationRequestRepository() { + if (this.authorizationRequestRepository == null) { + this.authorizationRequestRepository = new WebSessionOAuth2ServerAuthorizationRequestRepository(); + } + return this.authorizationRequestRepository; + } + + private ReactiveOAuth2AuthorizedClientService getAuthorizedClientService() { + ReactiveOAuth2AuthorizedClientService service = getBeanOrNull(ReactiveOAuth2AuthorizedClientService.class); + if (service == null) { + service = new InMemoryReactiveOAuth2AuthorizedClientService(getClientRegistrationRepository()); + } + return service; + } + + } + + public final class OAuth2ClientSpec { + + private ReactiveClientRegistrationRepository clientRegistrationRepository; + + private ServerAuthenticationConverter authenticationConverter; + + private ServerOAuth2AuthorizedClientRepository authorizedClientRepository; + + private ReactiveAuthenticationManager authenticationManager; + + private ServerAuthorizationRequestRepository authorizationRequestRepository; + + private OAuth2ClientSpec() { + } + + /** + * Sets the converter to use + * @param authenticationConverter the converter to use + * @return the {@link OAuth2ClientSpec} to customize + */ + public OAuth2ClientSpec authenticationConverter(ServerAuthenticationConverter authenticationConverter) { + this.authenticationConverter = authenticationConverter; + return this; + } + + private ServerAuthenticationConverter getAuthenticationConverter() { + if (this.authenticationConverter == null) { + ServerOAuth2AuthorizationCodeAuthenticationTokenConverter authenticationConverter = new ServerOAuth2AuthorizationCodeAuthenticationTokenConverter( + getClientRegistrationRepository()); + authenticationConverter.setAuthorizationRequestRepository(getAuthorizationRequestRepository()); + this.authenticationConverter = authenticationConverter; + } + return this.authenticationConverter; + } + + /** + * Configures the {@link ReactiveAuthenticationManager} to use. The default is + * {@link OAuth2AuthorizationCodeReactiveAuthenticationManager} + * @param authenticationManager the manager to use + * @return the {@link OAuth2ClientSpec} to customize + */ + public OAuth2ClientSpec authenticationManager(ReactiveAuthenticationManager authenticationManager) { + this.authenticationManager = authenticationManager; + return this; + } + + /** + * Gets the {@link ReactiveAuthenticationManager} to use. First tries an + * explicitly configured manager, and defaults to + * {@link OAuth2AuthorizationCodeReactiveAuthenticationManager} + * @return the {@link ReactiveAuthenticationManager} to use + */ + private ReactiveAuthenticationManager getAuthenticationManager() { + if (this.authenticationManager == null) { + this.authenticationManager = new OAuth2AuthorizationCodeReactiveAuthenticationManager( + new WebClientReactiveAuthorizationCodeTokenResponseClient()); + } + return this.authenticationManager; + } + + /** + * Configures the {@link ReactiveClientRegistrationRepository}. Default is to look + * the value up as a Bean. + * @param clientRegistrationRepository the repository to use + * @return the {@link OAuth2ClientSpec} to customize + */ + public OAuth2ClientSpec clientRegistrationRepository( + ReactiveClientRegistrationRepository clientRegistrationRepository) { + this.clientRegistrationRepository = clientRegistrationRepository; + return this; + } + + /** + * Configures the {@link ReactiveClientRegistrationRepository}. Default is to look + * the value up as a Bean. + * @param authorizedClientRepository the repository to use + * @return the {@link OAuth2ClientSpec} to customize + */ + public OAuth2ClientSpec authorizedClientRepository( + ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { + this.authorizedClientRepository = authorizedClientRepository; + return this; + } + + /** + * Sets the repository to use for storing {@link OAuth2AuthorizationRequest}'s. + * @param authorizationRequestRepository the repository to use for storing + * {@link OAuth2AuthorizationRequest}'s + * @return the {@link OAuth2ClientSpec} to customize + * @since 5.2 + */ + public OAuth2ClientSpec authorizationRequestRepository( + ServerAuthorizationRequestRepository authorizationRequestRepository) { + this.authorizationRequestRepository = authorizationRequestRepository; + return this; + } + + private ServerAuthorizationRequestRepository getAuthorizationRequestRepository() { + if (this.authorizationRequestRepository == null) { + this.authorizationRequestRepository = new WebSessionOAuth2ServerAuthorizationRequestRepository(); + } + return this.authorizationRequestRepository; + } + + /** + * Allows method chaining to continue configuring the {@link ServerHttpSecurity} + * @return the {@link ServerHttpSecurity} to continue configuring + */ + public ServerHttpSecurity and() { + return ServerHttpSecurity.this; + } + + protected void configure(ServerHttpSecurity http) { + ReactiveClientRegistrationRepository clientRegistrationRepository = getClientRegistrationRepository(); + ServerOAuth2AuthorizedClientRepository authorizedClientRepository = getAuthorizedClientRepository(); + ServerAuthenticationConverter authenticationConverter = getAuthenticationConverter(); + ReactiveAuthenticationManager authenticationManager = getAuthenticationManager(); + OAuth2AuthorizationCodeGrantWebFilter codeGrantWebFilter = new OAuth2AuthorizationCodeGrantWebFilter( + authenticationManager, authenticationConverter, authorizedClientRepository); + codeGrantWebFilter.setAuthorizationRequestRepository(getAuthorizationRequestRepository()); + if (http.requestCache != null) { + codeGrantWebFilter.setRequestCache(http.requestCache.requestCache); + } + + OAuth2AuthorizationRequestRedirectWebFilter oauthRedirectFilter = new OAuth2AuthorizationRequestRedirectWebFilter( + clientRegistrationRepository); + oauthRedirectFilter.setAuthorizationRequestRepository(getAuthorizationRequestRepository()); + if (http.requestCache != null) { + oauthRedirectFilter.setRequestCache(http.requestCache.requestCache); + } + + http.addFilterAt(codeGrantWebFilter, SecurityWebFiltersOrder.OAUTH2_AUTHORIZATION_CODE); + http.addFilterAt(oauthRedirectFilter, SecurityWebFiltersOrder.HTTP_BASIC); + } + + private ReactiveClientRegistrationRepository getClientRegistrationRepository() { + if (this.clientRegistrationRepository != null) { + return this.clientRegistrationRepository; + } + return getBeanOrNull(ReactiveClientRegistrationRepository.class); + } + + private ServerOAuth2AuthorizedClientRepository getAuthorizedClientRepository() { + if (this.authorizedClientRepository != null) { + return this.authorizedClientRepository; + } + ServerOAuth2AuthorizedClientRepository result = getBeanOrNull(ServerOAuth2AuthorizedClientRepository.class); + if (result == null) { + ReactiveOAuth2AuthorizedClientService authorizedClientService = getAuthorizedClientService(); + if (authorizedClientService != null) { + result = new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(authorizedClientService); + } + } + return result; + } + + private ReactiveOAuth2AuthorizedClientService getAuthorizedClientService() { + ReactiveOAuth2AuthorizedClientService service = getBeanOrNull(ReactiveOAuth2AuthorizedClientService.class); + if (service == null) { + service = new InMemoryReactiveOAuth2AuthorizedClientService(getClientRegistrationRepository()); + } + return service; + } + + } + + /** + * Configures OAuth2 Resource Server Support + */ + public class OAuth2ResourceServerSpec { + + private ServerAuthenticationEntryPoint entryPoint = new BearerTokenServerAuthenticationEntryPoint(); + + private ServerAccessDeniedHandler accessDeniedHandler = new BearerTokenServerAccessDeniedHandler(); + + private ServerAuthenticationConverter bearerTokenConverter = new ServerBearerTokenAuthenticationConverter(); + + private AuthenticationConverterServerWebExchangeMatcher authenticationConverterServerWebExchangeMatcher; + + private JwtSpec jwt; + + private OpaqueTokenSpec opaqueToken; + + private ReactiveAuthenticationManagerResolver authenticationManagerResolver; + + /** + * Configures the {@link ServerAccessDeniedHandler} to use for requests + * authenticating with + * Bearer Tokens. requests. + * @param accessDeniedHandler the {@link ServerAccessDeniedHandler} to use + * @return the {@link OAuth2ResourceServerSpec} for additional configuration + * @since 5.2 + */ + public OAuth2ResourceServerSpec accessDeniedHandler(ServerAccessDeniedHandler accessDeniedHandler) { + Assert.notNull(accessDeniedHandler, "accessDeniedHandler cannot be null"); + this.accessDeniedHandler = accessDeniedHandler; + return this; + } + + /** + * Configures the {@link ServerAuthenticationEntryPoint} to use for requests + * authenticating with + * Bearer Tokens. + * @param entryPoint the {@link ServerAuthenticationEntryPoint} to use + * @return the {@link OAuth2ResourceServerSpec} for additional configuration + * @since 5.2 + */ + public OAuth2ResourceServerSpec authenticationEntryPoint(ServerAuthenticationEntryPoint entryPoint) { + Assert.notNull(entryPoint, "entryPoint cannot be null"); + this.entryPoint = entryPoint; + return this; + } + + /** + * Configures the {@link ServerAuthenticationConverter} to use for requests + * authenticating with + * Bearer Tokens. + * @param bearerTokenConverter The {@link ServerAuthenticationConverter} to use + * @return The {@link OAuth2ResourceServerSpec} for additional configuration + * @since 5.2 + */ + public OAuth2ResourceServerSpec bearerTokenConverter(ServerAuthenticationConverter bearerTokenConverter) { + Assert.notNull(bearerTokenConverter, "bearerTokenConverter cannot be null"); + this.bearerTokenConverter = bearerTokenConverter; + return this; + } + + /** + * Configures the {@link ReactiveAuthenticationManagerResolver} + * @param authenticationManagerResolver the + * {@link ReactiveAuthenticationManagerResolver} + * @return the {@link OAuth2ResourceServerSpec} for additional configuration + * @since 5.3 + */ + public OAuth2ResourceServerSpec authenticationManagerResolver( + ReactiveAuthenticationManagerResolver authenticationManagerResolver) { + Assert.notNull(authenticationManagerResolver, "authenticationManagerResolver cannot be null"); + this.authenticationManagerResolver = authenticationManagerResolver; + return this; + } + + /** + * Enables JWT Resource Server support. + * @return the {@link JwtSpec} for additional configuration + */ + public JwtSpec jwt() { + if (this.jwt == null) { + this.jwt = new JwtSpec(); + } + return this.jwt; + } + + /** + * Enables JWT Resource Server support. + * @param jwtCustomizer the {@link Customizer} to provide more options for the + * {@link JwtSpec} + * @return the {@link OAuth2ResourceServerSpec} to customize + */ + public OAuth2ResourceServerSpec jwt(Customizer jwtCustomizer) { + if (this.jwt == null) { + this.jwt = new JwtSpec(); + } + jwtCustomizer.customize(this.jwt); + return this; + } + + /** + * Enables Opaque Token Resource Server support. + * @return the {@link OpaqueTokenSpec} for additional configuration + */ + public OpaqueTokenSpec opaqueToken() { + if (this.opaqueToken == null) { + this.opaqueToken = new OpaqueTokenSpec(); + } + return this.opaqueToken; + } + + /** + * Enables Opaque Token Resource Server support. + * @param opaqueTokenCustomizer the {@link Customizer} to provide more options for + * the {@link OpaqueTokenSpec} + * @return the {@link OAuth2ResourceServerSpec} to customize + */ + public OAuth2ResourceServerSpec opaqueToken(Customizer opaqueTokenCustomizer) { + if (this.opaqueToken == null) { + this.opaqueToken = new OpaqueTokenSpec(); + } + opaqueTokenCustomizer.customize(this.opaqueToken); + return this; + } + + protected void configure(ServerHttpSecurity http) { + this.authenticationConverterServerWebExchangeMatcher = new AuthenticationConverterServerWebExchangeMatcher( + this.bearerTokenConverter); + + registerDefaultAccessDeniedHandler(http); + registerDefaultAuthenticationEntryPoint(http); + registerDefaultCsrfOverride(http); + + validateConfiguration(); + + if (this.authenticationManagerResolver != null) { + AuthenticationWebFilter oauth2 = new AuthenticationWebFilter(this.authenticationManagerResolver); + oauth2.setServerAuthenticationConverter(this.bearerTokenConverter); + oauth2.setAuthenticationFailureHandler( + new ServerAuthenticationEntryPointFailureHandler(this.entryPoint)); + http.addFilterAt(oauth2, SecurityWebFiltersOrder.AUTHENTICATION); + } + else if (this.jwt != null) { + this.jwt.configure(http); + } + else if (this.opaqueToken != null) { + this.opaqueToken.configure(http); + } + } + + private void validateConfiguration() { + if (this.authenticationManagerResolver == null) { + if (this.jwt == null && this.opaqueToken == null) { + throw new IllegalStateException( + "Jwt and Opaque Token are the only supported formats for bearer tokens " + + "in Spring Security and neither was found. Make sure to configure JWT " + + "via http.oauth2ResourceServer().jwt() or Opaque Tokens via " + + "http.oauth2ResourceServer().opaqueToken()."); + } + + if (this.jwt != null && this.opaqueToken != null) { + throw new IllegalStateException( + "Spring Security only supports JWTs or Opaque Tokens, not both at the " + "same time."); + } + } + else { + if (this.jwt != null || this.opaqueToken != null) { + throw new IllegalStateException( + "If an authenticationManagerResolver() is configured, then it takes " + + "precedence over any jwt() or opaqueToken() configuration."); + } + } + } + + private void registerDefaultAccessDeniedHandler(ServerHttpSecurity http) { + if (http.exceptionHandling != null) { + http.defaultAccessDeniedHandlers + .add(new ServerWebExchangeDelegatingServerAccessDeniedHandler.DelegateEntry( + this.authenticationConverterServerWebExchangeMatcher, + OAuth2ResourceServerSpec.this.accessDeniedHandler)); + } + } + + private void registerDefaultAuthenticationEntryPoint(ServerHttpSecurity http) { + if (http.exceptionHandling != null) { + http.defaultEntryPoints.add(new DelegateEntry(this.authenticationConverterServerWebExchangeMatcher, + OAuth2ResourceServerSpec.this.entryPoint)); + } + } + + private void registerDefaultCsrfOverride(ServerHttpSecurity http) { + if (http.csrf != null && !http.csrf.specifiedRequireCsrfProtectionMatcher) { + // @formatter:off + http + .csrf() + .requireCsrfProtectionMatcher( + new AndServerWebExchangeMatcher( + CsrfWebFilter.DEFAULT_CSRF_MATCHER, + new NegatedServerWebExchangeMatcher( + this.authenticationConverterServerWebExchangeMatcher))); + // @formatter:on + } + } + + public ServerHttpSecurity and() { + return ServerHttpSecurity.this; + } + + private class BearerTokenAuthenticationWebFilter extends AuthenticationWebFilter { + + private ServerAuthenticationFailureHandler authenticationFailureHandler; + + BearerTokenAuthenticationWebFilter(ReactiveAuthenticationManager authenticationManager) { + super(authenticationManager); + } + + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + WebFilterExchange webFilterExchange = new WebFilterExchange(exchange, chain); + return super.filter(exchange, chain).onErrorResume(AuthenticationException.class, + e -> this.authenticationFailureHandler.onAuthenticationFailure(webFilterExchange, e)); + } + + @Override + public void setAuthenticationFailureHandler( + ServerAuthenticationFailureHandler authenticationFailureHandler) { + super.setAuthenticationFailureHandler(authenticationFailureHandler); + this.authenticationFailureHandler = authenticationFailureHandler; + } + + } + + /** + * Configures JWT Resource Server Support + */ + public class JwtSpec { + + private ReactiveAuthenticationManager authenticationManager; + + private ReactiveJwtDecoder jwtDecoder; + + private Converter> jwtAuthenticationConverter = new ReactiveJwtAuthenticationConverterAdapter( + new JwtAuthenticationConverter()); + + /** + * Configures the {@link ReactiveAuthenticationManager} to use + * @param authenticationManager the authentication manager to use + * @return the {@code JwtSpec} for additional configuration + */ + public JwtSpec authenticationManager(ReactiveAuthenticationManager authenticationManager) { + Assert.notNull(authenticationManager, "authenticationManager cannot be null"); + this.authenticationManager = authenticationManager; + return this; + } + + /** + * Configures the {@link Converter} to use for converting a {@link Jwt} into + * an {@link AbstractAuthenticationToken}. + * @param jwtAuthenticationConverter the converter to use + * @return the {@code JwtSpec} for additional configuration + * @since 5.1.1 + */ + public JwtSpec jwtAuthenticationConverter( + Converter> jwtAuthenticationConverter) { + Assert.notNull(jwtAuthenticationConverter, "jwtAuthenticationConverter cannot be null"); + this.jwtAuthenticationConverter = jwtAuthenticationConverter; + return this; + } + + /** + * Configures the {@link ReactiveJwtDecoder} to use + * @param jwtDecoder the decoder to use + * @return the {@code JwtSpec} for additional configuration + */ + public JwtSpec jwtDecoder(ReactiveJwtDecoder jwtDecoder) { + this.jwtDecoder = jwtDecoder; + return this; + } + + /** + * Configures a {@link ReactiveJwtDecoder} that leverages the provided + * {@link RSAPublicKey} + * @param publicKey the public key to use. + * @return the {@code JwtSpec} for additional configuration + */ + public JwtSpec publicKey(RSAPublicKey publicKey) { + this.jwtDecoder = new NimbusReactiveJwtDecoder(publicKey); + return this; + } + + /** + * Configures a {@link ReactiveJwtDecoder} using + * JSON Web Key + * (JWK) URL + * @param jwkSetUri the URL to use. + * @return the {@code JwtSpec} for additional configuration + */ + public JwtSpec jwkSetUri(String jwkSetUri) { + this.jwtDecoder = new NimbusReactiveJwtDecoder(jwkSetUri); + return this; + } + + public OAuth2ResourceServerSpec and() { + return OAuth2ResourceServerSpec.this; + } + + protected void configure(ServerHttpSecurity http) { + ReactiveAuthenticationManager authenticationManager = getAuthenticationManager(); + AuthenticationWebFilter oauth2 = new BearerTokenAuthenticationWebFilter(authenticationManager); + oauth2.setServerAuthenticationConverter(OAuth2ResourceServerSpec.this.bearerTokenConverter); + oauth2.setAuthenticationFailureHandler( + new ServerAuthenticationEntryPointFailureHandler(OAuth2ResourceServerSpec.this.entryPoint)); + // @formatter:off + http + .addFilterAt(oauth2, SecurityWebFiltersOrder.AUTHENTICATION); + // @formatter:on + } + + protected ReactiveJwtDecoder getJwtDecoder() { + if (this.jwtDecoder == null) { + return getBean(ReactiveJwtDecoder.class); + } + return this.jwtDecoder; + } + + protected Converter> getJwtAuthenticationConverter() { + + return this.jwtAuthenticationConverter; + } + + private ReactiveAuthenticationManager getAuthenticationManager() { + if (this.authenticationManager != null) { + return this.authenticationManager; + } + + ReactiveJwtDecoder jwtDecoder = getJwtDecoder(); + Converter> jwtAuthenticationConverter = getJwtAuthenticationConverter(); + JwtReactiveAuthenticationManager authenticationManager = new JwtReactiveAuthenticationManager( + jwtDecoder); + authenticationManager.setJwtAuthenticationConverter(jwtAuthenticationConverter); + + return authenticationManager; + } + + } + + /** + * Configures Opaque Token Resource Server support + * + * @author Josh Cummings + * @since 5.2 + */ + public final class OpaqueTokenSpec { + + private String introspectionUri; + + private String clientId; + + private String clientSecret; + + private Supplier introspector; + + private OpaqueTokenSpec() { + } + + /** + * Configures the URI of the Introspection endpoint + * @param introspectionUri The URI of the Introspection endpoint + * @return the {@code OpaqueTokenSpec} for additional configuration + */ + public OpaqueTokenSpec introspectionUri(String introspectionUri) { + Assert.hasText(introspectionUri, "introspectionUri cannot be empty"); + this.introspectionUri = introspectionUri; + this.introspector = () -> new NimbusReactiveOpaqueTokenIntrospector(this.introspectionUri, + this.clientId, this.clientSecret); + return this; + } + + /** + * Configures the credentials for Introspection endpoint + * @param clientId The clientId part of the credentials + * @param clientSecret The clientSecret part of the credentials + * @return the {@code OpaqueTokenSpec} for additional configuration + */ + public OpaqueTokenSpec introspectionClientCredentials(String clientId, String clientSecret) { + Assert.hasText(clientId, "clientId cannot be empty"); + Assert.notNull(clientSecret, "clientSecret cannot be null"); + this.clientId = clientId; + this.clientSecret = clientSecret; + this.introspector = () -> new NimbusReactiveOpaqueTokenIntrospector(this.introspectionUri, + this.clientId, this.clientSecret); + return this; + } + + public OpaqueTokenSpec introspector(ReactiveOpaqueTokenIntrospector introspector) { + Assert.notNull(introspector, "introspector cannot be null"); + this.introspector = () -> introspector; + return this; + } + + /** + * Allows method chaining to continue configuring the + * {@link ServerHttpSecurity} + * @return the {@link ServerHttpSecurity} to continue configuring + */ + public OAuth2ResourceServerSpec and() { + return OAuth2ResourceServerSpec.this; + } + + protected ReactiveAuthenticationManager getAuthenticationManager() { + return new OpaqueTokenReactiveAuthenticationManager(getIntrospector()); + } + + protected ReactiveOpaqueTokenIntrospector getIntrospector() { + if (this.introspector != null) { + return this.introspector.get(); + } + return getBean(ReactiveOpaqueTokenIntrospector.class); + } + + protected void configure(ServerHttpSecurity http) { + ReactiveAuthenticationManager authenticationManager = getAuthenticationManager(); + AuthenticationWebFilter oauth2 = new BearerTokenAuthenticationWebFilter(authenticationManager); + oauth2.setServerAuthenticationConverter(OAuth2ResourceServerSpec.this.bearerTokenConverter); + oauth2.setAuthenticationFailureHandler( + new ServerAuthenticationEntryPointFailureHandler(OAuth2ResourceServerSpec.this.entryPoint)); + http.addFilterAt(oauth2, SecurityWebFiltersOrder.AUTHENTICATION); + } + + } + + } + /** * Configures anonymous authentication * diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/AuthenticationManagerBuilderTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/AuthenticationManagerBuilderTests.java index 2f52e4f7b5..fa6bf9e5fa 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/AuthenticationManagerBuilderTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/AuthenticationManagerBuilderTests.java @@ -68,6 +68,9 @@ public class AuthenticationManagerBuilderTests { @Rule public final SpringTestRule spring = new SpringTestRule(); + @Autowired(required = false) + MockMvc mockMvc; + @Test public void buildWhenAddAuthenticationProviderThenDoesNotPerformRegistration() throws Exception { ObjectPostProcessor opp = mock(ObjectPostProcessor.class); @@ -110,25 +113,6 @@ public class AuthenticationManagerBuilderTests { assertThat(auth.getAuthorities()).extracting(GrantedAuthority::getAuthority).containsOnly("ROLE_USER"); } - @EnableWebSecurity - static class PasswordEncoderGlobalConfig extends WebSecurityConfigurerAdapter { - - @Autowired - void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { - // @formatter:off - auth - .inMemoryAuthentication() - .withUser("user").password("password").roles("USER"); - // @formatter:on - } - - @Bean - PasswordEncoder passwordEncoder() { - return NoOpPasswordEncoder.getInstance(); - } - - } - @Test public void getAuthenticationManagerWhenProtectedPasswordEncoderBeanThenUsed() throws Exception { this.spring.register(PasswordEncoderGlobalConfig.class).autowire(); @@ -141,28 +125,6 @@ public class AuthenticationManagerBuilderTests { assertThat(auth.getAuthorities()).extracting(GrantedAuthority::getAuthority).containsOnly("ROLE_USER"); } - @EnableWebSecurity - static class PasswordEncoderConfig extends WebSecurityConfigurerAdapter { - - @Override - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - // @formatter:off - auth - .inMemoryAuthentication() - .withUser("user").password("password").roles("USER"); - // @formatter:on - } - - @Bean - PasswordEncoder passwordEncoder() { - return NoOpPasswordEncoder.getInstance(); - } - - } - - @Autowired(required = false) - MockMvc mockMvc; - @Test public void authenticationManagerWhenMultipleProvidersThenWorks() throws Exception { this.spring.register(MultiAuthenticationProvidersConfig.class).autowire(); @@ -173,17 +135,6 @@ public class AuthenticationManagerBuilderTests { .andExpect(authenticated().withUsername("admin").withRoles("USER", "ADMIN")); } - @EnableWebSecurity - static class MultiAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter { - - @Override - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth.inMemoryAuthentication().withUser(PasswordEncodedUser.user()).and().inMemoryAuthentication() - .withUser(PasswordEncodedUser.admin()); - } - - } - @Test public void buildWhenAuthenticationProviderThenIsConfigured() throws Exception { ObjectPostProcessor opp = mock(ObjectPostProcessor.class); @@ -225,6 +176,55 @@ public class AuthenticationManagerBuilderTests { .andExpect(authenticated().withUsername("joe").withRoles("USER")); } + @EnableWebSecurity + static class MultiAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication().withUser(PasswordEncodedUser.user()).and().inMemoryAuthentication() + .withUser(PasswordEncodedUser.admin()); + } + + } + + @EnableWebSecurity + static class PasswordEncoderGlobalConfig extends WebSecurityConfigurerAdapter { + + @Autowired + void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off + auth + .inMemoryAuthentication() + .withUser("user").password("password").roles("USER"); + // @formatter:on + } + + @Bean + PasswordEncoder passwordEncoder() { + return NoOpPasswordEncoder.getInstance(); + } + + } + + @EnableWebSecurity + static class PasswordEncoderConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off + auth + .inMemoryAuthentication() + .withUser("user").password("password").roles("USER"); + // @formatter:on + } + + @Bean + PasswordEncoder passwordEncoder() { + return NoOpPasswordEncoder.getInstance(); + } + + } + @Configuration @EnableGlobalAuthentication @Import(ObjectPostProcessorConfiguration.class) diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationManagerTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationManagerTests.java index 6aa34abb27..4f924e7878 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationManagerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationManagerTests.java @@ -53,6 +53,27 @@ public class NamespaceAuthenticationManagerTests { // no exception due to username being cleared out } + @Test + public void authenticationMangerWhenEraseCredentialsIsFalseThenCredentialsNotNull() throws Exception { + this.spring.register(EraseCredentialsFalseConfig.class).autowire(); + + this.mockMvc.perform(formLogin()) + .andExpect(authenticated().withAuthentication(a -> assertThat(a.getCredentials()).isNotNull())); + + this.mockMvc.perform(formLogin()) + .andExpect(authenticated().withAuthentication(a -> assertThat(a.getCredentials()).isNotNull())); + // no exception due to username being cleared out + } + + @Test + // SEC-2533 + public void authenticationManagerWhenGlobalAndEraseCredentialsIsFalseThenCredentialsNotNull() throws Exception { + this.spring.register(GlobalEraseCredentialsFalseConfig.class).autowire(); + + this.mockMvc.perform(formLogin()) + .andExpect(authenticated().withAuthentication(a -> assertThat(a.getCredentials()).isNotNull())); + } + @EnableWebSecurity static class EraseCredentialsTrueDefaultConfig extends WebSecurityConfigurerAdapter { @@ -67,18 +88,6 @@ public class NamespaceAuthenticationManagerTests { } - @Test - public void authenticationMangerWhenEraseCredentialsIsFalseThenCredentialsNotNull() throws Exception { - this.spring.register(EraseCredentialsFalseConfig.class).autowire(); - - this.mockMvc.perform(formLogin()) - .andExpect(authenticated().withAuthentication(a -> assertThat(a.getCredentials()).isNotNull())); - - this.mockMvc.perform(formLogin()) - .andExpect(authenticated().withAuthentication(a -> assertThat(a.getCredentials()).isNotNull())); - // no exception due to username being cleared out - } - @EnableWebSecurity static class EraseCredentialsFalseConfig extends WebSecurityConfigurerAdapter { @@ -94,15 +103,6 @@ public class NamespaceAuthenticationManagerTests { } - @Test - // SEC-2533 - public void authenticationManagerWhenGlobalAndEraseCredentialsIsFalseThenCredentialsNotNull() throws Exception { - this.spring.register(GlobalEraseCredentialsFalseConfig.class).autowire(); - - this.mockMvc.perform(formLogin()) - .andExpect(authenticated().withAuthentication(a -> assertThat(a.getCredentials()).isNotNull())); - } - @EnableWebSecurity static class GlobalEraseCredentialsFalseConfig extends WebSecurityConfigurerAdapter { diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationProviderTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationProviderTests.java index ed63199915..aa3853f0f6 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationProviderTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationProviderTests.java @@ -53,6 +53,14 @@ public class NamespaceAuthenticationProviderTests { this.mockMvc.perform(formLogin()).andExpect(authenticated().withUsername("user")); } + @Test + // authentication-provider@user-service-ref + public void authenticationProviderUserServiceRef() throws Exception { + this.spring.register(AuthenticationProviderRefConfig.class).autowire(); + + this.mockMvc.perform(formLogin()).andExpect(authenticated().withUsername("user")); + } + @EnableWebSecurity static class AuthenticationProviderRefConfig extends WebSecurityConfigurerAdapter { @@ -73,14 +81,6 @@ public class NamespaceAuthenticationProviderTests { } - @Test - // authentication-provider@user-service-ref - public void authenticationProviderUserServiceRef() throws Exception { - this.spring.register(AuthenticationProviderRefConfig.class).autowire(); - - this.mockMvc.perform(formLogin()).andExpect(authenticated().withUsername("user")); - } - @EnableWebSecurity static class UserServiceRefConfig extends WebSecurityConfigurerAdapter { diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceJdbcUserServiceTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceJdbcUserServiceTests.java index bf3c3d4994..64c6c455e2 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceJdbcUserServiceTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceJdbcUserServiceTests.java @@ -57,6 +57,13 @@ public class NamespaceJdbcUserServiceTests { this.mockMvc.perform(formLogin()).andExpect(authenticated().withUsername("user")); } + @Test + public void jdbcUserServiceCustom() throws Exception { + this.spring.register(CustomDataSourceConfig.class, CustomJdbcUserServiceSampleConfig.class).autowire(); + + this.mockMvc.perform(formLogin()).andExpect(authenticated().withUsername("user").withRoles("DBA", "USER")); + } + @EnableWebSecurity static class JdbcUserServiceConfig extends WebSecurityConfigurerAdapter { @@ -87,13 +94,6 @@ public class NamespaceJdbcUserServiceTests { } - @Test - public void jdbcUserServiceCustom() throws Exception { - this.spring.register(CustomDataSourceConfig.class, CustomJdbcUserServiceSampleConfig.class).autowire(); - - this.mockMvc.perform(formLogin()).andExpect(authenticated().withUsername("user").withRoles("DBA", "USER")); - } - @EnableWebSecurity static class CustomJdbcUserServiceSampleConfig extends WebSecurityConfigurerAdapter { diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespacePasswordEncoderTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespacePasswordEncoderTests.java index 1288673c9e..a535a1874b 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespacePasswordEncoderTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/NamespacePasswordEncoderTests.java @@ -56,6 +56,20 @@ public class NamespacePasswordEncoderTests { this.mockMvc.perform(formLogin()).andExpect(authenticated()); } + @Test + public void passwordEncoderRefWithJdbc() throws Exception { + this.spring.register(PasswordEncoderWithJdbcConfig.class).autowire(); + + this.mockMvc.perform(formLogin()).andExpect(authenticated()); + } + + @Test + public void passwordEncoderRefWithUserDetailsService() throws Exception { + this.spring.register(PasswordEncoderWithUserDetailsServiceConfig.class).autowire(); + + this.mockMvc.perform(formLogin()).andExpect(authenticated()); + } + @EnableWebSecurity static class PasswordEncoderWithInMemoryConfig extends WebSecurityConfigurerAdapter { @@ -72,13 +86,6 @@ public class NamespacePasswordEncoderTests { } - @Test - public void passwordEncoderRefWithJdbc() throws Exception { - this.spring.register(PasswordEncoderWithJdbcConfig.class).autowire(); - - this.mockMvc.perform(formLogin()).andExpect(authenticated()); - } - @EnableWebSecurity static class PasswordEncoderWithJdbcConfig extends WebSecurityConfigurerAdapter { @@ -104,13 +111,6 @@ public class NamespacePasswordEncoderTests { } - @Test - public void passwordEncoderRefWithUserDetailsService() throws Exception { - this.spring.register(PasswordEncoderWithUserDetailsServiceConfig.class).autowire(); - - this.mockMvc.perform(formLogin()).andExpect(authenticated()); - } - @EnableWebSecurity static class PasswordEncoderWithUserDetailsServiceConfig extends WebSecurityConfigurerAdapter { diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/PasswordEncoderConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/PasswordEncoderConfigurerTests.java index 88c3464ebc..85c46ab747 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/PasswordEncoderConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/PasswordEncoderConfigurerTests.java @@ -48,6 +48,13 @@ public class PasswordEncoderConfigurerTests { this.spring.register(PasswordEncoderConfig.class).autowire(); } + @Test + public void passwordEncoderRefWhenAuthenticationManagerBuilderThenAuthenticationSuccess() throws Exception { + this.spring.register(PasswordEncoderNoAuthManagerLoadsConfig.class).autowire(); + + this.mockMvc.perform(formLogin()).andExpect(authenticated()); + } + @EnableWebSecurity static class PasswordEncoderConfig extends WebSecurityConfigurerAdapter { @@ -73,13 +80,6 @@ public class PasswordEncoderConfigurerTests { } - @Test - public void passwordEncoderRefWhenAuthenticationManagerBuilderThenAuthenticationSuccess() throws Exception { - this.spring.register(PasswordEncoderNoAuthManagerLoadsConfig.class).autowire(); - - this.mockMvc.perform(formLogin()).andExpect(authenticated()); - } - @EnableWebSecurity static class PasswordEncoderNoAuthManagerLoadsConfig extends WebSecurityConfigurerAdapter { diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationTests.java index d42c638cb3..e091dcecb1 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationTests.java @@ -93,11 +93,6 @@ public class AuthenticationConfigurationTests { this.service.run(); } - @EnableGlobalMethodSecurity(securedEnabled = true) - static class GlobalMethodSecurityAutowiredConfig { - - } - @Test public void orderingAutowiredOnEnableWebSecurity() { this.spring.register(AuthenticationTestConfiguration.class, WebSecurityConfig.class, @@ -108,11 +103,6 @@ public class AuthenticationConfigurationTests { this.service.run(); } - @EnableWebSecurity - static class WebSecurityConfig { - - } - @Test public void orderingAutowiredOnEnableWebMvcSecurity() { this.spring.register(AuthenticationTestConfiguration.class, WebMvcSecurityConfig.class, @@ -123,11 +113,6 @@ public class AuthenticationConfigurationTests { this.service.run(); } - @EnableWebMvcSecurity - static class WebMvcSecurityConfig { - - } - @Test public void getAuthenticationManagerWhenNoAuthenticationThenNull() throws Exception { this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class).autowire(); @@ -145,11 +130,6 @@ public class AuthenticationConfigurationTests { .isNull(); } - @Configuration - static class NoOpGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { - - } - @Test public void getAuthenticationWhenGlobalAuthenticationConfigurerAdapterThenAuthenticates() throws Exception { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password"); @@ -162,16 +142,6 @@ public class AuthenticationConfigurationTests { assertThat(authentication.authenticate(token).getName()).isEqualTo(token.getName()); } - @Configuration - static class UserGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { - - @Override - public void init(AuthenticationManagerBuilder auth) throws Exception { - auth.inMemoryAuthentication().withUser(PasswordEncodedUser.user()); - } - - } - @Test public void getAuthenticationWhenAuthenticationManagerBeanThenAuthenticates() throws Exception { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password"); @@ -185,6 +155,200 @@ public class AuthenticationConfigurationTests { assertThat(authentication.authenticate(token).getName()).isEqualTo(token.getName()); } + @Test + public void getAuthenticationWhenMultipleThenOrdered() throws Exception { + this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class, + AuthenticationManagerBeanConfig.class).autowire(); + AuthenticationConfiguration config = this.spring.getContext().getBean(AuthenticationConfiguration.class); + config.setGlobalAuthenticationConfigurers(Arrays.asList(new LowestOrderGlobalAuthenticationConfigurerAdapter(), + new HighestOrderGlobalAuthenticationConfigurerAdapter(), + new DefaultOrderGlobalAuthenticationConfigurerAdapter())); + } + + @Test + public void getAuthenticationWhenConfiguredThenBootNotTrigger() throws Exception { + this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class).autowire(); + AuthenticationConfiguration config = this.spring.getContext().getBean(AuthenticationConfiguration.class); + config.setGlobalAuthenticationConfigurers(Arrays.asList(new ConfiguresInMemoryConfigurerAdapter(), + new BootGlobalAuthenticationConfigurerAdapter())); + AuthenticationManager authenticationManager = config.getAuthenticationManager(); + + authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); + + assertThatThrownBy( + () -> authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("boot", "password"))) + .isInstanceOf(AuthenticationException.class); + + } + + @Test + public void getAuthenticationWhenNotConfiguredThenBootTrigger() throws Exception { + this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class).autowire(); + AuthenticationConfiguration config = this.spring.getContext().getBean(AuthenticationConfiguration.class); + config.setGlobalAuthenticationConfigurers(Arrays.asList(new BootGlobalAuthenticationConfigurerAdapter())); + AuthenticationManager authenticationManager = config.getAuthenticationManager(); + + authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("boot", "password")); + } + + // gh-2531 + @Test + public void getAuthenticationManagerWhenPostProcessThenUsesBeanClassLoaderOnProxyFactoryBean() throws Exception { + this.spring.register(Sec2531Config.class).autowire(); + ObjectPostProcessor opp = this.spring.getContext().getBean(ObjectPostProcessor.class); + when(opp.postProcess(any())).thenAnswer(a -> a.getArgument(0)); + + AuthenticationConfiguration config = this.spring.getContext().getBean(AuthenticationConfiguration.class); + config.getAuthenticationManager(); + + verify(opp).postProcess(any(ProxyFactoryBean.class)); + } + + @Test + public void getAuthenticationManagerWhenSec2822ThenCannotForceAuthenticationAlreadyBuilt() throws Exception { + this.spring.register(Sec2822WebSecurity.class, Sec2822UseAuth.class, Sec2822Config.class).autowire(); + + this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager(); + // no exception + } + + // sec-2868 + @Test + public void getAuthenticationWhenUserDetailsServiceBeanThenAuthenticationManagerUsesUserDetailsServiceBean() + throws Exception { + this.spring.register(UserDetailsServiceBeanConfig.class).autowire(); + UserDetailsService uds = this.spring.getContext().getBean(UserDetailsService.class); + AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class) + .getAuthenticationManager(); + when(uds.loadUserByUsername("user")).thenReturn(PasswordEncodedUser.user(), PasswordEncodedUser.user()); + + am.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); + + assertThatThrownBy(() -> am.authenticate(new UsernamePasswordAuthenticationToken("user", "invalid"))) + .isInstanceOf(AuthenticationException.class); + } + + @Test + public void getAuthenticationWhenUserDetailsServiceAndPasswordEncoderBeanThenEncoderUsed() throws Exception { + UserDetails user = new User("user", "$2a$10$FBAKClV1zBIOOC9XMXf3AO8RoGXYVYsfvUdoLxGkd/BnXEn4tqT3u", + AuthorityUtils.createAuthorityList("ROLE_USER")); + this.spring.register(UserDetailsServiceBeanWithPasswordEncoderConfig.class).autowire(); + UserDetailsService uds = this.spring.getContext().getBean(UserDetailsService.class); + AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class) + .getAuthenticationManager(); + when(uds.loadUserByUsername("user")).thenReturn(User.withUserDetails(user).build(), + User.withUserDetails(user).build()); + + am.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); + + assertThatThrownBy(() -> am.authenticate(new UsernamePasswordAuthenticationToken("user", "invalid"))) + .isInstanceOf(AuthenticationException.class); + } + + @Test + public void getAuthenticationWhenUserDetailsServiceAndPasswordManagerThenManagerUsed() throws Exception { + UserDetails user = new User("user", "{noop}password", AuthorityUtils.createAuthorityList("ROLE_USER")); + this.spring.register(UserDetailsPasswordManagerBeanConfig.class).autowire(); + UserDetailsPasswordManagerBeanConfig.Manager manager = this.spring.getContext() + .getBean(UserDetailsPasswordManagerBeanConfig.Manager.class); + AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class) + .getAuthenticationManager(); + when(manager.loadUserByUsername("user")).thenReturn(User.withUserDetails(user).build(), + User.withUserDetails(user).build()); + when(manager.updatePassword(any(), any())).thenReturn(user); + + am.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); + + verify(manager).updatePassword(eq(user), startsWith("{bcrypt}")); + } + + @Test + public void getAuthenticationWhenAuthenticationProviderAndUserDetailsBeanThenAuthenticationProviderUsed() + throws Exception { + this.spring.register(AuthenticationProviderBeanAndUserDetailsServiceConfig.class).autowire(); + AuthenticationProvider ap = this.spring.getContext().getBean(AuthenticationProvider.class); + AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class) + .getAuthenticationManager(); + when(ap.supports(any())).thenReturn(true); + when(ap.authenticate(any())).thenReturn(TestAuthentication.authenticatedUser()); + + am.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); + } + + // gh-3091 + @Test + public void getAuthenticationWhenAuthenticationProviderBeanThenUsed() throws Exception { + this.spring.register(AuthenticationProviderBeanConfig.class).autowire(); + AuthenticationProvider ap = this.spring.getContext().getBean(AuthenticationProvider.class); + AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class) + .getAuthenticationManager(); + when(ap.supports(any())).thenReturn(true); + when(ap.authenticate(any())).thenReturn(TestAuthentication.authenticatedUser()); + + am.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); + } + + @Test + public void enableGlobalMethodSecurityWhenPreAuthorizeThenNoException() { + this.spring.register(UsesPreAuthorizeMethodSecurityConfig.class, AuthenticationManagerBeanConfig.class) + .autowire(); + // no exception + } + + @Test + public void enableGlobalMethodSecurityWhenPreAuthorizeThenUsesMethodSecurityService() { + this.spring.register(ServicesConfig.class, UsesPreAuthorizeMethodSecurityConfig.class, + AuthenticationManagerBeanConfig.class).autowire(); + // no exception + } + + @Test + public void getAuthenticationManagerBeanWhenMultipleDefinedAndOnePrimaryThenNoException() throws Exception { + this.spring.register(MultipleAuthenticationManagerBeanConfig.class).autowire(); + this.spring.getContext().getBeanFactory().getBean(AuthenticationConfiguration.class).getAuthenticationManager(); + } + + @Test + public void getAuthenticationManagerWhenAuthenticationConfigurationSubclassedThenBuildsUsingBean() + throws Exception { + this.spring.register(AuthenticationConfigurationSubclass.class).autowire(); + AuthenticationManagerBuilder ap = this.spring.getContext().getBean(AuthenticationManagerBuilder.class); + + this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager(); + + assertThatThrownBy(ap::build).isInstanceOf(AlreadyBuiltException.class); + } + + @EnableGlobalMethodSecurity(securedEnabled = true) + static class GlobalMethodSecurityAutowiredConfig { + + } + + @EnableWebSecurity + static class WebSecurityConfig { + + } + + @EnableWebMvcSecurity + static class WebMvcSecurityConfig { + + } + + @Configuration + static class NoOpGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { + + } + + @Configuration + static class UserGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { + + @Override + public void init(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication().withUser(PasswordEncodedUser.user()); + } + + } + @Configuration static class AuthenticationManagerBeanConfig { @@ -197,9 +361,6 @@ public class AuthenticationConfigurationTests { } - // - // // - // @Configuration static class ServicesConfig { @@ -225,16 +386,6 @@ public class AuthenticationConfigurationTests { } - @Test - public void getAuthenticationWhenMultipleThenOrdered() throws Exception { - this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class, - AuthenticationManagerBeanConfig.class).autowire(); - AuthenticationConfiguration config = this.spring.getContext().getBean(AuthenticationConfiguration.class); - config.setGlobalAuthenticationConfigurers(Arrays.asList(new LowestOrderGlobalAuthenticationConfigurerAdapter(), - new HighestOrderGlobalAuthenticationConfigurerAdapter(), - new DefaultOrderGlobalAuthenticationConfigurerAdapter())); - } - static class DefaultOrderGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { static List> inits = new ArrayList<>(); @@ -264,32 +415,6 @@ public class AuthenticationConfigurationTests { } - @Test - public void getAuthenticationWhenConfiguredThenBootNotTrigger() throws Exception { - this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class).autowire(); - AuthenticationConfiguration config = this.spring.getContext().getBean(AuthenticationConfiguration.class); - config.setGlobalAuthenticationConfigurers(Arrays.asList(new ConfiguresInMemoryConfigurerAdapter(), - new BootGlobalAuthenticationConfigurerAdapter())); - AuthenticationManager authenticationManager = config.getAuthenticationManager(); - - authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); - - assertThatThrownBy( - () -> authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("boot", "password"))) - .isInstanceOf(AuthenticationException.class); - - } - - @Test - public void getAuthenticationWhenNotConfiguredThenBootTrigger() throws Exception { - this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class).autowire(); - AuthenticationConfiguration config = this.spring.getContext().getBean(AuthenticationConfiguration.class); - config.setGlobalAuthenticationConfigurers(Arrays.asList(new BootGlobalAuthenticationConfigurerAdapter())); - AuthenticationManager authenticationManager = config.getAuthenticationManager(); - - authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("boot", "password")); - } - static class ConfiguresInMemoryConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { @Override @@ -335,19 +460,6 @@ public class AuthenticationConfigurationTests { } - // gh-2531 - @Test - public void getAuthenticationManagerWhenPostProcessThenUsesBeanClassLoaderOnProxyFactoryBean() throws Exception { - this.spring.register(Sec2531Config.class).autowire(); - ObjectPostProcessor opp = this.spring.getContext().getBean(ObjectPostProcessor.class); - when(opp.postProcess(any())).thenAnswer(a -> a.getArgument(0)); - - AuthenticationConfiguration config = this.spring.getContext().getBean(AuthenticationConfiguration.class); - config.getAuthenticationManager(); - - verify(opp).postProcess(any(ProxyFactoryBean.class)); - } - @Configuration @Import(AuthenticationConfiguration.class) static class Sec2531Config { @@ -364,14 +476,6 @@ public class AuthenticationConfigurationTests { } - @Test - public void getAuthenticationManagerWhenSec2822ThenCannotForceAuthenticationAlreadyBuilt() throws Exception { - this.spring.register(Sec2822WebSecurity.class, Sec2822UseAuth.class, Sec2822Config.class).autowire(); - - this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager(); - // no exception - } - @Configuration @Import(AuthenticationConfiguration.class) static class Sec2822Config { @@ -410,22 +514,6 @@ public class AuthenticationConfigurationTests { } - // sec-2868 - @Test - public void getAuthenticationWhenUserDetailsServiceBeanThenAuthenticationManagerUsesUserDetailsServiceBean() - throws Exception { - this.spring.register(UserDetailsServiceBeanConfig.class).autowire(); - UserDetailsService uds = this.spring.getContext().getBean(UserDetailsService.class); - AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class) - .getAuthenticationManager(); - when(uds.loadUserByUsername("user")).thenReturn(PasswordEncodedUser.user(), PasswordEncodedUser.user()); - - am.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); - - assertThatThrownBy(() -> am.authenticate(new UsernamePasswordAuthenticationToken("user", "invalid"))) - .isInstanceOf(AuthenticationException.class); - } - @Configuration @Import({ AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class }) static class UserDetailsServiceBeanConfig { @@ -439,23 +527,6 @@ public class AuthenticationConfigurationTests { } - @Test - public void getAuthenticationWhenUserDetailsServiceAndPasswordEncoderBeanThenEncoderUsed() throws Exception { - UserDetails user = new User("user", "$2a$10$FBAKClV1zBIOOC9XMXf3AO8RoGXYVYsfvUdoLxGkd/BnXEn4tqT3u", - AuthorityUtils.createAuthorityList("ROLE_USER")); - this.spring.register(UserDetailsServiceBeanWithPasswordEncoderConfig.class).autowire(); - UserDetailsService uds = this.spring.getContext().getBean(UserDetailsService.class); - AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class) - .getAuthenticationManager(); - when(uds.loadUserByUsername("user")).thenReturn(User.withUserDetails(user).build(), - User.withUserDetails(user).build()); - - am.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); - - assertThatThrownBy(() -> am.authenticate(new UsernamePasswordAuthenticationToken("user", "invalid"))) - .isInstanceOf(AuthenticationException.class); - } - @Configuration @Import({ AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class }) static class UserDetailsServiceBeanWithPasswordEncoderConfig { @@ -474,23 +545,6 @@ public class AuthenticationConfigurationTests { } - @Test - public void getAuthenticationWhenUserDetailsServiceAndPasswordManagerThenManagerUsed() throws Exception { - UserDetails user = new User("user", "{noop}password", AuthorityUtils.createAuthorityList("ROLE_USER")); - this.spring.register(UserDetailsPasswordManagerBeanConfig.class).autowire(); - UserDetailsPasswordManagerBeanConfig.Manager manager = this.spring.getContext() - .getBean(UserDetailsPasswordManagerBeanConfig.Manager.class); - AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class) - .getAuthenticationManager(); - when(manager.loadUserByUsername("user")).thenReturn(User.withUserDetails(user).build(), - User.withUserDetails(user).build()); - when(manager.updatePassword(any(), any())).thenReturn(user); - - am.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); - - verify(manager).updatePassword(eq(user), startsWith("{bcrypt}")); - } - @Configuration @Import({ AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class }) static class UserDetailsPasswordManagerBeanConfig { @@ -508,19 +562,6 @@ public class AuthenticationConfigurationTests { } - // gh-3091 - @Test - public void getAuthenticationWhenAuthenticationProviderBeanThenUsed() throws Exception { - this.spring.register(AuthenticationProviderBeanConfig.class).autowire(); - AuthenticationProvider ap = this.spring.getContext().getBean(AuthenticationProvider.class); - AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class) - .getAuthenticationManager(); - when(ap.supports(any())).thenReturn(true); - when(ap.authenticate(any())).thenReturn(TestAuthentication.authenticatedUser()); - - am.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); - } - @Configuration @Import({ AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class }) static class AuthenticationProviderBeanConfig { @@ -534,19 +575,6 @@ public class AuthenticationConfigurationTests { } - @Test - public void getAuthenticationWhenAuthenticationProviderAndUserDetailsBeanThenAuthenticationProviderUsed() - throws Exception { - this.spring.register(AuthenticationProviderBeanAndUserDetailsServiceConfig.class).autowire(); - AuthenticationProvider ap = this.spring.getContext().getBean(AuthenticationProvider.class); - AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class) - .getAuthenticationManager(); - when(ap.supports(any())).thenReturn(true); - when(ap.authenticate(any())).thenReturn(TestAuthentication.authenticatedUser()); - - am.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); - } - @Configuration @Import({ AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class }) static class AuthenticationProviderBeanAndUserDetailsServiceConfig { @@ -567,14 +595,6 @@ public class AuthenticationConfigurationTests { } - @Test - public void enableGlobalMethodSecurityWhenPreAuthorizeThenNoException() { - this.spring.register(UsesPreAuthorizeMethodSecurityConfig.class, AuthenticationManagerBeanConfig.class) - .autowire(); - - // no exception - } - @Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) static class UsesPreAuthorizeMethodSecurityConfig { @@ -585,14 +605,6 @@ public class AuthenticationConfigurationTests { } - @Test - public void enableGlobalMethodSecurityWhenPreAuthorizeThenUsesMethodSecurityService() { - this.spring.register(ServicesConfig.class, UsesPreAuthorizeMethodSecurityConfig.class, - AuthenticationManagerBeanConfig.class).autowire(); - - // no exception - } - @Configuration @EnableGlobalMethodSecurity(securedEnabled = true) static class UsesServiceMethodSecurityConfig { @@ -602,12 +614,6 @@ public class AuthenticationConfigurationTests { } - @Test - public void getAuthenticationManagerBeanWhenMultipleDefinedAndOnePrimaryThenNoException() throws Exception { - this.spring.register(MultipleAuthenticationManagerBeanConfig.class).autowire(); - this.spring.getContext().getBeanFactory().getBean(AuthenticationConfiguration.class).getAuthenticationManager(); - } - @Configuration @Import(AuthenticationConfiguration.class) static class MultipleAuthenticationManagerBeanConfig { @@ -625,17 +631,6 @@ public class AuthenticationConfigurationTests { } - @Test - public void getAuthenticationManagerWhenAuthenticationConfigurationSubclassedThenBuildsUsingBean() - throws Exception { - this.spring.register(AuthenticationConfigurationSubclass.class).autowire(); - AuthenticationManagerBuilder ap = this.spring.getContext().getBean(AuthenticationManagerBuilder.class); - - this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager(); - - assertThatThrownBy(ap::build).isInstanceOf(AlreadyBuiltException.class); - } - @Configuration static class AuthenticationConfigurationSubclass extends AuthenticationConfiguration { diff --git a/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/EnableGlobalAuthenticationTests.java b/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/EnableGlobalAuthenticationTests.java index c36a69936c..b854bd952f 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/EnableGlobalAuthenticationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/EnableGlobalAuthenticationTests.java @@ -45,6 +45,26 @@ public class EnableGlobalAuthenticationTests { assertThat(auth.getAuthenticationManager()).isNotNull(); } + @Test + public void enableGlobalAuthenticationWhenNoConfigurationAnnotationThenBeanProxyingEnabled() { + this.spring.register(BeanProxyEnabledByDefaultConfig.class).autowire(); + + Child childBean = this.spring.getContext().getBean(Child.class); + Parent parentBean = this.spring.getContext().getBean(Parent.class); + + assertThat(parentBean.getChild()).isSameAs(childBean); + } + + @Test + public void enableGlobalAuthenticationWhenProxyBeanMethodsFalseThenBeanProxyingDisabled() { + this.spring.register(BeanProxyDisabledConfig.class).autowire(); + + Child childBean = this.spring.getContext().getBean(Child.class); + Parent parentBean = this.spring.getContext().getBean(Parent.class); + + assertThat(parentBean.getChild()).isNotSameAs(childBean); + } + @Configuration @EnableGlobalAuthentication static class Config { @@ -56,16 +76,6 @@ public class EnableGlobalAuthenticationTests { } - @Test - public void enableGlobalAuthenticationWhenNoConfigurationAnnotationThenBeanProxyingEnabled() { - this.spring.register(BeanProxyEnabledByDefaultConfig.class).autowire(); - - Child childBean = this.spring.getContext().getBean(Child.class); - Parent parentBean = this.spring.getContext().getBean(Parent.class); - - assertThat(parentBean.getChild()).isSameAs(childBean); - } - @EnableGlobalAuthentication static class BeanProxyEnabledByDefaultConfig { @@ -81,16 +91,6 @@ public class EnableGlobalAuthenticationTests { } - @Test - public void enableGlobalAuthenticationWhenProxyBeanMethodsFalseThenBeanProxyingDisabled() { - this.spring.register(BeanProxyDisabledConfig.class).autowire(); - - Child childBean = this.spring.getContext().getBean(Child.class); - Parent parentBean = this.spring.getContext().getBean(Parent.class); - - assertThat(parentBean.getChild()).isNotSameAs(childBean); - } - @Configuration(proxyBeanMethods = false) @EnableGlobalAuthentication static class BeanProxyDisabledConfig { diff --git a/config/src/test/java/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessorTests.java b/config/src/test/java/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessorTests.java index 5c93b35afb..c24f59a092 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessorTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessorTests.java @@ -126,6 +126,25 @@ public class AutowireBeanFactoryObjectPostProcessorTests { verify(toPostProcess).destroy(); } + @Test + public void postProcessWhenSmartInitializingSingletonThenAwareInvoked() { + this.spring.register(Config.class, SmartConfig.class).autowire(); + + SmartConfig config = this.spring.getContext().getBean(SmartConfig.class); + + verify(config.toTest).afterSingletonsInstantiated(); + } + + @Test + // SEC-2382 + public void autowireBeanFactoryWhenBeanNameAutoProxyCreatorThenWorks() { + this.spring.testConfigLocations("AutowireBeanFactoryObjectPostProcessorTests-aopconfig.xml").autowire(); + + MyAdvisedBean bean = this.spring.getContext().getBean(MyAdvisedBean.class); + + assertThat(bean.doStuff()).isEqualTo("null"); + } + @Configuration static class Config { @@ -136,15 +155,6 @@ public class AutowireBeanFactoryObjectPostProcessorTests { } - @Test - public void postProcessWhenSmartInitializingSingletonThenAwareInvoked() { - this.spring.register(Config.class, SmartConfig.class).autowire(); - - SmartConfig config = this.spring.getContext().getBean(SmartConfig.class); - - verify(config.toTest).afterSingletonsInstantiated(); - } - @Configuration static class SmartConfig { @@ -157,16 +167,6 @@ public class AutowireBeanFactoryObjectPostProcessorTests { } - @Test - // SEC-2382 - public void autowireBeanFactoryWhenBeanNameAutoProxyCreatorThenWorks() { - this.spring.testConfigLocations("AutowireBeanFactoryObjectPostProcessorTests-aopconfig.xml").autowire(); - - MyAdvisedBean bean = this.spring.getContext().getBean(MyAdvisedBean.class); - - assertThat(bean.doStuff()).isEqualTo("null"); - } - @Configuration static class WithBeanNameAutoProxyCreatorConfig { diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.java index 93f787f010..697f72734a 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.java @@ -101,27 +101,11 @@ public class GlobalMethodSecurityConfigurationTests { this.spring.register(IllegalStateGlobalMethodSecurityConfig.class).autowire(); } - @EnableGlobalMethodSecurity - public static class IllegalStateGlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration { - - } - @Test public void configureWhenGlobalMethodSecurityHasCustomMetadataSourceThenNoEnablingAttributeIsNeeded() { this.spring.register(CustomMetadataSourceConfig.class).autowire(); } - @EnableGlobalMethodSecurity - public static class CustomMetadataSourceConfig extends GlobalMethodSecurityConfiguration { - - @Bean - @Override - protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() { - return mock(MethodSecurityMetadataSource.class); - } - - } - @Test public void methodSecurityAuthenticationManagerPublishesEvent() { this.spring.register(InMemoryAuthWithGlobalMethodSecurityConfig.class).autowire(); @@ -136,25 +120,6 @@ public class GlobalMethodSecurityConfigurationTests { .containsOnly((Class) AuthenticationFailureBadCredentialsEvent.class); } - @EnableGlobalMethodSecurity(prePostEnabled = true) - public static class InMemoryAuthWithGlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration { - - @Override - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - // @formatter:off - auth - .inMemoryAuthentication(); - // @formatter:on - } - - @Bean - public MockEventListener listener() { - return new MockEventListener() { - }; - } - - } - @Test @WithMockUser public void methodSecurityWhenAuthenticationTrustResolverIsBeanThenAutowires() { @@ -170,21 +135,6 @@ public class GlobalMethodSecurityConfigurationTests { verify(trustResolver, atLeastOnce()).isAnonymous(any()); } - @EnableGlobalMethodSecurity(prePostEnabled = true) - static class CustomTrustResolverConfig { - - @Bean - public AuthenticationTrustResolver trustResolver() { - return mock(AuthenticationTrustResolver.class); - } - - @Bean - public MethodSecurityServiceImpl service() { - return new MethodSecurityServiceImpl(); - } - - } - // SEC-2301 @Test @WithMockUser @@ -197,21 +147,6 @@ public class GlobalMethodSecurityConfigurationTests { this.service.preAuthorizeBean(true); } - @EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true) - static class ExpressionHandlerHasBeanResolverSetConfig { - - @Bean - public MethodSecurityServiceImpl service() { - return new MethodSecurityServiceImpl(); - } - - @Bean - public Authz authz() { - return new Authz(); - } - - } - @Test @WithMockUser public void methodSecuritySupportsAnnotaitonsOnInterfaceParamerNames() { @@ -223,16 +158,6 @@ public class GlobalMethodSecurityConfigurationTests { // no exception } - @EnableGlobalMethodSecurity(prePostEnabled = true) - static class MethodSecurityServiceConfig { - - @Bean - public MethodSecurityService service() { - return new MethodSecurityServiceImpl(); - } - - } - @Test @WithMockUser public void globalMethodSecurityConfigurationAutowiresPermissionEvaluator() { @@ -246,21 +171,6 @@ public class GlobalMethodSecurityConfigurationTests { assertThatThrownBy(() -> this.service.hasPermission("something")).isInstanceOf(AccessDeniedException.class); } - @EnableGlobalMethodSecurity(prePostEnabled = true) - public static class AutowirePermissionEvaluatorConfig { - - @Bean - public PermissionEvaluator permissionEvaluator() { - return mock(PermissionEvaluator.class); - } - - @Bean - public MethodSecurityService service() { - return new MethodSecurityServiceImpl(); - } - - } - @Test public void multiPermissionEvaluatorConfig() { this.spring.register(MultiPermissionEvaluatorConfig.class).autowire(); @@ -268,21 +178,6 @@ public class GlobalMethodSecurityConfigurationTests { // no exception } - @EnableGlobalMethodSecurity(prePostEnabled = true) - public static class MultiPermissionEvaluatorConfig { - - @Bean - public PermissionEvaluator permissionEvaluator() { - return mock(PermissionEvaluator.class); - } - - @Bean - public PermissionEvaluator permissionEvaluator2() { - return mock(PermissionEvaluator.class); - } - - } - // SEC-2425 @Test @WithMockUser @@ -292,21 +187,6 @@ public class GlobalMethodSecurityConfigurationTests { assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); } - @Configuration - static class ChildConfig extends ParentConfig { - - } - - @EnableGlobalMethodSecurity(prePostEnabled = true) - static class ParentConfig { - - @Bean - public MethodSecurityService service() { - return new MethodSecurityServiceImpl(); - } - - } - // SEC-2479 @Test @WithMockUser @@ -325,6 +205,221 @@ public class GlobalMethodSecurityConfigurationTests { } } + @Test + public void enableGlobalMethodSecurityDoesNotTriggerEagerInitializationOfBeansInGlobalAuthenticationConfigurer() { + this.spring.register(Sec2815Config.class).autowire(); + + MockBeanPostProcessor pp = this.spring.getContext().getBean(MockBeanPostProcessor.class); + + assertThat(pp.beforeInit).containsKeys("dataSource"); + assertThat(pp.afterInit).containsKeys("dataSource"); + } + + // SEC-3045 + @Test + public void globalSecurityProxiesSecurity() { + this.spring.register(Sec3005Config.class).autowire(); + + assertThat(this.service.getClass()).matches(c -> !Proxy.isProxyClass(c), "is not proxy class"); + } + // + // // gh-3797 + // def preAuthorizeBeanSpel() { + // setup: + // SecurityContextHolder.getContext().setAuthentication( + // new TestingAuthenticationToken("user", "password","ROLE_USER")) + // context = new AnnotationConfigApplicationContext(PreAuthorizeBeanSpelConfig) + // BeanSpelService service = context.getBean(BeanSpelService) + // when: + // service.run(true) + // then: + // noExceptionThrown() + // when: + // service.run(false) + // then: + // thrown(AccessDeniedException) + // } + // + + @Test + @WithMockUser + public void preAuthorizeBeanSpel() { + this.spring.register(PreAuthorizeBeanSpelConfig.class).autowire(); + + assertThatThrownBy(() -> this.service.preAuthorizeBean(false)).isInstanceOf(AccessDeniedException.class); + + this.service.preAuthorizeBean(true); + } + + // gh-3394 + @Test + @WithMockUser + public void roleHierarchy() { + this.spring.register(RoleHierarchyConfig.class).autowire(); + + assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); + this.service.preAuthorizeAdmin(); + } + + @Test + @WithMockUser(authorities = "ROLE:USER") + public void grantedAuthorityDefaultsAutowires() { + this.spring.register(CustomGrantedAuthorityConfig.class).autowire(); + + CustomGrantedAuthorityConfig.CustomAuthorityService customService = this.spring.getContext() + .getBean(CustomGrantedAuthorityConfig.CustomAuthorityService.class); + + assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); + + customService.customPrefixRoleUser(); + // no exception + } + + @Test + @WithMockUser(authorities = "USER") + public void grantedAuthorityDefaultsWithEmptyRolePrefix() { + this.spring.register(EmptyRolePrefixGrantedAuthorityConfig.class).autowire(); + + EmptyRolePrefixGrantedAuthorityConfig.CustomAuthorityService customService = this.spring.getContext() + .getBean(EmptyRolePrefixGrantedAuthorityConfig.CustomAuthorityService.class); + + assertThatThrownBy(() -> this.service.securedUser()).isInstanceOf(AccessDeniedException.class); + + customService.emptyPrefixRoleUser(); + // no exception + } + + @Test + public void methodSecurityInterceptorUsesMetadataSourceBeanWhenProxyingDisabled() { + this.spring.register(CustomMetadataSourceBeanProxyEnabledConfig.class).autowire(); + MethodSecurityInterceptor methodInterceptor = (MethodSecurityInterceptor) this.spring.getContext() + .getBean(MethodInterceptor.class); + MethodSecurityMetadataSource methodSecurityMetadataSource = this.spring.getContext() + .getBean(MethodSecurityMetadataSource.class); + + assertThat(methodInterceptor.getSecurityMetadataSource()).isSameAs(methodSecurityMetadataSource); + } + + @EnableGlobalMethodSecurity + public static class IllegalStateGlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration { + + } + + @EnableGlobalMethodSecurity + public static class CustomMetadataSourceConfig extends GlobalMethodSecurityConfiguration { + + @Bean + @Override + protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() { + return mock(MethodSecurityMetadataSource.class); + } + + } + + @EnableGlobalMethodSecurity(prePostEnabled = true) + public static class InMemoryAuthWithGlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration { + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off + auth + .inMemoryAuthentication(); + // @formatter:on + } + + @Bean + public MockEventListener listener() { + return new MockEventListener() { + }; + } + + } + + @EnableGlobalMethodSecurity(prePostEnabled = true) + static class CustomTrustResolverConfig { + + @Bean + public AuthenticationTrustResolver trustResolver() { + return mock(AuthenticationTrustResolver.class); + } + + @Bean + public MethodSecurityServiceImpl service() { + return new MethodSecurityServiceImpl(); + } + + } + + @EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true) + static class ExpressionHandlerHasBeanResolverSetConfig { + + @Bean + public MethodSecurityServiceImpl service() { + return new MethodSecurityServiceImpl(); + } + + @Bean + public Authz authz() { + return new Authz(); + } + + } + + @EnableGlobalMethodSecurity(prePostEnabled = true) + static class MethodSecurityServiceConfig { + + @Bean + public MethodSecurityService service() { + return new MethodSecurityServiceImpl(); + } + + } + + @EnableGlobalMethodSecurity(prePostEnabled = true) + public static class AutowirePermissionEvaluatorConfig { + + @Bean + public PermissionEvaluator permissionEvaluator() { + return mock(PermissionEvaluator.class); + } + + @Bean + public MethodSecurityService service() { + return new MethodSecurityServiceImpl(); + } + + } + + @EnableGlobalMethodSecurity(prePostEnabled = true) + public static class MultiPermissionEvaluatorConfig { + + @Bean + public PermissionEvaluator permissionEvaluator() { + return mock(PermissionEvaluator.class); + } + + @Bean + public PermissionEvaluator permissionEvaluator2() { + return mock(PermissionEvaluator.class); + } + + } + + @Configuration + static class ChildConfig extends ParentConfig { + + } + + @EnableGlobalMethodSecurity(prePostEnabled = true) + static class ParentConfig { + + @Bean + public MethodSecurityService service() { + return new MethodSecurityServiceImpl(); + } + + } + @Configuration static class Sec2479ParentConfig { @@ -345,16 +440,6 @@ public class GlobalMethodSecurityConfigurationTests { } - @Test - public void enableGlobalMethodSecurityDoesNotTriggerEagerInitializationOfBeansInGlobalAuthenticationConfigurer() { - this.spring.register(Sec2815Config.class).autowire(); - - MockBeanPostProcessor pp = this.spring.getContext().getBean(MockBeanPostProcessor.class); - - assertThat(pp.beforeInit).containsKeys("dataSource"); - assertThat(pp.afterInit).containsKeys("dataSource"); - } - @EnableGlobalMethodSecurity(prePostEnabled = true) static class Sec2815Config { @@ -408,14 +493,6 @@ public class GlobalMethodSecurityConfigurationTests { } - // SEC-3045 - @Test - public void globalSecurityProxiesSecurity() { - this.spring.register(Sec3005Config.class).autowire(); - - assertThat(this.service.getClass()).matches(c -> !Proxy.isProxyClass(c), "is not proxy class"); - } - @EnableGlobalMethodSecurity(prePostEnabled = true, mode = AdviceMode.ASPECTJ) @EnableTransactionManagement static class Sec3005Config { @@ -432,35 +509,6 @@ public class GlobalMethodSecurityConfigurationTests { } - // - // // gh-3797 - // def preAuthorizeBeanSpel() { - // setup: - // SecurityContextHolder.getContext().setAuthentication( - // new TestingAuthenticationToken("user", "password","ROLE_USER")) - // context = new AnnotationConfigApplicationContext(PreAuthorizeBeanSpelConfig) - // BeanSpelService service = context.getBean(BeanSpelService) - // when: - // service.run(true) - // then: - // noExceptionThrown() - // when: - // service.run(false) - // then: - // thrown(AccessDeniedException) - // } - // - - @Test - @WithMockUser - public void preAuthorizeBeanSpel() { - this.spring.register(PreAuthorizeBeanSpelConfig.class).autowire(); - - assertThatThrownBy(() -> this.service.preAuthorizeBean(false)).isInstanceOf(AccessDeniedException.class); - - this.service.preAuthorizeBean(true); - } - @Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) public static class PreAuthorizeBeanSpelConfig { @@ -477,16 +525,6 @@ public class GlobalMethodSecurityConfigurationTests { } - // gh-3394 - @Test - @WithMockUser - public void roleHierarchy() { - this.spring.register(RoleHierarchyConfig.class).autowire(); - - assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); - this.service.preAuthorizeAdmin(); - } - @EnableGlobalMethodSecurity(prePostEnabled = true) @Configuration public static class RoleHierarchyConfig { @@ -505,20 +543,6 @@ public class GlobalMethodSecurityConfigurationTests { } - @Test - @WithMockUser(authorities = "ROLE:USER") - public void grantedAuthorityDefaultsAutowires() { - this.spring.register(CustomGrantedAuthorityConfig.class).autowire(); - - CustomGrantedAuthorityConfig.CustomAuthorityService customService = this.spring.getContext() - .getBean(CustomGrantedAuthorityConfig.CustomAuthorityService.class); - - assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); - - customService.customPrefixRoleUser(); - // no exception - } - @EnableGlobalMethodSecurity(prePostEnabled = true) static class CustomGrantedAuthorityConfig { @@ -547,20 +571,6 @@ public class GlobalMethodSecurityConfigurationTests { } - @Test - @WithMockUser(authorities = "USER") - public void grantedAuthorityDefaultsWithEmptyRolePrefix() { - this.spring.register(EmptyRolePrefixGrantedAuthorityConfig.class).autowire(); - - EmptyRolePrefixGrantedAuthorityConfig.CustomAuthorityService customService = this.spring.getContext() - .getBean(EmptyRolePrefixGrantedAuthorityConfig.CustomAuthorityService.class); - - assertThatThrownBy(() -> this.service.securedUser()).isInstanceOf(AccessDeniedException.class); - - customService.emptyPrefixRoleUser(); - // no exception - } - @EnableGlobalMethodSecurity(securedEnabled = true) static class EmptyRolePrefixGrantedAuthorityConfig { @@ -589,17 +599,6 @@ public class GlobalMethodSecurityConfigurationTests { } - @Test - public void methodSecurityInterceptorUsesMetadataSourceBeanWhenProxyingDisabled() { - this.spring.register(CustomMetadataSourceBeanProxyEnabledConfig.class).autowire(); - MethodSecurityInterceptor methodInterceptor = (MethodSecurityInterceptor) this.spring.getContext() - .getBean(MethodInterceptor.class); - MethodSecurityMetadataSource methodSecurityMetadataSource = this.spring.getContext() - .getBean(MethodSecurityMetadataSource.class); - - assertThat(methodInterceptor.getSecurityMetadataSource()).isSameAs(methodSecurityMetadataSource); - } - @EnableGlobalMethodSecurity(prePostEnabled = true) @Configuration public static class CustomMetadataSourceBeanProxyEnabledConfig extends GlobalMethodSecurityConfiguration { diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityTests.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityTests.java index ccfc66ac40..49a0b080cb 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityTests.java @@ -73,8 +73,6 @@ public class NamespaceGlobalMethodSecurityTests { @Autowired(required = false) private MethodSecurityService service; - // --- access-decision-manager-ref --- - @Test @WithMockUser public void methodSecurityWhenCustomAccessDecisionManagerThenAuthorizes() { @@ -86,6 +84,198 @@ public class NamespaceGlobalMethodSecurityTests { } + @Test + @WithMockUser + public void methodSecurityWhenCustomAfterInvocationManagerThenAuthorizes() { + this.spring.register(CustomAfterInvocationManagerConfig.class, MethodSecurityServiceConfig.class).autowire(); + + assertThatThrownBy(() -> this.service.preAuthorizePermitAll()).isInstanceOf(AccessDeniedException.class); + } + + @Test + @WithMockUser + public void methodSecurityWhenCustomAuthenticationManagerThenAuthorizes() { + this.spring.register(CustomAuthenticationConfig.class, MethodSecurityServiceConfig.class).autowire(); + + assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(UnsupportedOperationException.class); + } + + @Test + @WithMockUser + public void methodSecurityWhenJsr250EnabledThenAuthorizes() { + this.spring.register(Jsr250Config.class, MethodSecurityServiceConfig.class).autowire(); + + assertThatCode(() -> this.service.preAuthorize()).doesNotThrowAnyException(); + + assertThatCode(() -> this.service.secured()).doesNotThrowAnyException(); + + assertThatThrownBy(() -> this.service.jsr250()).isInstanceOf(AccessDeniedException.class); + + assertThatCode(() -> this.service.jsr250PermitAll()).doesNotThrowAnyException(); + + } + + @Test + @WithMockUser + public void methodSecurityWhenCustomMethodSecurityMetadataSourceThenAuthorizes() { + this.spring.register(CustomMethodSecurityMetadataSourceConfig.class, MethodSecurityServiceConfig.class) + .autowire(); + + assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); + + assertThatThrownBy(() -> this.service.secured()).isInstanceOf(AccessDeniedException.class); + + assertThatThrownBy(() -> this.service.jsr250()).isInstanceOf(AccessDeniedException.class); + } + + @Test + @WithMockUser + public void contextRefreshWhenUsingAspectJThenAutowire() throws Exception { + this.spring.register(AspectJModeConfig.class, MethodSecurityServiceConfig.class).autowire(); + + assertThat(this.spring.getContext().getBean( + Class.forName("org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect"))) + .isNotNull(); + assertThat(this.spring.getContext().getBean(AspectJMethodSecurityInterceptor.class)).isNotNull(); + + // TODO diagnose why aspectj isn't weaving method security advice around + // MethodSecurityServiceImpl + } + + @Test + public void contextRefreshWhenUsingAspectJAndCustomGlobalMethodSecurityConfigurationThenAutowire() + throws Exception { + + this.spring.register(AspectJModeExtendsGMSCConfig.class).autowire(); + + assertThat(this.spring.getContext().getBean( + Class.forName("org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect"))) + .isNotNull(); + assertThat(this.spring.getContext().getBean(AspectJMethodSecurityInterceptor.class)).isNotNull(); + + } + + @Test + @WithMockUser + public void methodSecurityWhenOrderSpecifiedThenConfigured() { + this.spring.register(CustomOrderConfig.class, MethodSecurityServiceConfig.class).autowire(); + + assertThat(this.spring.getContext().getBean("metaDataSourceAdvisor", MethodSecurityMetadataSourceAdvisor.class) + .getOrder()).isEqualTo(-135); + + assertThatThrownBy(() -> this.service.jsr250()).isInstanceOf(AccessDeniedException.class); + } + + @Test + @WithMockUser + public void methodSecurityWhenOrderUnspecifiedThenConfiguredToLowestPrecedence() { + this.spring.register(DefaultOrderConfig.class, MethodSecurityServiceConfig.class).autowire(); + + assertThat(this.spring.getContext().getBean("metaDataSourceAdvisor", MethodSecurityMetadataSourceAdvisor.class) + .getOrder()).isEqualTo(Ordered.LOWEST_PRECEDENCE); + + assertThatThrownBy(() -> this.service.jsr250()).isInstanceOf(UnsupportedOperationException.class); + } + + @Test + @WithMockUser + public void methodSecurityWhenOrderUnspecifiedAndCustomGlobalMethodSecurityConfigurationThenConfiguredToLowestPrecedence() { + this.spring.register(DefaultOrderExtendsMethodSecurityConfig.class, MethodSecurityServiceConfig.class) + .autowire(); + + assertThat(this.spring.getContext().getBean("metaDataSourceAdvisor", MethodSecurityMetadataSourceAdvisor.class) + .getOrder()).isEqualTo(Ordered.LOWEST_PRECEDENCE); + + assertThatThrownBy(() -> this.service.jsr250()).isInstanceOf(UnsupportedOperationException.class); + } + + @Test + @WithMockUser + public void methodSecurityWhenPrePostEnabledThenPreAuthorizes() { + this.spring.register(PreAuthorizeConfig.class, MethodSecurityServiceConfig.class).autowire(); + + assertThatCode(() -> this.service.secured()).doesNotThrowAnyException(); + + assertThatCode(() -> this.service.jsr250()).doesNotThrowAnyException(); + + assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); + } + + @Test + @WithMockUser + public void methodSecurityWhenPrePostEnabledAndCustomGlobalMethodSecurityConfigurationThenPreAuthorizes() { + this.spring.register(PreAuthorizeExtendsGMSCConfig.class, MethodSecurityServiceConfig.class).autowire(); + + assertThatCode(() -> this.service.secured()).doesNotThrowAnyException(); + + assertThatCode(() -> this.service.jsr250()).doesNotThrowAnyException(); + + assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); + } + + @Test + @WithMockUser + public void methodSecurityWhenProxyTargetClassThenDoesNotWireToInterface() { + this.spring.register(ProxyTargetClassConfig.class, MethodSecurityServiceConfig.class).autowire(); + + // make sure service was actually proxied + assertThat(this.service.getClass().getInterfaces()).doesNotContain(MethodSecurityService.class); + + assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); + } + + @Test + @WithMockUser + public void methodSecurityWhenDefaultProxyThenWiresToInterface() { + this.spring.register(DefaultProxyConfig.class, MethodSecurityServiceConfig.class).autowire(); + + assertThat(this.service.getClass().getInterfaces()).contains(MethodSecurityService.class); + + assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); + } + + @Test + @WithMockUser + public void methodSecurityWhenCustomRunAsManagerThenRunAsWrapsAuthentication() { + this.spring.register(CustomRunAsManagerConfig.class, MethodSecurityServiceConfig.class).autowire(); + + assertThat(this.service.runAs().getAuthorities()) + .anyMatch(authority -> "ROLE_RUN_AS_SUPER".equals(authority.getAuthority())); + } + + @Test + @WithMockUser + public void methodSecurityWhenSecuredEnabledThenSecures() { + this.spring.register(SecuredConfig.class, MethodSecurityServiceConfig.class).autowire(); + + assertThatThrownBy(() -> this.service.secured()).isInstanceOf(AccessDeniedException.class); + + assertThatCode(() -> this.service.securedUser()).doesNotThrowAnyException(); + + assertThatCode(() -> this.service.preAuthorize()).doesNotThrowAnyException(); + + assertThatCode(() -> this.service.jsr250()).doesNotThrowAnyException(); + } + + @Test + @WithMockUser + public void methodSecurityWhenMissingEnableAnnotationThenShowsHelpfulError() { + assertThatThrownBy(() -> this.spring.register(ExtendsNoEnableAnntotationConfig.class).autowire()) + .hasStackTraceContaining(EnableGlobalMethodSecurity.class.getName() + " is required"); + } + + @Test + @WithMockUser + public void methodSecurityWhenImportingGlobalMethodSecurityConfigurationSubclassThenAuthorizes() { + this.spring.register(ImportSubclassGMSCConfig.class, MethodSecurityServiceConfig.class).autowire(); + + assertThatCode(() -> this.service.secured()).doesNotThrowAnyException(); + + assertThatCode(() -> this.service.jsr250()).doesNotThrowAnyException(); + + assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); + } + @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) public static class CustomAccessDecisionManagerConfig extends GlobalMethodSecurityConfiguration { @@ -116,16 +306,6 @@ public class NamespaceGlobalMethodSecurityTests { } - // --- after-invocation-provider - - @Test - @WithMockUser - public void methodSecurityWhenCustomAfterInvocationManagerThenAuthorizes() { - this.spring.register(CustomAfterInvocationManagerConfig.class, MethodSecurityServiceConfig.class).autowire(); - - assertThatThrownBy(() -> this.service.preAuthorizePermitAll()).isInstanceOf(AccessDeniedException.class); - } - @EnableGlobalMethodSecurity(prePostEnabled = true) public static class CustomAfterInvocationManagerConfig extends GlobalMethodSecurityConfiguration { @@ -157,16 +337,6 @@ public class NamespaceGlobalMethodSecurityTests { } - // --- authentication-manager-ref --- - - @Test - @WithMockUser - public void methodSecurityWhenCustomAuthenticationManagerThenAuthorizes() { - this.spring.register(CustomAuthenticationConfig.class, MethodSecurityServiceConfig.class).autowire(); - - assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(UnsupportedOperationException.class); - } - @EnableGlobalMethodSecurity(prePostEnabled = true) public static class CustomAuthenticationConfig extends GlobalMethodSecurityConfiguration { @@ -186,44 +356,12 @@ public class NamespaceGlobalMethodSecurityTests { } - // --- jsr250-annotations --- - - @Test - @WithMockUser - public void methodSecurityWhenJsr250EnabledThenAuthorizes() { - this.spring.register(Jsr250Config.class, MethodSecurityServiceConfig.class).autowire(); - - assertThatCode(() -> this.service.preAuthorize()).doesNotThrowAnyException(); - - assertThatCode(() -> this.service.secured()).doesNotThrowAnyException(); - - assertThatThrownBy(() -> this.service.jsr250()).isInstanceOf(AccessDeniedException.class); - - assertThatCode(() -> this.service.jsr250PermitAll()).doesNotThrowAnyException(); - - } - @EnableGlobalMethodSecurity(jsr250Enabled = true) @Configuration public static class Jsr250Config { } - // --- metadata-source-ref --- - - @Test - @WithMockUser - public void methodSecurityWhenCustomMethodSecurityMetadataSourceThenAuthorizes() { - this.spring.register(CustomMethodSecurityMetadataSourceConfig.class, MethodSecurityServiceConfig.class) - .autowire(); - - assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); - - assertThatThrownBy(() -> this.service.secured()).isInstanceOf(AccessDeniedException.class); - - assertThatThrownBy(() -> this.service.jsr250()).isInstanceOf(AccessDeniedException.class); - } - @EnableGlobalMethodSecurity public static class CustomMethodSecurityMetadataSourceConfig extends GlobalMethodSecurityConfiguration { @@ -247,58 +385,18 @@ public class NamespaceGlobalMethodSecurityTests { } - // --- mode --- - - @Test - @WithMockUser - public void contextRefreshWhenUsingAspectJThenAutowire() throws Exception { - this.spring.register(AspectJModeConfig.class, MethodSecurityServiceConfig.class).autowire(); - - assertThat(this.spring.getContext().getBean( - Class.forName("org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect"))) - .isNotNull(); - assertThat(this.spring.getContext().getBean(AspectJMethodSecurityInterceptor.class)).isNotNull(); - - // TODO diagnose why aspectj isn't weaving method security advice around - // MethodSecurityServiceImpl - } - @EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ, securedEnabled = true) public static class AspectJModeConfig { } - @Test - public void contextRefreshWhenUsingAspectJAndCustomGlobalMethodSecurityConfigurationThenAutowire() - throws Exception { - - this.spring.register(AspectJModeExtendsGMSCConfig.class).autowire(); - - assertThat(this.spring.getContext().getBean( - Class.forName("org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect"))) - .isNotNull(); - assertThat(this.spring.getContext().getBean(AspectJMethodSecurityInterceptor.class)).isNotNull(); - - } - @EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ, securedEnabled = true) public static class AspectJModeExtendsGMSCConfig extends GlobalMethodSecurityConfiguration { } - // --- order --- - private static class AdvisorOrderConfig implements ImportBeanDefinitionRegistrar { - private static class ExceptingInterceptor implements MethodInterceptor { - - @Override - public Object invoke(MethodInvocation invocation) { - throw new UnsupportedOperationException("Deny All"); - } - - } - @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { @@ -315,17 +413,15 @@ public class NamespaceGlobalMethodSecurityTests { registry.registerBeanDefinition("exceptingAdvisor", advisor.getBeanDefinition()); } - } + private static class ExceptingInterceptor implements MethodInterceptor { - @Test - @WithMockUser - public void methodSecurityWhenOrderSpecifiedThenConfigured() { - this.spring.register(CustomOrderConfig.class, MethodSecurityServiceConfig.class).autowire(); + @Override + public Object invoke(MethodInvocation invocation) { + throw new UnsupportedOperationException("Deny All"); + } - assertThat(this.spring.getContext().getBean("metaDataSourceAdvisor", MethodSecurityMetadataSourceAdvisor.class) - .getOrder()).isEqualTo(-135); + } - assertThatThrownBy(() -> this.service.jsr250()).isInstanceOf(AccessDeniedException.class); } @EnableGlobalMethodSecurity(order = -135, jsr250Enabled = true) @@ -334,121 +430,38 @@ public class NamespaceGlobalMethodSecurityTests { } - @Test - @WithMockUser - public void methodSecurityWhenOrderUnspecifiedThenConfiguredToLowestPrecedence() { - this.spring.register(DefaultOrderConfig.class, MethodSecurityServiceConfig.class).autowire(); - - assertThat(this.spring.getContext().getBean("metaDataSourceAdvisor", MethodSecurityMetadataSourceAdvisor.class) - .getOrder()).isEqualTo(Ordered.LOWEST_PRECEDENCE); - - assertThatThrownBy(() -> this.service.jsr250()).isInstanceOf(UnsupportedOperationException.class); - } - @EnableGlobalMethodSecurity(jsr250Enabled = true) @Import(AdvisorOrderConfig.class) public static class DefaultOrderConfig { } - @Test - @WithMockUser - public void methodSecurityWhenOrderUnspecifiedAndCustomGlobalMethodSecurityConfigurationThenConfiguredToLowestPrecedence() { - this.spring.register(DefaultOrderExtendsMethodSecurityConfig.class, MethodSecurityServiceConfig.class) - .autowire(); - - assertThat(this.spring.getContext().getBean("metaDataSourceAdvisor", MethodSecurityMetadataSourceAdvisor.class) - .getOrder()).isEqualTo(Ordered.LOWEST_PRECEDENCE); - - assertThatThrownBy(() -> this.service.jsr250()).isInstanceOf(UnsupportedOperationException.class); - } - @EnableGlobalMethodSecurity(jsr250Enabled = true) @Import(AdvisorOrderConfig.class) public static class DefaultOrderExtendsMethodSecurityConfig extends GlobalMethodSecurityConfiguration { } - // --- pre-post-annotations --- - - @Test - @WithMockUser - public void methodSecurityWhenPrePostEnabledThenPreAuthorizes() { - this.spring.register(PreAuthorizeConfig.class, MethodSecurityServiceConfig.class).autowire(); - - assertThatCode(() -> this.service.secured()).doesNotThrowAnyException(); - - assertThatCode(() -> this.service.jsr250()).doesNotThrowAnyException(); - - assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); - } - @EnableGlobalMethodSecurity(prePostEnabled = true) public static class PreAuthorizeConfig { } - @Test - @WithMockUser - public void methodSecurityWhenPrePostEnabledAndCustomGlobalMethodSecurityConfigurationThenPreAuthorizes() { - this.spring.register(PreAuthorizeExtendsGMSCConfig.class, MethodSecurityServiceConfig.class).autowire(); - - assertThatCode(() -> this.service.secured()).doesNotThrowAnyException(); - - assertThatCode(() -> this.service.jsr250()).doesNotThrowAnyException(); - - assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); - } - @EnableGlobalMethodSecurity(prePostEnabled = true) public static class PreAuthorizeExtendsGMSCConfig extends GlobalMethodSecurityConfiguration { } - // --- proxy-target-class --- - - @Test - @WithMockUser - public void methodSecurityWhenProxyTargetClassThenDoesNotWireToInterface() { - this.spring.register(ProxyTargetClassConfig.class, MethodSecurityServiceConfig.class).autowire(); - - // make sure service was actually proxied - assertThat(this.service.getClass().getInterfaces()).doesNotContain(MethodSecurityService.class); - - assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); - } - @EnableGlobalMethodSecurity(proxyTargetClass = true, prePostEnabled = true) public static class ProxyTargetClassConfig { } - @Test - @WithMockUser - public void methodSecurityWhenDefaultProxyThenWiresToInterface() { - this.spring.register(DefaultProxyConfig.class, MethodSecurityServiceConfig.class).autowire(); - - assertThat(this.service.getClass().getInterfaces()).contains(MethodSecurityService.class); - - assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); - } - @EnableGlobalMethodSecurity(prePostEnabled = true) public static class DefaultProxyConfig { } - // --- run-as-manager-ref --- - - @Test - @WithMockUser - public void methodSecurityWhenCustomRunAsManagerThenRunAsWrapsAuthentication() { - this.spring.register(CustomRunAsManagerConfig.class, MethodSecurityServiceConfig.class).autowire(); - - assertThat(this.service.runAs().getAuthorities()) - .anyMatch(authority -> "ROLE_RUN_AS_SUPER".equals(authority.getAuthority())); - } - @EnableGlobalMethodSecurity(securedEnabled = true) public static class CustomRunAsManagerConfig extends GlobalMethodSecurityConfiguration { @@ -461,53 +474,16 @@ public class NamespaceGlobalMethodSecurityTests { } - // --- secured-annotation --- - - @Test - @WithMockUser - public void methodSecurityWhenSecuredEnabledThenSecures() { - this.spring.register(SecuredConfig.class, MethodSecurityServiceConfig.class).autowire(); - - assertThatThrownBy(() -> this.service.secured()).isInstanceOf(AccessDeniedException.class); - - assertThatCode(() -> this.service.securedUser()).doesNotThrowAnyException(); - - assertThatCode(() -> this.service.preAuthorize()).doesNotThrowAnyException(); - - assertThatCode(() -> this.service.jsr250()).doesNotThrowAnyException(); - } - @EnableGlobalMethodSecurity(securedEnabled = true) public static class SecuredConfig { } - // --- unsorted --- - - @Test - @WithMockUser - public void methodSecurityWhenMissingEnableAnnotationThenShowsHelpfulError() { - assertThatThrownBy(() -> this.spring.register(ExtendsNoEnableAnntotationConfig.class).autowire()) - .hasStackTraceContaining(EnableGlobalMethodSecurity.class.getName() + " is required"); - } - @Configuration public static class ExtendsNoEnableAnntotationConfig extends GlobalMethodSecurityConfiguration { } - @Test - @WithMockUser - public void methodSecurityWhenImportingGlobalMethodSecurityConfigurationSubclassThenAuthorizes() { - this.spring.register(ImportSubclassGMSCConfig.class, MethodSecurityServiceConfig.class).autowire(); - - assertThatCode(() -> this.service.secured()).doesNotThrowAnyException(); - - assertThatCode(() -> this.service.jsr250()).doesNotThrowAnyException(); - - assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class); - } - @Configuration @Import(PreAuthorizeExtendsGMSCConfig.class) public static class ImportSubclassGMSCConfig { diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityConfigurationTests.java index 575df914fa..13f45b1ca8 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityConfigurationTests.java @@ -77,17 +77,6 @@ public class ReactiveMethodSecurityConfigurationTests { assertThat(root.hasRole("ABC")).isTrue(); } - @Configuration - @EnableReactiveMethodSecurity // this imports ReactiveMethodSecurityConfiguration - static class WithRolePrefixConfiguration { - - @Bean - GrantedAuthorityDefaults grantedAuthorityDefaults() { - return new GrantedAuthorityDefaults("CUSTOM_"); - } - - } - @Test public void rolePrefixWithGrantedAuthorityDefaultsAndSubclassWithProxyingEnabled() throws NoSuchMethodException { this.spring.register(SubclassConfig.class).autowire(); @@ -104,6 +93,17 @@ public class ReactiveMethodSecurityConfigurationTests { assertThat(root.hasRole("ABC")).isTrue(); } + @Configuration + @EnableReactiveMethodSecurity // this imports ReactiveMethodSecurityConfiguration + static class WithRolePrefixConfiguration { + + @Bean + GrantedAuthorityDefaults grantedAuthorityDefaults() { + return new GrantedAuthorityDefaults("CUSTOM_"); + } + + } + @Configuration static class SubclassConfig extends ReactiveMethodSecurityConfiguration { diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/SampleEnableGlobalMethodSecurityTests.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/SampleEnableGlobalMethodSecurityTests.java index f2c70cb81e..f16f3586ec 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/SampleEnableGlobalMethodSecurityTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/SampleEnableGlobalMethodSecurityTests.java @@ -66,6 +66,16 @@ public class SampleEnableGlobalMethodSecurityTests { assertThatThrownBy(() -> this.methodSecurityService.preAuthorize()).isInstanceOf(AccessDeniedException.class); } + @Test + public void customPermissionHandler() { + this.spring.register(CustomPermissionEvaluatorWebSecurityConfig.class).autowire(); + + assertThat(this.methodSecurityService.hasPermission("allowed")).isNull(); + + assertThatThrownBy(() -> this.methodSecurityService.hasPermission("denied")) + .isInstanceOf(AccessDeniedException.class); + } + @EnableGlobalMethodSecurity(prePostEnabled = true) static class SampleWebSecurityConfig { @@ -86,16 +96,6 @@ public class SampleEnableGlobalMethodSecurityTests { } - @Test - public void customPermissionHandler() { - this.spring.register(CustomPermissionEvaluatorWebSecurityConfig.class).autowire(); - - assertThat(this.methodSecurityService.hasPermission("allowed")).isNull(); - - assertThatThrownBy(() -> this.methodSecurityService.hasPermission("denied")) - .isInstanceOf(AccessDeniedException.class); - } - @EnableGlobalMethodSecurity(prePostEnabled = true) public static class CustomPermissionEvaluatorWebSecurityConfig extends GlobalMethodSecurityConfiguration { diff --git a/config/src/test/java/org/springframework/security/config/annotation/sec2758/Sec2758Tests.java b/config/src/test/java/org/springframework/security/config/annotation/sec2758/Sec2758Tests.java index 5113be8bf4..c550d4045c 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/sec2758/Sec2758Tests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/sec2758/Sec2758Tests.java @@ -88,22 +88,12 @@ public class Sec2758Tests { @EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true) static class SecurityConfig extends WebSecurityConfigurerAdapter { - @RestController - static class RootController { - - @GetMapping("/") - public String ok() { - return "ok"; - } - - } - @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off http - .authorizeRequests() - .anyRequest().access("hasAnyRole('CUSTOM')"); + .authorizeRequests() + .anyRequest().access("hasAnyRole('CUSTOM')"); // @formatter:on } @@ -117,6 +107,16 @@ public class Sec2758Tests { return new DefaultRolesPrefixPostProcessor(); } + @RestController + static class RootController { + + @GetMapping("/") + public String ok() { + return "ok"; + } + + } + } static class Service { diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryAnyMatcherTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryAnyMatcherTests.java index 3d7dd81d84..06d405188f 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryAnyMatcherTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryAnyMatcherTests.java @@ -32,6 +32,39 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationCon */ public class AbstractRequestMatcherRegistryAnyMatcherTests { + @Test(expected = BeanCreationException.class) + public void antMatchersCanNotWorkAfterAnyRequest() { + loadConfig(AntMatchersAfterAnyRequestConfig.class); + } + + @Test(expected = BeanCreationException.class) + public void mvcMatchersCanNotWorkAfterAnyRequest() { + loadConfig(MvcMatchersAfterAnyRequestConfig.class); + } + + @Test(expected = BeanCreationException.class) + public void regexMatchersCanNotWorkAfterAnyRequest() { + loadConfig(RegexMatchersAfterAnyRequestConfig.class); + } + + @Test(expected = BeanCreationException.class) + public void anyRequestCanNotWorkAfterItself() { + loadConfig(AnyRequestAfterItselfConfig.class); + } + + @Test(expected = BeanCreationException.class) + public void requestMatchersCanNotWorkAfterAnyRequest() { + loadConfig(RequestMatchersAfterAnyRequestConfig.class); + } + + private void loadConfig(Class... configs) { + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + context.setAllowCircularReferences(false); + context.register(configs); + context.setServletContext(new MockServletContext()); + context.refresh(); + } + @EnableWebSecurity static class AntMatchersAfterAnyRequestConfig extends WebSecurityConfigurerAdapter { @@ -48,11 +81,6 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests { } - @Test(expected = BeanCreationException.class) - public void antMatchersCanNotWorkAfterAnyRequest() { - loadConfig(AntMatchersAfterAnyRequestConfig.class); - } - @EnableWebSecurity static class MvcMatchersAfterAnyRequestConfig extends WebSecurityConfigurerAdapter { @@ -69,11 +97,6 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests { } - @Test(expected = BeanCreationException.class) - public void mvcMatchersCanNotWorkAfterAnyRequest() { - loadConfig(MvcMatchersAfterAnyRequestConfig.class); - } - @EnableWebSecurity static class RegexMatchersAfterAnyRequestConfig extends WebSecurityConfigurerAdapter { @@ -90,11 +113,6 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests { } - @Test(expected = BeanCreationException.class) - public void regexMatchersCanNotWorkAfterAnyRequest() { - loadConfig(RegexMatchersAfterAnyRequestConfig.class); - } - @EnableWebSecurity static class AnyRequestAfterItselfConfig extends WebSecurityConfigurerAdapter { @@ -111,11 +129,6 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests { } - @Test(expected = BeanCreationException.class) - public void anyRequestCanNotWorkAfterItself() { - loadConfig(AnyRequestAfterItselfConfig.class); - } - @EnableWebSecurity static class RequestMatchersAfterAnyRequestConfig extends WebSecurityConfigurerAdapter { @@ -132,17 +145,4 @@ public class AbstractRequestMatcherRegistryAnyMatcherTests { } - @Test(expected = BeanCreationException.class) - public void requestMatchersCanNotWorkAfterAnyRequest() { - loadConfig(RequestMatchersAfterAnyRequestConfig.class); - } - - private void loadConfig(Class... configs) { - AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); - context.setAllowCircularReferences(false); - context.register(configs); - context.setServletContext(new MockServletContext()); - context.refresh(); - } - } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/SampleWebSecurityConfigurerAdapterTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/SampleWebSecurityConfigurerAdapterTests.java index 978a3e0eed..198c55c3b3 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/SampleWebSecurityConfigurerAdapterTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/SampleWebSecurityConfigurerAdapterTests.java @@ -110,6 +110,106 @@ public class SampleWebSecurityConfigurerAdapterTests { assertThat(this.response.getRedirectedUrl()).isEqualTo("/"); } + @Test + public void readmeSampleWhenRequestSecureResourceThenRedirectToLogin() throws Exception { + this.spring.register(SampleWebSecurityConfigurerAdapter.class).autowire(); + + this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); + + assertThat(this.response.getRedirectedUrl()).isEqualTo("http://localhost/login"); + } + + @Test + public void readmeSampleWhenRequestLoginWithoutCredentialsThenRedirectToLogin() throws Exception { + this.spring.register(SampleWebSecurityConfigurerAdapter.class).autowire(); + + this.request.setServletPath("/login"); + this.request.setMethod("POST"); + this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); + + assertThat(this.response.getRedirectedUrl()).isEqualTo("/login?error"); + } + + @Test + public void readmeSampleWhenRequestLoginWithValidCredentialsThenRedirectToIndex() throws Exception { + this.spring.register(SampleWebSecurityConfigurerAdapter.class).autowire(); + + this.request.setServletPath("/login"); + this.request.setMethod("POST"); + this.request.addParameter("username", "user"); + this.request.addParameter("password", "password"); + this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); + + assertThat(this.response.getRedirectedUrl()).isEqualTo("/"); + } + + @Test + public void multiHttpSampleWhenRequestSecureResourceThenRedirectToLogin() throws Exception { + this.spring.register(SampleMultiHttpSecurityConfig.class).autowire(); + + this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); + + assertThat(this.response.getRedirectedUrl()).isEqualTo("http://localhost/login"); + } + + @Test + public void multiHttpSampleWhenRequestLoginWithoutCredentialsThenRedirectToLogin() throws Exception { + this.spring.register(SampleMultiHttpSecurityConfig.class).autowire(); + + this.request.setServletPath("/login"); + this.request.setMethod("POST"); + this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); + + assertThat(this.response.getRedirectedUrl()).isEqualTo("/login?error"); + } + + @Test + public void multiHttpSampleWhenRequestLoginWithValidCredentialsThenRedirectToIndex() throws Exception { + this.spring.register(SampleMultiHttpSecurityConfig.class).autowire(); + + this.request.setServletPath("/login"); + this.request.setMethod("POST"); + this.request.addParameter("username", "user"); + this.request.addParameter("password", "password"); + this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); + + assertThat(this.response.getRedirectedUrl()).isEqualTo("/"); + } + + @Test + public void multiHttpSampleWhenRequestProtectedResourceThenStatusUnauthorized() throws Exception { + this.spring.register(SampleMultiHttpSecurityConfig.class).autowire(); + + this.request.setServletPath("/api/admin/test"); + this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); + + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED); + } + + @Test + public void multiHttpSampleWhenRequestAdminResourceWithRegularUserThenStatusForbidden() throws Exception { + this.spring.register(SampleMultiHttpSecurityConfig.class).autowire(); + + this.request.setServletPath("/api/admin/test"); + this.request.addHeader("Authorization", + "Basic " + Base64.getEncoder().encodeToString("user:password".getBytes())); + this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); + + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN); + } + + @Test + public void multiHttpSampleWhenRequestAdminResourceWithAdminUserThenStatusOk() throws Exception { + this.spring.register(SampleMultiHttpSecurityConfig.class).autowire(); + + this.request.setServletPath("/api/admin/test"); + this.request.addHeader("Authorization", + "Basic " + Base64.getEncoder().encodeToString("admin:password".getBytes())); + this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain); + + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK); + } + /** *
 	 *   <http>
@@ -151,39 +251,6 @@ public class SampleWebSecurityConfigurerAdapterTests {
 
 	}
 
-	@Test
-	public void readmeSampleWhenRequestSecureResourceThenRedirectToLogin() throws Exception {
-		this.spring.register(SampleWebSecurityConfigurerAdapter.class).autowire();
-
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getRedirectedUrl()).isEqualTo("http://localhost/login");
-	}
-
-	@Test
-	public void readmeSampleWhenRequestLoginWithoutCredentialsThenRedirectToLogin() throws Exception {
-		this.spring.register(SampleWebSecurityConfigurerAdapter.class).autowire();
-
-		this.request.setServletPath("/login");
-		this.request.setMethod("POST");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getRedirectedUrl()).isEqualTo("/login?error");
-	}
-
-	@Test
-	public void readmeSampleWhenRequestLoginWithValidCredentialsThenRedirectToIndex() throws Exception {
-		this.spring.register(SampleWebSecurityConfigurerAdapter.class).autowire();
-
-		this.request.setServletPath("/login");
-		this.request.setMethod("POST");
-		this.request.addParameter("username", "user");
-		this.request.addParameter("password", "password");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getRedirectedUrl()).isEqualTo("/");
-	}
-
 	/**
 	 * 
 	 *   <http security="none" pattern="/resources/**"/>
@@ -252,73 +319,6 @@ public class SampleWebSecurityConfigurerAdapterTests {
 
 	}
 
-	@Test
-	public void multiHttpSampleWhenRequestSecureResourceThenRedirectToLogin() throws Exception {
-		this.spring.register(SampleMultiHttpSecurityConfig.class).autowire();
-
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getRedirectedUrl()).isEqualTo("http://localhost/login");
-	}
-
-	@Test
-	public void multiHttpSampleWhenRequestLoginWithoutCredentialsThenRedirectToLogin() throws Exception {
-		this.spring.register(SampleMultiHttpSecurityConfig.class).autowire();
-
-		this.request.setServletPath("/login");
-		this.request.setMethod("POST");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getRedirectedUrl()).isEqualTo("/login?error");
-	}
-
-	@Test
-	public void multiHttpSampleWhenRequestLoginWithValidCredentialsThenRedirectToIndex() throws Exception {
-		this.spring.register(SampleMultiHttpSecurityConfig.class).autowire();
-
-		this.request.setServletPath("/login");
-		this.request.setMethod("POST");
-		this.request.addParameter("username", "user");
-		this.request.addParameter("password", "password");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getRedirectedUrl()).isEqualTo("/");
-	}
-
-	@Test
-	public void multiHttpSampleWhenRequestProtectedResourceThenStatusUnauthorized() throws Exception {
-		this.spring.register(SampleMultiHttpSecurityConfig.class).autowire();
-
-		this.request.setServletPath("/api/admin/test");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
-	}
-
-	@Test
-	public void multiHttpSampleWhenRequestAdminResourceWithRegularUserThenStatusForbidden() throws Exception {
-		this.spring.register(SampleMultiHttpSecurityConfig.class).autowire();
-
-		this.request.setServletPath("/api/admin/test");
-		this.request.addHeader("Authorization",
-				"Basic " + Base64.getEncoder().encodeToString("user:password".getBytes()));
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
-	}
-
-	@Test
-	public void multiHttpSampleWhenRequestAdminResourceWithAdminUserThenStatusOk() throws Exception {
-		this.spring.register(SampleMultiHttpSecurityConfig.class).autowire();
-
-		this.request.setServletPath("/api/admin/test");
-		this.request.addHeader("Authorization",
-				"Basic " + Base64.getEncoder().encodeToString("admin:password".getBytes()));
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
-	}
-
 	/**
 	 * 
 	 *   <http security="none" pattern="/resources/**"/>
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterPowermockTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterPowermockTests.java
index a5cf2d3dd9..7c68fabcde 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterPowermockTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterPowermockTests.java
@@ -90,6 +90,27 @@ public class WebSecurityConfigurerAdapterPowermockTests {
 		assertThat(configurer.configure).isTrue();
 	}
 
+	@Test
+	public void loadConfigWhenDefaultConfigThenWebAsyncManagerIntegrationFilterAdded() throws Exception {
+		this.spring.register(WebAsyncPopulatedByDefaultConfig.class).autowire();
+
+		WebAsyncManager webAsyncManager = mock(WebAsyncManager.class);
+
+		this.mockMvc.perform(get("/").requestAttr(WebAsyncUtils.WEB_ASYNC_MANAGER_ATTRIBUTE, webAsyncManager));
+
+		ArgumentCaptor callableProcessingInterceptorArgCaptor = ArgumentCaptor
+				.forClass(CallableProcessingInterceptor.class);
+		verify(webAsyncManager, atLeastOnce()).registerCallableInterceptor(any(),
+				callableProcessingInterceptorArgCaptor.capture());
+
+		CallableProcessingInterceptor callableProcessingInterceptor = callableProcessingInterceptorArgCaptor
+				.getAllValues().stream()
+				.filter(e -> SecurityContextCallableProcessingInterceptor.class.isAssignableFrom(e.getClass()))
+				.findFirst().orElse(null);
+
+		assertThat(callableProcessingInterceptor).isNotNull();
+	}
+
 	private void loadConfig(Class... classes) {
 		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
 		context.setClassLoader(getClass().getClassLoader());
@@ -125,27 +146,6 @@ public class WebSecurityConfigurerAdapterPowermockTests {
 
 	}
 
-	@Test
-	public void loadConfigWhenDefaultConfigThenWebAsyncManagerIntegrationFilterAdded() throws Exception {
-		this.spring.register(WebAsyncPopulatedByDefaultConfig.class).autowire();
-
-		WebAsyncManager webAsyncManager = mock(WebAsyncManager.class);
-
-		this.mockMvc.perform(get("/").requestAttr(WebAsyncUtils.WEB_ASYNC_MANAGER_ATTRIBUTE, webAsyncManager));
-
-		ArgumentCaptor callableProcessingInterceptorArgCaptor = ArgumentCaptor
-				.forClass(CallableProcessingInterceptor.class);
-		verify(webAsyncManager, atLeastOnce()).registerCallableInterceptor(any(),
-				callableProcessingInterceptorArgCaptor.capture());
-
-		CallableProcessingInterceptor callableProcessingInterceptor = callableProcessingInterceptorArgCaptor
-				.getAllValues().stream()
-				.filter(e -> SecurityContextCallableProcessingInterceptor.class.isAssignableFrom(e.getClass()))
-				.findFirst().orElse(null);
-
-		assertThat(callableProcessingInterceptor).isNotNull();
-	}
-
 	@EnableWebSecurity
 	static class WebAsyncPopulatedByDefaultConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterTests.java
index a31287e6b6..dcd06d382d 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterTests.java
@@ -91,6 +91,135 @@ public class WebSecurityConfigurerAdapterTests {
 				.andExpect(header().string("X-XSS-Protection", "1; mode=block"));
 	}
 
+	@Test
+	public void loadConfigWhenRequestAuthenticateThenAuthenticationEventPublished() throws Exception {
+		this.spring.register(InMemoryAuthWithWebSecurityConfigurerAdapter.class).autowire();
+
+		this.mockMvc.perform(formLogin()).andExpect(status().is3xxRedirection());
+
+		assertThat(InMemoryAuthWithWebSecurityConfigurerAdapter.EVENTS).isNotEmpty();
+		assertThat(InMemoryAuthWithWebSecurityConfigurerAdapter.EVENTS).hasSize(1);
+	}
+
+	@Test
+	public void loadConfigWhenInMemoryConfigureProtectedThenPasswordUpgraded() throws Exception {
+		this.spring.register(InMemoryConfigureProtectedConfig.class).autowire();
+
+		this.mockMvc.perform(formLogin()).andExpect(status().is3xxRedirection());
+
+		UserDetailsService uds = this.spring.getContext().getBean(UserDetailsService.class);
+		assertThat(uds.loadUserByUsername("user").getPassword()).startsWith("{bcrypt}");
+	}
+
+	@Test
+	public void loadConfigWhenInMemoryConfigureGlobalThenPasswordUpgraded() throws Exception {
+		this.spring.register(InMemoryConfigureGlobalConfig.class).autowire();
+
+		this.mockMvc.perform(formLogin()).andExpect(status().is3xxRedirection());
+
+		UserDetailsService uds = this.spring.getContext().getBean(UserDetailsService.class);
+		assertThat(uds.loadUserByUsername("user").getPassword()).startsWith("{bcrypt}");
+	}
+
+	@Test
+	public void loadConfigWhenCustomContentNegotiationStrategyBeanThenOverridesDefault() {
+		OverrideContentNegotiationStrategySharedObjectConfig.CONTENT_NEGOTIATION_STRATEGY_BEAN = mock(
+				ContentNegotiationStrategy.class);
+		this.spring.register(OverrideContentNegotiationStrategySharedObjectConfig.class).autowire();
+
+		OverrideContentNegotiationStrategySharedObjectConfig securityConfig = this.spring.getContext()
+				.getBean(OverrideContentNegotiationStrategySharedObjectConfig.class);
+
+		assertThat(securityConfig.contentNegotiationStrategySharedObject).isNotNull();
+		assertThat(securityConfig.contentNegotiationStrategySharedObject)
+				.isSameAs(OverrideContentNegotiationStrategySharedObjectConfig.CONTENT_NEGOTIATION_STRATEGY_BEAN);
+	}
+
+	@Test
+	public void loadConfigWhenDefaultContentNegotiationStrategyThenHeaderContentNegotiationStrategy() {
+		this.spring.register(ContentNegotiationStrategyDefaultSharedObjectConfig.class).autowire();
+
+		ContentNegotiationStrategyDefaultSharedObjectConfig securityConfig = this.spring.getContext()
+				.getBean(ContentNegotiationStrategyDefaultSharedObjectConfig.class);
+
+		assertThat(securityConfig.contentNegotiationStrategySharedObject).isNotNull();
+		assertThat(securityConfig.contentNegotiationStrategySharedObject)
+				.isInstanceOf(HeaderContentNegotiationStrategy.class);
+	}
+
+	@Test
+	public void loadConfigWhenUserDetailsServiceHasCircularReferenceThenStillLoads() {
+		this.spring.register(RequiresUserDetailsServiceConfig.class, UserDetailsServiceConfig.class).autowire();
+
+		MyFilter myFilter = this.spring.getContext().getBean(MyFilter.class);
+
+		Throwable thrown = catchThrowable(() -> myFilter.userDetailsService.loadUserByUsername("user"));
+		assertThat(thrown).isNull();
+
+		thrown = catchThrowable(() -> myFilter.userDetailsService.loadUserByUsername("admin"));
+		assertThat(thrown).isInstanceOf(UsernameNotFoundException.class);
+	}
+
+	// SEC-2274: WebSecurityConfigurer adds ApplicationContext as a shared object
+	@Test
+	public void loadConfigWhenSharedObjectsCreatedThenApplicationContextAdded() {
+		this.spring.register(ApplicationContextSharedObjectConfig.class).autowire();
+
+		ApplicationContextSharedObjectConfig securityConfig = this.spring.getContext()
+				.getBean(ApplicationContextSharedObjectConfig.class);
+
+		assertThat(securityConfig.applicationContextSharedObject).isNotNull();
+		assertThat(securityConfig.applicationContextSharedObject).isSameAs(this.spring.getContext());
+	}
+
+	@Test
+	public void loadConfigWhenCustomAuthenticationTrustResolverBeanThenOverridesDefault() {
+		CustomTrustResolverConfig.AUTHENTICATION_TRUST_RESOLVER_BEAN = mock(AuthenticationTrustResolver.class);
+		this.spring.register(CustomTrustResolverConfig.class).autowire();
+
+		CustomTrustResolverConfig securityConfig = this.spring.getContext().getBean(CustomTrustResolverConfig.class);
+
+		assertThat(securityConfig.authenticationTrustResolverSharedObject).isNotNull();
+		assertThat(securityConfig.authenticationTrustResolverSharedObject)
+				.isSameAs(CustomTrustResolverConfig.AUTHENTICATION_TRUST_RESOLVER_BEAN);
+	}
+
+	@Test
+	public void compareOrderWebSecurityConfigurerAdapterWhenLowestOrderToDefaultOrderThenGreaterThanZero() {
+		AnnotationAwareOrderComparator comparator = new AnnotationAwareOrderComparator();
+		assertThat(comparator.compare(new LowestPriorityWebSecurityConfig(), new DefaultOrderWebSecurityConfig()))
+				.isGreaterThan(0);
+	}
+
+	// gh-7515
+	@Test
+	public void performWhenUsingAuthenticationEventPublisherBeanThenUses() throws Exception {
+		this.spring.register(CustomAuthenticationEventPublisherBean.class).autowire();
+
+		AuthenticationEventPublisher authenticationEventPublisher = this.spring.getContext()
+				.getBean(AuthenticationEventPublisher.class);
+
+		this.mockMvc.perform(get("/").with(httpBasic("user", "password")));
+
+		verify(authenticationEventPublisher).publishAuthenticationSuccess(any(Authentication.class));
+	}
+
+	// gh-4400
+	@Test
+	public void performWhenUsingAuthenticationEventPublisherInDslThenUses() throws Exception {
+		this.spring.register(CustomAuthenticationEventPublisherDsl.class).autowire();
+
+		AuthenticationEventPublisher authenticationEventPublisher = CustomAuthenticationEventPublisherDsl.EVENT_PUBLISHER;
+
+		this.mockMvc.perform(get("/").with(httpBasic("user", "password"))); // fails since
+																			// no
+																			// providers
+																			// configured
+
+		verify(authenticationEventPublisher).publishAuthenticationFailure(any(AuthenticationException.class),
+				any(Authentication.class));
+	}
+
 	@EnableWebSecurity
 	static class HeadersArePopulatedByDefaultConfig extends WebSecurityConfigurerAdapter {
 
@@ -109,16 +238,6 @@ public class WebSecurityConfigurerAdapterTests {
 
 	}
 
-	@Test
-	public void loadConfigWhenRequestAuthenticateThenAuthenticationEventPublished() throws Exception {
-		this.spring.register(InMemoryAuthWithWebSecurityConfigurerAdapter.class).autowire();
-
-		this.mockMvc.perform(formLogin()).andExpect(status().is3xxRedirection());
-
-		assertThat(InMemoryAuthWithWebSecurityConfigurerAdapter.EVENTS).isNotEmpty();
-		assertThat(InMemoryAuthWithWebSecurityConfigurerAdapter.EVENTS).hasSize(1);
-	}
-
 	@EnableWebSecurity
 	static class InMemoryAuthWithWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter
 			implements ApplicationListener {
@@ -141,16 +260,6 @@ public class WebSecurityConfigurerAdapterTests {
 
 	}
 
-	@Test
-	public void loadConfigWhenInMemoryConfigureProtectedThenPasswordUpgraded() throws Exception {
-		this.spring.register(InMemoryConfigureProtectedConfig.class).autowire();
-
-		this.mockMvc.perform(formLogin()).andExpect(status().is3xxRedirection());
-
-		UserDetailsService uds = this.spring.getContext().getBean(UserDetailsService.class);
-		assertThat(uds.loadUserByUsername("user").getPassword()).startsWith("{bcrypt}");
-	}
-
 	@EnableWebSecurity
 	static class InMemoryConfigureProtectedConfig extends WebSecurityConfigurerAdapter {
 
@@ -171,16 +280,6 @@ public class WebSecurityConfigurerAdapterTests {
 
 	}
 
-	@Test
-	public void loadConfigWhenInMemoryConfigureGlobalThenPasswordUpgraded() throws Exception {
-		this.spring.register(InMemoryConfigureGlobalConfig.class).autowire();
-
-		this.mockMvc.perform(formLogin()).andExpect(status().is3xxRedirection());
-
-		UserDetailsService uds = this.spring.getContext().getBean(UserDetailsService.class);
-		assertThat(uds.loadUserByUsername("user").getPassword()).startsWith("{bcrypt}");
-	}
-
 	@EnableWebSecurity
 	static class InMemoryConfigureGlobalConfig extends WebSecurityConfigurerAdapter {
 
@@ -201,20 +300,6 @@ public class WebSecurityConfigurerAdapterTests {
 
 	}
 
-	@Test
-	public void loadConfigWhenCustomContentNegotiationStrategyBeanThenOverridesDefault() {
-		OverrideContentNegotiationStrategySharedObjectConfig.CONTENT_NEGOTIATION_STRATEGY_BEAN = mock(
-				ContentNegotiationStrategy.class);
-		this.spring.register(OverrideContentNegotiationStrategySharedObjectConfig.class).autowire();
-
-		OverrideContentNegotiationStrategySharedObjectConfig securityConfig = this.spring.getContext()
-				.getBean(OverrideContentNegotiationStrategySharedObjectConfig.class);
-
-		assertThat(securityConfig.contentNegotiationStrategySharedObject).isNotNull();
-		assertThat(securityConfig.contentNegotiationStrategySharedObject)
-				.isSameAs(OverrideContentNegotiationStrategySharedObjectConfig.CONTENT_NEGOTIATION_STRATEGY_BEAN);
-	}
-
 	@EnableWebSecurity
 	static class OverrideContentNegotiationStrategySharedObjectConfig extends WebSecurityConfigurerAdapter {
 
@@ -235,18 +320,6 @@ public class WebSecurityConfigurerAdapterTests {
 
 	}
 
-	@Test
-	public void loadConfigWhenDefaultContentNegotiationStrategyThenHeaderContentNegotiationStrategy() {
-		this.spring.register(ContentNegotiationStrategyDefaultSharedObjectConfig.class).autowire();
-
-		ContentNegotiationStrategyDefaultSharedObjectConfig securityConfig = this.spring.getContext()
-				.getBean(ContentNegotiationStrategyDefaultSharedObjectConfig.class);
-
-		assertThat(securityConfig.contentNegotiationStrategySharedObject).isNotNull();
-		assertThat(securityConfig.contentNegotiationStrategySharedObject)
-				.isInstanceOf(HeaderContentNegotiationStrategy.class);
-	}
-
 	@EnableWebSecurity
 	static class ContentNegotiationStrategyDefaultSharedObjectConfig extends WebSecurityConfigurerAdapter {
 
@@ -260,19 +333,6 @@ public class WebSecurityConfigurerAdapterTests {
 
 	}
 
-	@Test
-	public void loadConfigWhenUserDetailsServiceHasCircularReferenceThenStillLoads() {
-		this.spring.register(RequiresUserDetailsServiceConfig.class, UserDetailsServiceConfig.class).autowire();
-
-		MyFilter myFilter = this.spring.getContext().getBean(MyFilter.class);
-
-		Throwable thrown = catchThrowable(() -> myFilter.userDetailsService.loadUserByUsername("user"));
-		assertThat(thrown).isNull();
-
-		thrown = catchThrowable(() -> myFilter.userDetailsService.loadUserByUsername("admin"));
-		assertThat(thrown).isInstanceOf(UsernameNotFoundException.class);
-	}
-
 	@Configuration
 	static class RequiresUserDetailsServiceConfig {
 
@@ -327,18 +387,6 @@ public class WebSecurityConfigurerAdapterTests {
 
 	}
 
-	// SEC-2274: WebSecurityConfigurer adds ApplicationContext as a shared object
-	@Test
-	public void loadConfigWhenSharedObjectsCreatedThenApplicationContextAdded() {
-		this.spring.register(ApplicationContextSharedObjectConfig.class).autowire();
-
-		ApplicationContextSharedObjectConfig securityConfig = this.spring.getContext()
-				.getBean(ApplicationContextSharedObjectConfig.class);
-
-		assertThat(securityConfig.applicationContextSharedObject).isNotNull();
-		assertThat(securityConfig.applicationContextSharedObject).isSameAs(this.spring.getContext());
-	}
-
 	@EnableWebSecurity
 	static class ApplicationContextSharedObjectConfig extends WebSecurityConfigurerAdapter {
 
@@ -352,18 +400,6 @@ public class WebSecurityConfigurerAdapterTests {
 
 	}
 
-	@Test
-	public void loadConfigWhenCustomAuthenticationTrustResolverBeanThenOverridesDefault() {
-		CustomTrustResolverConfig.AUTHENTICATION_TRUST_RESOLVER_BEAN = mock(AuthenticationTrustResolver.class);
-		this.spring.register(CustomTrustResolverConfig.class).autowire();
-
-		CustomTrustResolverConfig securityConfig = this.spring.getContext().getBean(CustomTrustResolverConfig.class);
-
-		assertThat(securityConfig.authenticationTrustResolverSharedObject).isNotNull();
-		assertThat(securityConfig.authenticationTrustResolverSharedObject)
-				.isSameAs(CustomTrustResolverConfig.AUTHENTICATION_TRUST_RESOLVER_BEAN);
-	}
-
 	@EnableWebSecurity
 	static class CustomTrustResolverConfig extends WebSecurityConfigurerAdapter {
 
@@ -384,13 +420,6 @@ public class WebSecurityConfigurerAdapterTests {
 
 	}
 
-	@Test
-	public void compareOrderWebSecurityConfigurerAdapterWhenLowestOrderToDefaultOrderThenGreaterThanZero() {
-		AnnotationAwareOrderComparator comparator = new AnnotationAwareOrderComparator();
-		assertThat(comparator.compare(new LowestPriorityWebSecurityConfig(), new DefaultOrderWebSecurityConfig()))
-				.isGreaterThan(0);
-	}
-
 	static class DefaultOrderWebSecurityConfig extends WebSecurityConfigurerAdapter {
 
 	}
@@ -400,19 +429,6 @@ public class WebSecurityConfigurerAdapterTests {
 
 	}
 
-	// gh-7515
-	@Test
-	public void performWhenUsingAuthenticationEventPublisherBeanThenUses() throws Exception {
-		this.spring.register(CustomAuthenticationEventPublisherBean.class).autowire();
-
-		AuthenticationEventPublisher authenticationEventPublisher = this.spring.getContext()
-				.getBean(AuthenticationEventPublisher.class);
-
-		this.mockMvc.perform(get("/").with(httpBasic("user", "password")));
-
-		verify(authenticationEventPublisher).publishAuthenticationSuccess(any(Authentication.class));
-	}
-
 	@EnableWebSecurity
 	static class CustomAuthenticationEventPublisherBean extends WebSecurityConfigurerAdapter {
 
@@ -429,22 +445,6 @@ public class WebSecurityConfigurerAdapterTests {
 
 	}
 
-	// gh-4400
-	@Test
-	public void performWhenUsingAuthenticationEventPublisherInDslThenUses() throws Exception {
-		this.spring.register(CustomAuthenticationEventPublisherDsl.class).autowire();
-
-		AuthenticationEventPublisher authenticationEventPublisher = CustomAuthenticationEventPublisherDsl.EVENT_PUBLISHER;
-
-		this.mockMvc.perform(get("/").with(httpBasic("user", "password"))); // fails since
-																			// no
-																			// providers
-																			// configured
-
-		verify(authenticationEventPublisher).publishAuthenticationFailure(any(AuthenticationException.class),
-				any(Authentication.class));
-	}
-
 	@EnableWebSecurity
 	static class CustomAuthenticationEventPublisherDsl extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.java
index 79e610a314..e84265cfdf 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.java
@@ -69,6 +69,28 @@ public class HttpConfigurationTests {
 				+ " Consider using addFilterBefore or addFilterAfter instead.");
 	}
 
+	// https://github.com/spring-projects/spring-security-javaconfig/issues/104
+	@Test
+	public void configureWhenAddFilterCasAuthenticationFilterThenFilterAdded() throws Exception {
+		CasAuthenticationFilterConfig.CAS_AUTHENTICATION_FILTER = spy(new CasAuthenticationFilter());
+		this.spring.register(CasAuthenticationFilterConfig.class).autowire();
+
+		this.mockMvc.perform(get("/"));
+
+		verify(CasAuthenticationFilterConfig.CAS_AUTHENTICATION_FILTER).doFilter(any(ServletRequest.class),
+				any(ServletResponse.class), any(FilterChain.class));
+	}
+
+	@Test
+	public void configureWhenConfigIsRequestMatchersJavadocThenAuthorizationApplied() throws Exception {
+		this.spring.register(RequestMatcherRegistryConfigs.class).autowire();
+
+		this.mockMvc.perform(get("/oauth/a")).andExpect(status().isUnauthorized());
+		this.mockMvc.perform(get("/oauth/b")).andExpect(status().isUnauthorized());
+		this.mockMvc.perform(get("/api/a")).andExpect(status().isUnauthorized());
+		this.mockMvc.perform(get("/api/b")).andExpect(status().isUnauthorized());
+	}
+
 	@EnableWebSecurity
 	static class UnregisteredFilterConfig extends WebSecurityConfigurerAdapter {
 
@@ -101,18 +123,6 @@ public class HttpConfigurationTests {
 
 	}
 
-	// https://github.com/spring-projects/spring-security-javaconfig/issues/104
-	@Test
-	public void configureWhenAddFilterCasAuthenticationFilterThenFilterAdded() throws Exception {
-		CasAuthenticationFilterConfig.CAS_AUTHENTICATION_FILTER = spy(new CasAuthenticationFilter());
-		this.spring.register(CasAuthenticationFilterConfig.class).autowire();
-
-		this.mockMvc.perform(get("/"));
-
-		verify(CasAuthenticationFilterConfig.CAS_AUTHENTICATION_FILTER).doFilter(any(ServletRequest.class),
-				any(ServletResponse.class), any(FilterChain.class));
-	}
-
 	@EnableWebSecurity
 	static class CasAuthenticationFilterConfig extends WebSecurityConfigurerAdapter {
 
@@ -128,16 +138,6 @@ public class HttpConfigurationTests {
 
 	}
 
-	@Test
-	public void configureWhenConfigIsRequestMatchersJavadocThenAuthorizationApplied() throws Exception {
-		this.spring.register(RequestMatcherRegistryConfigs.class).autowire();
-
-		this.mockMvc.perform(get("/oauth/a")).andExpect(status().isUnauthorized());
-		this.mockMvc.perform(get("/oauth/b")).andExpect(status().isUnauthorized());
-		this.mockMvc.perform(get("/api/a")).andExpect(status().isUnauthorized());
-		this.mockMvc.perform(get("/api/b")).andExpect(status().isUnauthorized());
-	}
-
 	@EnableWebSecurity
 	static class RequestMatcherRegistryConfigs extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java
index d695d5624d..4744963b5c 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java
@@ -101,6 +101,212 @@ public class NamespaceHttpTests {
 				any(), anyCollection());
 	}
 
+	@Test // http@access-denied-page
+	public void configureWhenAccessDeniedPageSetAndRequestForbiddenThenForwardedToAccessDeniedPage() throws Exception {
+		this.spring.register(AccessDeniedPageConfig.class).autowire();
+
+		this.mockMvc.perform(get("/admin").with(user(PasswordEncodedUser.user()))).andExpect(status().isForbidden())
+				.andExpect(forwardedUrl("/AccessDeniedPage"));
+	}
+
+	@Test // http@authentication-manager-ref
+	public void configureWhenAuthenticationManagerProvidedThenVerifyUse() throws Exception {
+		AuthenticationManagerRefConfig.AUTHENTICATION_MANAGER = mock(AuthenticationManager.class);
+		this.spring.register(AuthenticationManagerRefConfig.class).autowire();
+
+		this.mockMvc.perform(formLogin());
+
+		verify(AuthenticationManagerRefConfig.AUTHENTICATION_MANAGER, times(1)).authenticate(any(Authentication.class));
+	}
+
+	@Test // http@create-session=always
+	public void configureWhenSessionCreationPolicyAlwaysThenSessionCreatedOnRequest() throws Exception {
+		this.spring.register(CreateSessionAlwaysConfig.class).autowire();
+
+		MvcResult mvcResult = this.mockMvc.perform(get("/")).andReturn();
+		HttpSession session = mvcResult.getRequest().getSession(false);
+
+		assertThat(session).isNotNull();
+		assertThat(session.isNew()).isTrue();
+	}
+
+	@Test // http@create-session=stateless
+	public void configureWhenSessionCreationPolicyStatelessThenSessionNotCreatedOnRequest() throws Exception {
+		this.spring.register(CreateSessionStatelessConfig.class).autowire();
+
+		MvcResult mvcResult = this.mockMvc.perform(get("/")).andReturn();
+		HttpSession session = mvcResult.getRequest().getSession(false);
+
+		assertThat(session).isNull();
+	}
+
+	@Test // http@create-session=ifRequired
+	public void configureWhenSessionCreationPolicyIfRequiredThenSessionCreatedWhenRequiredOnRequest() throws Exception {
+		this.spring.register(IfRequiredConfig.class).autowire();
+
+		MvcResult mvcResult = this.mockMvc.perform(get("/unsecure")).andReturn();
+		HttpSession session = mvcResult.getRequest().getSession(false);
+
+		assertThat(session).isNull();
+
+		mvcResult = this.mockMvc.perform(formLogin()).andReturn();
+		session = mvcResult.getRequest().getSession(false);
+
+		assertThat(session).isNotNull();
+		assertThat(session.isNew()).isTrue();
+	}
+
+	@Test // http@create-session=never
+	public void configureWhenSessionCreationPolicyNeverThenSessionNotCreatedOnRequest() throws Exception {
+		this.spring.register(CreateSessionNeverConfig.class).autowire();
+
+		MvcResult mvcResult = this.mockMvc.perform(get("/")).andReturn();
+		HttpSession session = mvcResult.getRequest().getSession(false);
+
+		assertThat(session).isNull();
+	}
+
+	@Test // http@entry-point-ref
+	public void configureWhenAuthenticationEntryPointSetAndRequestUnauthorizedThenRedirectedToAuthenticationEntryPoint()
+			throws Exception {
+		this.spring.register(EntryPointRefConfig.class).autowire();
+
+		this.mockMvc.perform(get("/")).andExpect(status().is3xxRedirection())
+				.andExpect(redirectedUrlPattern("**/entry-point"));
+	}
+
+	@Test // http@jaas-api-provision
+	public void configureWhenJaasApiIntegrationFilterAddedThenJaasSubjectObtained() throws Exception {
+		LoginContext loginContext = mock(LoginContext.class);
+		when(loginContext.getSubject()).thenReturn(new Subject());
+
+		JaasAuthenticationToken authenticationToken = mock(JaasAuthenticationToken.class);
+		when(authenticationToken.isAuthenticated()).thenReturn(true);
+		when(authenticationToken.getLoginContext()).thenReturn(loginContext);
+
+		this.spring.register(JaasApiProvisionConfig.class).autowire();
+
+		this.mockMvc.perform(get("/").with(authentication(authenticationToken)));
+
+		verify(loginContext, times(1)).getSubject();
+	}
+
+	@Test // http@realm
+	public void configureWhenHttpBasicAndRequestUnauthorizedThenReturnWWWAuthenticateWithRealm() throws Exception {
+		this.spring.register(RealmConfig.class).autowire();
+
+		this.mockMvc.perform(get("/")).andExpect(status().isUnauthorized())
+				.andExpect(header().string("WWW-Authenticate", "Basic realm=\"RealmConfig\""));
+	}
+
+	@Test // http@request-matcher-ref ant
+	public void configureWhenAntPatternMatchingThenAntPathRequestMatcherUsed() {
+		this.spring.register(RequestMatcherAntConfig.class).autowire();
+
+		FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
+
+		assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class);
+		DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains()
+				.get(0);
+		assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class);
+	}
+
+	@Test // http@request-matcher-ref regex
+	public void configureWhenRegexPatternMatchingThenRegexRequestMatcherUsed() {
+		this.spring.register(RequestMatcherRegexConfig.class).autowire();
+
+		FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
+
+		assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class);
+		DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains()
+				.get(0);
+		assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(RegexRequestMatcher.class);
+	}
+
+	@Test // http@request-matcher-ref
+	public void configureWhenRequestMatcherProvidedThenRequestMatcherUsed() {
+		this.spring.register(RequestMatcherRefConfig.class).autowire();
+
+		FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
+
+		assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class);
+		DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains()
+				.get(0);
+		assertThat(securityFilterChain.getRequestMatcher())
+				.isInstanceOf(RequestMatcherRefConfig.MyRequestMatcher.class);
+	}
+
+	@Test // http@security=none
+	public void configureWhenIgnoredAntPatternsThenAntPathRequestMatcherUsedWithNoFilters() {
+		this.spring.register(SecurityNoneConfig.class).autowire();
+
+		FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
+
+		assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class);
+		DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains()
+				.get(0);
+		assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class);
+		assertThat(((AntPathRequestMatcher) securityFilterChain.getRequestMatcher()).getPattern())
+				.isEqualTo("/resources/**");
+		assertThat(securityFilterChain.getFilters()).isEmpty();
+
+		assertThat(filterChainProxy.getFilterChains().get(1)).isInstanceOf(DefaultSecurityFilterChain.class);
+		securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains().get(1);
+		assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class);
+		assertThat(((AntPathRequestMatcher) securityFilterChain.getRequestMatcher()).getPattern())
+				.isEqualTo("/public/**");
+		assertThat(securityFilterChain.getFilters()).isEmpty();
+	}
+
+	@Test // http@security-context-repository-ref
+	public void configureWhenNullSecurityContextRepositoryThenSecurityContextNotSavedInSession() throws Exception {
+		this.spring.register(SecurityContextRepoConfig.class).autowire();
+
+		MvcResult mvcResult = this.mockMvc.perform(formLogin()).andReturn();
+		HttpSession session = mvcResult.getRequest().getSession(false);
+		assertThat(session).isNull();
+	}
+
+	@Test // http@servlet-api-provision=false
+	public void configureWhenServletApiDisabledThenRequestNotServletApiWrapper() throws Exception {
+		this.spring.register(ServletApiProvisionConfig.class, MainController.class).autowire();
+
+		this.mockMvc.perform(get("/"));
+
+		assertThat(MainController.HTTP_SERVLET_REQUEST_TYPE)
+				.isNotInstanceOf(SecurityContextHolderAwareRequestWrapper.class);
+	}
+
+	@Test // http@servlet-api-provision defaults to true
+	public void configureWhenServletApiDefaultThenRequestIsServletApiWrapper() throws Exception {
+		this.spring.register(ServletApiProvisionDefaultsConfig.class, MainController.class).autowire();
+
+		this.mockMvc.perform(get("/"));
+
+		assertThat(SecurityContextHolderAwareRequestWrapper.class)
+				.isAssignableFrom(MainController.HTTP_SERVLET_REQUEST_TYPE);
+	}
+
+	@Test // http@use-expressions=true
+	public void configureWhenUseExpressionsEnabledThenExpressionBasedSecurityMetadataSource() {
+		this.spring.register(UseExpressionsConfig.class).autowire();
+
+		UseExpressionsConfig config = this.spring.getContext().getBean(UseExpressionsConfig.class);
+
+		assertThat(ExpressionBasedFilterInvocationSecurityMetadataSource.class)
+				.isAssignableFrom(config.filterInvocationSecurityMetadataSourceType);
+	}
+
+	@Test // http@use-expressions=false
+	public void configureWhenUseExpressionsDisabledThenDefaultSecurityMetadataSource() {
+		this.spring.register(DisableUseExpressionsConfig.class).autowire();
+
+		DisableUseExpressionsConfig config = this.spring.getContext().getBean(DisableUseExpressionsConfig.class);
+
+		assertThat(DefaultFilterInvocationSecurityMetadataSource.class)
+				.isAssignableFrom(config.filterInvocationSecurityMetadataSourceType);
+	}
+
 	@EnableWebSecurity
 	static class AccessDecisionManagerRefConfig extends WebSecurityConfigurerAdapter {
 
@@ -118,14 +324,6 @@ public class NamespaceHttpTests {
 
 	}
 
-	@Test // http@access-denied-page
-	public void configureWhenAccessDeniedPageSetAndRequestForbiddenThenForwardedToAccessDeniedPage() throws Exception {
-		this.spring.register(AccessDeniedPageConfig.class).autowire();
-
-		this.mockMvc.perform(get("/admin").with(user(PasswordEncodedUser.user()))).andExpect(status().isForbidden())
-				.andExpect(forwardedUrl("/AccessDeniedPage"));
-	}
-
 	@EnableWebSecurity
 	static class AccessDeniedPageConfig extends WebSecurityConfigurerAdapter {
 
@@ -144,16 +342,6 @@ public class NamespaceHttpTests {
 
 	}
 
-	@Test // http@authentication-manager-ref
-	public void configureWhenAuthenticationManagerProvidedThenVerifyUse() throws Exception {
-		AuthenticationManagerRefConfig.AUTHENTICATION_MANAGER = mock(AuthenticationManager.class);
-		this.spring.register(AuthenticationManagerRefConfig.class).autowire();
-
-		this.mockMvc.perform(formLogin());
-
-		verify(AuthenticationManagerRefConfig.AUTHENTICATION_MANAGER, times(1)).authenticate(any(Authentication.class));
-	}
-
 	@EnableWebSecurity
 	static class AuthenticationManagerRefConfig extends WebSecurityConfigurerAdapter {
 
@@ -177,17 +365,6 @@ public class NamespaceHttpTests {
 
 	}
 
-	@Test // http@create-session=always
-	public void configureWhenSessionCreationPolicyAlwaysThenSessionCreatedOnRequest() throws Exception {
-		this.spring.register(CreateSessionAlwaysConfig.class).autowire();
-
-		MvcResult mvcResult = this.mockMvc.perform(get("/")).andReturn();
-		HttpSession session = mvcResult.getRequest().getSession(false);
-
-		assertThat(session).isNotNull();
-		assertThat(session.isNew()).isTrue();
-	}
-
 	@EnableWebSecurity
 	static class CreateSessionAlwaysConfig extends WebSecurityConfigurerAdapter {
 
@@ -205,16 +382,6 @@ public class NamespaceHttpTests {
 
 	}
 
-	@Test // http@create-session=stateless
-	public void configureWhenSessionCreationPolicyStatelessThenSessionNotCreatedOnRequest() throws Exception {
-		this.spring.register(CreateSessionStatelessConfig.class).autowire();
-
-		MvcResult mvcResult = this.mockMvc.perform(get("/")).andReturn();
-		HttpSession session = mvcResult.getRequest().getSession(false);
-
-		assertThat(session).isNull();
-	}
-
 	@EnableWebSecurity
 	static class CreateSessionStatelessConfig extends WebSecurityConfigurerAdapter {
 
@@ -232,22 +399,6 @@ public class NamespaceHttpTests {
 
 	}
 
-	@Test // http@create-session=ifRequired
-	public void configureWhenSessionCreationPolicyIfRequiredThenSessionCreatedWhenRequiredOnRequest() throws Exception {
-		this.spring.register(IfRequiredConfig.class).autowire();
-
-		MvcResult mvcResult = this.mockMvc.perform(get("/unsecure")).andReturn();
-		HttpSession session = mvcResult.getRequest().getSession(false);
-
-		assertThat(session).isNull();
-
-		mvcResult = this.mockMvc.perform(formLogin()).andReturn();
-		session = mvcResult.getRequest().getSession(false);
-
-		assertThat(session).isNotNull();
-		assertThat(session.isNew()).isTrue();
-	}
-
 	@EnableWebSecurity
 	static class IfRequiredConfig extends WebSecurityConfigurerAdapter {
 
@@ -268,16 +419,6 @@ public class NamespaceHttpTests {
 
 	}
 
-	@Test // http@create-session=never
-	public void configureWhenSessionCreationPolicyNeverThenSessionNotCreatedOnRequest() throws Exception {
-		this.spring.register(CreateSessionNeverConfig.class).autowire();
-
-		MvcResult mvcResult = this.mockMvc.perform(get("/")).andReturn();
-		HttpSession session = mvcResult.getRequest().getSession(false);
-
-		assertThat(session).isNull();
-	}
-
 	@EnableWebSecurity
 	static class CreateSessionNeverConfig extends WebSecurityConfigurerAdapter {
 
@@ -295,15 +436,6 @@ public class NamespaceHttpTests {
 
 	}
 
-	@Test // http@entry-point-ref
-	public void configureWhenAuthenticationEntryPointSetAndRequestUnauthorizedThenRedirectedToAuthenticationEntryPoint()
-			throws Exception {
-		this.spring.register(EntryPointRefConfig.class).autowire();
-
-		this.mockMvc.perform(get("/")).andExpect(status().is3xxRedirection())
-				.andExpect(redirectedUrlPattern("**/entry-point"));
-	}
-
 	@EnableWebSecurity
 	static class EntryPointRefConfig extends WebSecurityConfigurerAdapter {
 
@@ -323,22 +455,6 @@ public class NamespaceHttpTests {
 
 	}
 
-	@Test // http@jaas-api-provision
-	public void configureWhenJaasApiIntegrationFilterAddedThenJaasSubjectObtained() throws Exception {
-		LoginContext loginContext = mock(LoginContext.class);
-		when(loginContext.getSubject()).thenReturn(new Subject());
-
-		JaasAuthenticationToken authenticationToken = mock(JaasAuthenticationToken.class);
-		when(authenticationToken.isAuthenticated()).thenReturn(true);
-		when(authenticationToken.getLoginContext()).thenReturn(loginContext);
-
-		this.spring.register(JaasApiProvisionConfig.class).autowire();
-
-		this.mockMvc.perform(get("/").with(authentication(authenticationToken)));
-
-		verify(loginContext, times(1)).getSubject();
-	}
-
 	@EnableWebSecurity
 	static class JaasApiProvisionConfig extends WebSecurityConfigurerAdapter {
 
@@ -352,14 +468,6 @@ public class NamespaceHttpTests {
 
 	}
 
-	@Test // http@realm
-	public void configureWhenHttpBasicAndRequestUnauthorizedThenReturnWWWAuthenticateWithRealm() throws Exception {
-		this.spring.register(RealmConfig.class).autowire();
-
-		this.mockMvc.perform(get("/")).andExpect(status().isUnauthorized())
-				.andExpect(header().string("WWW-Authenticate", "Basic realm=\"RealmConfig\""));
-	}
-
 	@EnableWebSecurity
 	static class RealmConfig extends WebSecurityConfigurerAdapter {
 
@@ -377,18 +485,6 @@ public class NamespaceHttpTests {
 
 	}
 
-	@Test // http@request-matcher-ref ant
-	public void configureWhenAntPatternMatchingThenAntPathRequestMatcherUsed() {
-		this.spring.register(RequestMatcherAntConfig.class).autowire();
-
-		FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
-
-		assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class);
-		DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains()
-				.get(0);
-		assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class);
-	}
-
 	@EnableWebSecurity
 	static class RequestMatcherAntConfig extends WebSecurityConfigurerAdapter {
 
@@ -402,18 +498,6 @@ public class NamespaceHttpTests {
 
 	}
 
-	@Test // http@request-matcher-ref regex
-	public void configureWhenRegexPatternMatchingThenRegexRequestMatcherUsed() {
-		this.spring.register(RequestMatcherRegexConfig.class).autowire();
-
-		FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
-
-		assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class);
-		DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains()
-				.get(0);
-		assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(RegexRequestMatcher.class);
-	}
-
 	@EnableWebSecurity
 	static class RequestMatcherRegexConfig extends WebSecurityConfigurerAdapter {
 
@@ -427,19 +511,6 @@ public class NamespaceHttpTests {
 
 	}
 
-	@Test // http@request-matcher-ref
-	public void configureWhenRequestMatcherProvidedThenRequestMatcherUsed() {
-		this.spring.register(RequestMatcherRefConfig.class).autowire();
-
-		FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
-
-		assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class);
-		DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains()
-				.get(0);
-		assertThat(securityFilterChain.getRequestMatcher())
-				.isInstanceOf(RequestMatcherRefConfig.MyRequestMatcher.class);
-	}
-
 	@EnableWebSecurity
 	static class RequestMatcherRefConfig extends WebSecurityConfigurerAdapter {
 
@@ -462,28 +533,6 @@ public class NamespaceHttpTests {
 
 	}
 
-	@Test // http@security=none
-	public void configureWhenIgnoredAntPatternsThenAntPathRequestMatcherUsedWithNoFilters() {
-		this.spring.register(SecurityNoneConfig.class).autowire();
-
-		FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
-
-		assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class);
-		DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains()
-				.get(0);
-		assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class);
-		assertThat(((AntPathRequestMatcher) securityFilterChain.getRequestMatcher()).getPattern())
-				.isEqualTo("/resources/**");
-		assertThat(securityFilterChain.getFilters()).isEmpty();
-
-		assertThat(filterChainProxy.getFilterChains().get(1)).isInstanceOf(DefaultSecurityFilterChain.class);
-		securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains().get(1);
-		assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class);
-		assertThat(((AntPathRequestMatcher) securityFilterChain.getRequestMatcher()).getPattern())
-				.isEqualTo("/public/**");
-		assertThat(securityFilterChain.getFilters()).isEmpty();
-	}
-
 	@EnableWebSecurity
 	static class SecurityNoneConfig extends WebSecurityConfigurerAdapter {
 
@@ -498,15 +547,6 @@ public class NamespaceHttpTests {
 
 	}
 
-	@Test // http@security-context-repository-ref
-	public void configureWhenNullSecurityContextRepositoryThenSecurityContextNotSavedInSession() throws Exception {
-		this.spring.register(SecurityContextRepoConfig.class).autowire();
-
-		MvcResult mvcResult = this.mockMvc.perform(formLogin()).andReturn();
-		HttpSession session = mvcResult.getRequest().getSession(false);
-		assertThat(session).isNull();
-	}
-
 	@EnableWebSecurity
 	static class SecurityContextRepoConfig extends WebSecurityConfigurerAdapter {
 
@@ -535,16 +575,6 @@ public class NamespaceHttpTests {
 
 	}
 
-	@Test // http@servlet-api-provision=false
-	public void configureWhenServletApiDisabledThenRequestNotServletApiWrapper() throws Exception {
-		this.spring.register(ServletApiProvisionConfig.class, MainController.class).autowire();
-
-		this.mockMvc.perform(get("/"));
-
-		assertThat(MainController.HTTP_SERVLET_REQUEST_TYPE)
-				.isNotInstanceOf(SecurityContextHolderAwareRequestWrapper.class);
-	}
-
 	@EnableWebSecurity
 	static class ServletApiProvisionConfig extends WebSecurityConfigurerAdapter {
 
@@ -562,16 +592,6 @@ public class NamespaceHttpTests {
 
 	}
 
-	@Test // http@servlet-api-provision defaults to true
-	public void configureWhenServletApiDefaultThenRequestIsServletApiWrapper() throws Exception {
-		this.spring.register(ServletApiProvisionDefaultsConfig.class, MainController.class).autowire();
-
-		this.mockMvc.perform(get("/"));
-
-		assertThat(SecurityContextHolderAwareRequestWrapper.class)
-				.isAssignableFrom(MainController.HTTP_SERVLET_REQUEST_TYPE);
-	}
-
 	@EnableWebSecurity
 	static class ServletApiProvisionDefaultsConfig extends WebSecurityConfigurerAdapter {
 
@@ -599,16 +619,6 @@ public class NamespaceHttpTests {
 
 	}
 
-	@Test // http@use-expressions=true
-	public void configureWhenUseExpressionsEnabledThenExpressionBasedSecurityMetadataSource() {
-		this.spring.register(UseExpressionsConfig.class).autowire();
-
-		UseExpressionsConfig config = this.spring.getContext().getBean(UseExpressionsConfig.class);
-
-		assertThat(ExpressionBasedFilterInvocationSecurityMetadataSource.class)
-				.isAssignableFrom(config.filterInvocationSecurityMetadataSourceType);
-	}
-
 	@EnableWebSecurity
 	static class UseExpressionsConfig extends WebSecurityConfigurerAdapter {
 
@@ -638,16 +648,6 @@ public class NamespaceHttpTests {
 
 	}
 
-	@Test // http@use-expressions=false
-	public void configureWhenUseExpressionsDisabledThenDefaultSecurityMetadataSource() {
-		this.spring.register(DisableUseExpressionsConfig.class).autowire();
-
-		DisableUseExpressionsConfig config = this.spring.getContext().getBean(DisableUseExpressionsConfig.class);
-
-		assertThat(DefaultFilterInvocationSecurityMetadataSource.class)
-				.isAssignableFrom(config.filterInvocationSecurityMetadataSourceType);
-	}
-
 	@EnableWebSecurity
 	static class DisableUseExpressionsConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/builders/WebSecurityTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/builders/WebSecurityTests.java
index b773e244c8..223dabf3b2 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/builders/WebSecurityTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/builders/WebSecurityTests.java
@@ -103,6 +103,50 @@ public class WebSecurityTests {
 		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
 	}
 
+	@Test
+	public void ignoringMvcMatcherServletPath() throws Exception {
+		loadConfig(MvcMatcherServletPathConfig.class, LegacyMvcMatchingConfig.class);
+
+		this.request.setServletPath("/spring");
+		this.request.setRequestURI("/spring/path");
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
+
+		setup();
+
+		this.request.setServletPath("/spring");
+		this.request.setRequestURI("/spring/path.html");
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
+
+		setup();
+
+		this.request.setServletPath("/spring");
+		this.request.setRequestURI("/spring/path/");
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
+
+		setup();
+
+		this.request.setServletPath("/other");
+		this.request.setRequestURI("/other/path");
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
+	}
+
+	public void loadConfig(Class... configs) {
+		this.context = new AnnotationConfigWebApplicationContext();
+		this.context.register(configs);
+		this.context.setServletContext(new MockServletContext());
+		this.context.refresh();
+
+		this.context.getAutowireCapableBeanFactory().autowireBean(this);
+	}
+
 	@EnableWebSecurity
 	@Configuration
 	@EnableWebMvc
@@ -147,41 +191,6 @@ public class WebSecurityTests {
 
 	}
 
-	@Test
-	public void ignoringMvcMatcherServletPath() throws Exception {
-		loadConfig(MvcMatcherServletPathConfig.class, LegacyMvcMatchingConfig.class);
-
-		this.request.setServletPath("/spring");
-		this.request.setRequestURI("/spring/path");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
-
-		setup();
-
-		this.request.setServletPath("/spring");
-		this.request.setRequestURI("/spring/path.html");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
-
-		setup();
-
-		this.request.setServletPath("/spring");
-		this.request.setRequestURI("/spring/path/");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
-
-		setup();
-
-		this.request.setServletPath("/other");
-		this.request.setRequestURI("/other/path");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
-	}
-
 	@EnableWebSecurity
 	@Configuration
 	@EnableWebMvc
@@ -237,13 +246,4 @@ public class WebSecurityTests {
 
 	}
 
-	public void loadConfig(Class... configs) {
-		this.context = new AnnotationConfigWebApplicationContext();
-		this.context.register(configs);
-		this.context.setServletContext(new MockServletContext());
-		this.context.refresh();
-
-		this.context.getAutowireCapableBeanFactory().autowireBean(this);
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurityTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurityTests.java
index aaa399372f..962db3234d 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurityTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurityTests.java
@@ -63,6 +63,48 @@ public class EnableWebSecurityTests {
 		assertThat(authentication.isAuthenticated()).isTrue();
 	}
 
+	@Test
+	public void loadConfigWhenChildConfigExtendsSecurityConfigThenSecurityConfigInherited() {
+		this.spring.register(ChildSecurityConfig.class).autowire();
+		this.spring.getContext().getBean("springSecurityFilterChain", DebugFilter.class);
+	}
+
+	@Test
+	public void configureWhenEnableWebMvcThenAuthenticationPrincipalResolvable() throws Exception {
+		this.spring.register(AuthenticationPrincipalConfig.class).autowire();
+
+		this.mockMvc.perform(get("/").with(authentication(new TestingAuthenticationToken("user1", "password"))))
+				.andExpect(content().string("user1"));
+	}
+
+	@Test
+	public void securityFilterChainWhenEnableWebMvcThenAuthenticationPrincipalResolvable() throws Exception {
+		this.spring.register(SecurityFilterChainAuthenticationPrincipalConfig.class).autowire();
+
+		this.mockMvc.perform(get("/").with(authentication(new TestingAuthenticationToken("user1", "password"))))
+				.andExpect(content().string("user1"));
+	}
+
+	@Test
+	public void enableWebSecurityWhenNoConfigurationAnnotationThenBeanProxyingEnabled() {
+		this.spring.register(BeanProxyEnabledByDefaultConfig.class).autowire();
+
+		Child childBean = this.spring.getContext().getBean(Child.class);
+		Parent parentBean = this.spring.getContext().getBean(Parent.class);
+
+		assertThat(parentBean.getChild()).isSameAs(childBean);
+	}
+
+	@Test
+	public void enableWebSecurityWhenProxyBeanMethodsFalseThenBeanProxyingDisabled() {
+		this.spring.register(BeanProxyDisabledConfig.class).autowire();
+
+		Child childBean = this.spring.getContext().getBean(Child.class);
+		Parent parentBean = this.spring.getContext().getBean(Parent.class);
+
+		assertThat(parentBean.getChild()).isNotSameAs(childBean);
+	}
+
 	@EnableWebSecurity
 	static class SecurityConfig extends WebSecurityConfigurerAdapter {
 
@@ -94,12 +136,6 @@ public class EnableWebSecurityTests {
 
 	}
 
-	@Test
-	public void loadConfigWhenChildConfigExtendsSecurityConfigThenSecurityConfigInherited() {
-		this.spring.register(ChildSecurityConfig.class).autowire();
-		this.spring.getContext().getBean("springSecurityFilterChain", DebugFilter.class);
-	}
-
 	@Configuration
 	static class ChildSecurityConfig extends DebugSecurityConfig {
 
@@ -110,14 +146,6 @@ public class EnableWebSecurityTests {
 
 	}
 
-	@Test
-	public void configureWhenEnableWebMvcThenAuthenticationPrincipalResolvable() throws Exception {
-		this.spring.register(AuthenticationPrincipalConfig.class).autowire();
-
-		this.mockMvc.perform(get("/").with(authentication(new TestingAuthenticationToken("user1", "password"))))
-				.andExpect(content().string("user1"));
-	}
-
 	@EnableWebSecurity
 	@EnableWebMvc
 	static class AuthenticationPrincipalConfig extends WebSecurityConfigurerAdapter {
@@ -138,14 +166,6 @@ public class EnableWebSecurityTests {
 
 	}
 
-	@Test
-	public void securityFilterChainWhenEnableWebMvcThenAuthenticationPrincipalResolvable() throws Exception {
-		this.spring.register(SecurityFilterChainAuthenticationPrincipalConfig.class).autowire();
-
-		this.mockMvc.perform(get("/").with(authentication(new TestingAuthenticationToken("user1", "password"))))
-				.andExpect(content().string("user1"));
-	}
-
 	@EnableWebSecurity
 	@EnableWebMvc
 	static class SecurityFilterChainAuthenticationPrincipalConfig {
@@ -167,16 +187,6 @@ public class EnableWebSecurityTests {
 
 	}
 
-	@Test
-	public void enableWebSecurityWhenNoConfigurationAnnotationThenBeanProxyingEnabled() {
-		this.spring.register(BeanProxyEnabledByDefaultConfig.class).autowire();
-
-		Child childBean = this.spring.getContext().getBean(Child.class);
-		Parent parentBean = this.spring.getContext().getBean(Parent.class);
-
-		assertThat(parentBean.getChild()).isSameAs(childBean);
-	}
-
 	@EnableWebSecurity
 	static class BeanProxyEnabledByDefaultConfig extends WebSecurityConfigurerAdapter {
 
@@ -192,16 +202,6 @@ public class EnableWebSecurityTests {
 
 	}
 
-	@Test
-	public void enableWebSecurityWhenProxyBeanMethodsFalseThenBeanProxyingDisabled() {
-		this.spring.register(BeanProxyDisabledConfig.class).autowire();
-
-		Child childBean = this.spring.getContext().getBean(Child.class);
-		Parent parentBean = this.spring.getContext().getBean(Parent.class);
-
-		assertThat(parentBean.getChild()).isNotSameAs(childBean);
-	}
-
 	@Configuration(proxyBeanMethods = false)
 	@EnableWebSecurity
 	static class BeanProxyDisabledConfig extends WebSecurityConfigurerAdapter {
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfigurationTests.java
index bbe01aaf1d..6e2eb6804c 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfigurationTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfigurationTests.java
@@ -114,26 +114,6 @@ public class HttpSecurityConfigurationTests {
 		this.mockMvc.perform(asyncDispatch(mvcResult)).andExpect(status().isOk()).andExpect(content().string("Bob"));
 	}
 
-	@RestController
-	static class NameController {
-
-		@GetMapping("/name")
-		public Callable name() {
-			return () -> SecurityContextHolder.getContext().getAuthentication().getName();
-		}
-
-	}
-
-	@EnableWebSecurity
-	static class DefaultWithFilterChainConfig {
-
-		@Bean
-		public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
-			return http.build();
-		}
-
-	}
-
 	@Test
 	public void getWhenDefaultFilterChainBeanThenAnonymousPermitted() throws Exception {
 		this.spring.register(AuthorizeRequestsConfig.class, UserDetailsConfig.class, BaseController.class).autowire();
@@ -141,16 +121,6 @@ public class HttpSecurityConfigurationTests {
 		this.mockMvc.perform(get("/")).andExpect(status().isOk());
 	}
 
-	@EnableWebSecurity
-	static class AuthorizeRequestsConfig {
-
-		@Bean
-		public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
-			return http.authorizeRequests(authorize -> authorize.anyRequest().permitAll()).build();
-		}
-
-	}
-
 	@Test
 	public void authenticateWhenDefaultFilterChainBeanThenSessionIdChanges() throws Exception {
 		this.spring.register(SecurityEnabledConfig.class, UserDetailsConfig.class).autowire();
@@ -194,6 +164,36 @@ public class HttpSecurityConfigurationTests {
 		this.mockMvc.perform(get("/login")).andExpect(status().isOk());
 	}
 
+	@RestController
+	static class NameController {
+
+		@GetMapping("/name")
+		public Callable name() {
+			return () -> SecurityContextHolder.getContext().getAuthentication().getName();
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class DefaultWithFilterChainConfig {
+
+		@Bean
+		public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
+			return http.build();
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class AuthorizeRequestsConfig {
+
+		@Bean
+		public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
+			return http.authorizeRequests(authorize -> authorize.anyRequest().permitAll()).build();
+		}
+
+	}
+
 	@EnableWebSecurity
 	static class SecurityEnabledConfig {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfigurationTests.java
index 6a1edaec4f..08af641427 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfigurationTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfigurationTests.java
@@ -133,6 +133,68 @@ public class OAuth2ClientConfigurationTests {
 		verify(accessTokenResponseClient, times(1)).getTokenResponse(any(OAuth2ClientCredentialsGrantRequest.class));
 	}
 
+	// gh-5321
+	@Test
+	public void loadContextWhenOAuth2AuthorizedClientRepositoryRegisteredTwiceThenThrowNoUniqueBeanDefinitionException() {
+		assertThatThrownBy(
+				() -> this.spring.register(OAuth2AuthorizedClientRepositoryRegisteredTwiceConfig.class).autowire())
+						.hasRootCauseInstanceOf(NoUniqueBeanDefinitionException.class)
+						.hasMessageContaining("Expected single matching bean of type '"
+								+ OAuth2AuthorizedClientRepository.class.getName()
+								+ "' but found 2: authorizedClientRepository1,authorizedClientRepository2");
+	}
+
+	@Test
+	public void loadContextWhenClientRegistrationRepositoryNotRegisteredThenThrowNoSuchBeanDefinitionException() {
+		assertThatThrownBy(() -> this.spring.register(ClientRegistrationRepositoryNotRegisteredConfig.class).autowire())
+				.hasRootCauseInstanceOf(NoSuchBeanDefinitionException.class).hasMessageContaining(
+						"No qualifying bean of type '" + ClientRegistrationRepository.class.getName() + "' available");
+	}
+
+	@Test
+	public void loadContextWhenClientRegistrationRepositoryRegisteredTwiceThenThrowNoUniqueBeanDefinitionException() {
+		assertThatThrownBy(() -> this.spring.register(ClientRegistrationRepositoryRegisteredTwiceConfig.class)
+				.autowire()).hasRootCauseInstanceOf(NoUniqueBeanDefinitionException.class).hasMessageContaining(
+						"expected single matching bean but found 2: clientRegistrationRepository1,clientRegistrationRepository2");
+	}
+
+	@Test
+	public void loadContextWhenAccessTokenResponseClientRegisteredTwiceThenThrowNoUniqueBeanDefinitionException() {
+		assertThatThrownBy(() -> this.spring.register(AccessTokenResponseClientRegisteredTwiceConfig.class).autowire())
+				.hasRootCauseInstanceOf(NoUniqueBeanDefinitionException.class).hasMessageContaining(
+						"expected single matching bean but found 2: accessTokenResponseClient1,accessTokenResponseClient2");
+	}
+
+	// gh-8700
+	@Test
+	public void requestWhenAuthorizedClientManagerConfiguredThenUsed() throws Exception {
+		String clientRegistrationId = "client1";
+		String principalName = "user1";
+		TestingAuthenticationToken authentication = new TestingAuthenticationToken(principalName, "password");
+
+		ClientRegistrationRepository clientRegistrationRepository = mock(ClientRegistrationRepository.class);
+		OAuth2AuthorizedClientRepository authorizedClientRepository = mock(OAuth2AuthorizedClientRepository.class);
+		OAuth2AuthorizedClientManager authorizedClientManager = mock(OAuth2AuthorizedClientManager.class);
+
+		ClientRegistration clientRegistration = clientRegistration().registrationId(clientRegistrationId).build();
+		OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(clientRegistration, principalName,
+				TestOAuth2AccessTokens.noScopes());
+
+		when(authorizedClientManager.authorize(any())).thenReturn(authorizedClient);
+
+		OAuth2AuthorizedClientManagerRegisteredConfig.CLIENT_REGISTRATION_REPOSITORY = clientRegistrationRepository;
+		OAuth2AuthorizedClientManagerRegisteredConfig.AUTHORIZED_CLIENT_REPOSITORY = authorizedClientRepository;
+		OAuth2AuthorizedClientManagerRegisteredConfig.AUTHORIZED_CLIENT_MANAGER = authorizedClientManager;
+		this.spring.register(OAuth2AuthorizedClientManagerRegisteredConfig.class).autowire();
+
+		this.mockMvc.perform(get("/authorized-client").with(authentication(authentication))).andExpect(status().isOk())
+				.andExpect(content().string("resolved"));
+
+		verify(authorizedClientManager).authorize(any());
+		verifyNoInteractions(clientRegistrationRepository);
+		verifyNoInteractions(authorizedClientRepository);
+	}
+
 	@EnableWebMvc
 	@EnableWebSecurity
 	static class OAuth2AuthorizedClientArgumentResolverConfig extends WebSecurityConfigurerAdapter {
@@ -145,17 +207,6 @@ public class OAuth2ClientConfigurationTests {
 		protected void configure(HttpSecurity http) {
 		}
 
-		@RestController
-		public class Controller {
-
-			@GetMapping("/authorized-client")
-			public String authorizedClient(
-					@RegisteredOAuth2AuthorizedClient("client1") OAuth2AuthorizedClient authorizedClient) {
-				return authorizedClient != null ? "resolved" : "not-resolved";
-			}
-
-		}
-
 		@Bean
 		public ClientRegistrationRepository clientRegistrationRepository() {
 			return CLIENT_REGISTRATION_REPOSITORY;
@@ -171,17 +222,17 @@ public class OAuth2ClientConfigurationTests {
 			return ACCESS_TOKEN_RESPONSE_CLIENT;
 		}
 
-	}
+		@RestController
+		public class Controller {
+
+			@GetMapping("/authorized-client")
+			public String authorizedClient(
+					@RegisteredOAuth2AuthorizedClient("client1") OAuth2AuthorizedClient authorizedClient) {
+				return authorizedClient != null ? "resolved" : "not-resolved";
+			}
+
+		}
 
-	// gh-5321
-	@Test
-	public void loadContextWhenOAuth2AuthorizedClientRepositoryRegisteredTwiceThenThrowNoUniqueBeanDefinitionException() {
-		assertThatThrownBy(
-				() -> this.spring.register(OAuth2AuthorizedClientRepositoryRegisteredTwiceConfig.class).autowire())
-						.hasRootCauseInstanceOf(NoUniqueBeanDefinitionException.class)
-						.hasMessageContaining("Expected single matching bean of type '"
-								+ OAuth2AuthorizedClientRepository.class.getName()
-								+ "' but found 2: authorizedClientRepository1,authorizedClientRepository2");
 	}
 
 	@EnableWebMvc
@@ -221,13 +272,6 @@ public class OAuth2ClientConfigurationTests {
 
 	}
 
-	@Test
-	public void loadContextWhenClientRegistrationRepositoryNotRegisteredThenThrowNoSuchBeanDefinitionException() {
-		assertThatThrownBy(() -> this.spring.register(ClientRegistrationRepositoryNotRegisteredConfig.class).autowire())
-				.hasRootCauseInstanceOf(NoSuchBeanDefinitionException.class).hasMessageContaining(
-						"No qualifying bean of type '" + ClientRegistrationRepository.class.getName() + "' available");
-	}
-
 	@EnableWebMvc
 	@EnableWebSecurity
 	static class ClientRegistrationRepositoryNotRegisteredConfig extends WebSecurityConfigurerAdapter {
@@ -245,13 +289,6 @@ public class OAuth2ClientConfigurationTests {
 
 	}
 
-	@Test
-	public void loadContextWhenClientRegistrationRepositoryRegisteredTwiceThenThrowNoUniqueBeanDefinitionException() {
-		assertThatThrownBy(() -> this.spring.register(ClientRegistrationRepositoryRegisteredTwiceConfig.class)
-				.autowire()).hasRootCauseInstanceOf(NoUniqueBeanDefinitionException.class).hasMessageContaining(
-						"expected single matching bean but found 2: clientRegistrationRepository1,clientRegistrationRepository2");
-	}
-
 	@EnableWebMvc
 	@EnableWebSecurity
 	static class ClientRegistrationRepositoryRegisteredTwiceConfig extends WebSecurityConfigurerAdapter {
@@ -289,13 +326,6 @@ public class OAuth2ClientConfigurationTests {
 
 	}
 
-	@Test
-	public void loadContextWhenAccessTokenResponseClientRegisteredTwiceThenThrowNoUniqueBeanDefinitionException() {
-		assertThatThrownBy(() -> this.spring.register(AccessTokenResponseClientRegisteredTwiceConfig.class).autowire())
-				.hasRootCauseInstanceOf(NoUniqueBeanDefinitionException.class).hasMessageContaining(
-						"expected single matching bean but found 2: accessTokenResponseClient1,accessTokenResponseClient2");
-	}
-
 	@EnableWebMvc
 	@EnableWebSecurity
 	static class AccessTokenResponseClientRegisteredTwiceConfig extends WebSecurityConfigurerAdapter {
@@ -333,36 +363,6 @@ public class OAuth2ClientConfigurationTests {
 
 	}
 
-	// gh-8700
-	@Test
-	public void requestWhenAuthorizedClientManagerConfiguredThenUsed() throws Exception {
-		String clientRegistrationId = "client1";
-		String principalName = "user1";
-		TestingAuthenticationToken authentication = new TestingAuthenticationToken(principalName, "password");
-
-		ClientRegistrationRepository clientRegistrationRepository = mock(ClientRegistrationRepository.class);
-		OAuth2AuthorizedClientRepository authorizedClientRepository = mock(OAuth2AuthorizedClientRepository.class);
-		OAuth2AuthorizedClientManager authorizedClientManager = mock(OAuth2AuthorizedClientManager.class);
-
-		ClientRegistration clientRegistration = clientRegistration().registrationId(clientRegistrationId).build();
-		OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(clientRegistration, principalName,
-				TestOAuth2AccessTokens.noScopes());
-
-		when(authorizedClientManager.authorize(any())).thenReturn(authorizedClient);
-
-		OAuth2AuthorizedClientManagerRegisteredConfig.CLIENT_REGISTRATION_REPOSITORY = clientRegistrationRepository;
-		OAuth2AuthorizedClientManagerRegisteredConfig.AUTHORIZED_CLIENT_REPOSITORY = authorizedClientRepository;
-		OAuth2AuthorizedClientManagerRegisteredConfig.AUTHORIZED_CLIENT_MANAGER = authorizedClientManager;
-		this.spring.register(OAuth2AuthorizedClientManagerRegisteredConfig.class).autowire();
-
-		this.mockMvc.perform(get("/authorized-client").with(authentication(authentication))).andExpect(status().isOk())
-				.andExpect(content().string("resolved"));
-
-		verify(authorizedClientManager).authorize(any());
-		verifyNoInteractions(clientRegistrationRepository);
-		verifyNoInteractions(authorizedClientRepository);
-	}
-
 	@EnableWebMvc
 	@EnableWebSecurity
 	static class OAuth2AuthorizedClientManagerRegisteredConfig extends WebSecurityConfigurerAdapter {
@@ -375,17 +375,6 @@ public class OAuth2ClientConfigurationTests {
 		protected void configure(HttpSecurity http) {
 		}
 
-		@RestController
-		public class Controller {
-
-			@GetMapping("/authorized-client")
-			public String authorizedClient(
-					@RegisteredOAuth2AuthorizedClient("client1") OAuth2AuthorizedClient authorizedClient) {
-				return authorizedClient != null ? "resolved" : "not-resolved";
-			}
-
-		}
-
 		@Bean
 		public ClientRegistrationRepository clientRegistrationRepository() {
 			return CLIENT_REGISTRATION_REPOSITORY;
@@ -401,6 +390,17 @@ public class OAuth2ClientConfigurationTests {
 			return AUTHORIZED_CLIENT_MANAGER;
 		}
 
+		@RestController
+		public class Controller {
+
+			@GetMapping("/authorized-client")
+			public String authorizedClient(
+					@RegisteredOAuth2AuthorizedClient("client1") OAuth2AuthorizedClient authorizedClient) {
+				return authorizedClient != null ? "resolved" : "not-resolved";
+			}
+
+		}
+
 	}
 
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/Sec2515Tests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/Sec2515Tests.java
index 744147312b..d81ecb80d0 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/Sec2515Tests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/Sec2515Tests.java
@@ -45,33 +45,11 @@ public class Sec2515Tests {
 		this.spring.register(StackOverflowSecurityConfig.class).autowire();
 	}
 
-	@EnableWebSecurity
-	static class StackOverflowSecurityConfig extends WebSecurityConfigurerAdapter {
-
-		@Bean
-		@Override
-		public AuthenticationManager authenticationManagerBean() throws Exception {
-			return super.authenticationManagerBean();
-		}
-
-	}
-
 	@Test(expected = FatalBeanException.class)
 	public void loadConfigWhenAuthenticationManagerNotConfiguredAndRegisterBeanCustomNameThenThrowFatalBeanException() {
 		this.spring.register(CustomBeanNameStackOverflowSecurityConfig.class).autowire();
 	}
 
-	@EnableWebSecurity
-	static class CustomBeanNameStackOverflowSecurityConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		@Bean(name = "custom")
-		public AuthenticationManager authenticationManagerBean() throws Exception {
-			return super.authenticationManagerBean();
-		}
-
-	}
-
 	// SEC-2549
 	@Test
 	public void loadConfigWhenChildClassLoaderSetThenContextLoads() {
@@ -83,6 +61,33 @@ public class Sec2515Tests {
 		this.spring.autowire();
 
 		assertThat(this.spring.getContext().getBean(AuthenticationManager.class)).isNotNull();
+	} // SEC-2515
+
+	@Test
+	public void loadConfigWhenAuthenticationManagerConfiguredAndRegisterBeanThenContextLoads() {
+		this.spring.register(SecurityConfig.class).autowire();
+	}
+
+	@EnableWebSecurity
+	static class StackOverflowSecurityConfig extends WebSecurityConfigurerAdapter {
+
+		@Bean
+		@Override
+		public AuthenticationManager authenticationManagerBean() throws Exception {
+			return super.authenticationManagerBean();
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class CustomBeanNameStackOverflowSecurityConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		@Bean(name = "custom")
+		public AuthenticationManager authenticationManagerBean() throws Exception {
+			return super.authenticationManagerBean();
+		}
+
 	}
 
 	@EnableWebSecurity
@@ -98,12 +103,6 @@ public class Sec2515Tests {
 
 	}
 
-	// SEC-2515
-	@Test
-	public void loadConfigWhenAuthenticationManagerConfiguredAndRegisterBeanThenContextLoads() {
-		this.spring.register(SecurityConfig.class).autowire();
-	}
-
 	@EnableWebSecurity
 	static class SecurityConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java
index 1a86b00a1a..c5eb62cd68 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java
@@ -79,6 +79,9 @@ public class WebSecurityConfigurationTests {
 	@Rule
 	public final SpringTestRule spring = new SpringTestRule();
 
+	@Rule
+	public SpringTestRule child = new SpringTestRule();
+
 	@Autowired
 	private MockMvc mockMvc;
 
@@ -113,6 +116,177 @@ public class WebSecurityConfigurationTests {
 		assertThat(filterChains.get(5).matches(request)).isTrue();
 	}
 
+	@Test
+	public void loadConfigWhenSecurityFilterChainsHaveOrderThenFilterChainsOrdered() {
+		this.spring.register(SortedSecurityFilterChainConfig.class).autowire();
+
+		FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
+		List filterChains = filterChainProxy.getFilterChains();
+		assertThat(filterChains).hasSize(4);
+
+		MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
+
+		request.setServletPath("/role1/**");
+		assertThat(filterChains.get(0).matches(request)).isTrue();
+
+		request.setServletPath("/role2/**");
+		assertThat(filterChains.get(1).matches(request)).isTrue();
+
+		request.setServletPath("/role3/**");
+		assertThat(filterChains.get(2).matches(request)).isTrue();
+
+		request.setServletPath("/**");
+		assertThat(filterChains.get(3).matches(request)).isTrue();
+	}
+
+	@Test
+	public void loadConfigWhenWebSecurityConfigurersHaveSameOrderThenThrowBeanCreationException() {
+		Throwable thrown = catchThrowable(() -> this.spring.register(DuplicateOrderConfig.class).autowire());
+
+		assertThat(thrown).isInstanceOf(BeanCreationException.class)
+				.hasMessageContaining("@Order on WebSecurityConfigurers must be unique")
+				.hasMessageContaining(DuplicateOrderConfig.WebConfigurer1.class.getName())
+				.hasMessageContaining(DuplicateOrderConfig.WebConfigurer2.class.getName());
+	}
+
+	@Test
+	public void loadConfigWhenWebInvocationPrivilegeEvaluatorSetThenIsRegistered() {
+		PrivilegeEvaluatorConfigurerAdapterConfig.PRIVILEGE_EVALUATOR = mock(WebInvocationPrivilegeEvaluator.class);
+
+		this.spring.register(PrivilegeEvaluatorConfigurerAdapterConfig.class).autowire();
+
+		assertThat(this.spring.getContext().getBean(WebInvocationPrivilegeEvaluator.class))
+				.isSameAs(PrivilegeEvaluatorConfigurerAdapterConfig.PRIVILEGE_EVALUATOR);
+	}
+
+	@Test
+	public void loadConfigWhenSecurityExpressionHandlerSetThenIsRegistered() {
+		WebSecurityExpressionHandlerConfig.EXPRESSION_HANDLER = mock(SecurityExpressionHandler.class);
+		when(WebSecurityExpressionHandlerConfig.EXPRESSION_HANDLER.getExpressionParser())
+				.thenReturn(mock(ExpressionParser.class));
+
+		this.spring.register(WebSecurityExpressionHandlerConfig.class).autowire();
+
+		assertThat(this.spring.getContext().getBean(SecurityExpressionHandler.class))
+				.isSameAs(WebSecurityExpressionHandlerConfig.EXPRESSION_HANDLER);
+	}
+
+	@Test
+	public void loadConfigWhenSecurityExpressionHandlerIsNullThenException() {
+		Throwable thrown = catchThrowable(
+				() -> this.spring.register(NullWebSecurityExpressionHandlerConfig.class).autowire());
+
+		assertThat(thrown).isInstanceOf(BeanCreationException.class);
+		assertThat(thrown).hasRootCauseExactlyInstanceOf(IllegalArgumentException.class);
+	}
+
+	@Test
+	public void loadConfigWhenDefaultSecurityExpressionHandlerThenDefaultIsRegistered() {
+		this.spring.register(WebSecurityExpressionHandlerDefaultsConfig.class).autowire();
+
+		assertThat(this.spring.getContext().getBean(SecurityExpressionHandler.class))
+				.isInstanceOf(DefaultWebSecurityExpressionHandler.class);
+	}
+
+	@Test
+	public void securityExpressionHandlerWhenRoleHierarchyBeanThenRoleHierarchyUsed() {
+		this.spring.register(WebSecurityExpressionHandlerRoleHierarchyBeanConfig.class).autowire();
+		TestingAuthenticationToken authentication = new TestingAuthenticationToken("user", "notused", "ROLE_ADMIN");
+		FilterInvocation invocation = new FilterInvocation(new MockHttpServletRequest("GET", ""),
+				new MockHttpServletResponse(), new MockFilterChain());
+
+		AbstractSecurityExpressionHandler handler = this.spring.getContext()
+				.getBean(AbstractSecurityExpressionHandler.class);
+		EvaluationContext evaluationContext = handler.createEvaluationContext(authentication, invocation);
+		Expression expression = handler.getExpressionParser().parseExpression("hasRole('ROLE_USER')");
+		boolean granted = expression.getValue(evaluationContext, Boolean.class);
+		assertThat(granted).isTrue();
+	}
+
+	@Test
+	public void securityExpressionHandlerWhenPermissionEvaluatorBeanThenPermissionEvaluatorUsed() {
+		this.spring.register(WebSecurityExpressionHandlerPermissionEvaluatorBeanConfig.class).autowire();
+		TestingAuthenticationToken authentication = new TestingAuthenticationToken("user", "notused");
+		FilterInvocation invocation = new FilterInvocation(new MockHttpServletRequest("GET", ""),
+				new MockHttpServletResponse(), new MockFilterChain());
+
+		AbstractSecurityExpressionHandler handler = this.spring.getContext()
+				.getBean(AbstractSecurityExpressionHandler.class);
+		EvaluationContext evaluationContext = handler.createEvaluationContext(authentication, invocation);
+		Expression expression = handler.getExpressionParser().parseExpression("hasPermission(#study,'DELETE')");
+		boolean granted = expression.getValue(evaluationContext, Boolean.class);
+		assertThat(granted).isTrue();
+	}
+
+	@Test
+	public void loadConfigWhenDefaultWebInvocationPrivilegeEvaluatorThenDefaultIsRegistered() {
+		this.spring.register(WebInvocationPrivilegeEvaluatorDefaultsConfig.class).autowire();
+
+		assertThat(this.spring.getContext().getBean(WebInvocationPrivilegeEvaluator.class))
+				.isInstanceOf(DefaultWebInvocationPrivilegeEvaluator.class);
+	}
+
+	@Test
+	public void loadConfigWhenSecurityFilterChainBeanThenDefaultWebInvocationPrivilegeEvaluatorIsRegistered() {
+		this.spring.register(AuthorizeRequestsFilterChainConfig.class).autowire();
+
+		assertThat(this.spring.getContext().getBean(WebInvocationPrivilegeEvaluator.class))
+				.isInstanceOf(DefaultWebInvocationPrivilegeEvaluator.class);
+	}
+
+	// SEC-2303
+	@Test
+	public void loadConfigWhenDefaultSecurityExpressionHandlerThenBeanResolverSet() throws Exception {
+		this.spring.register(DefaultExpressionHandlerSetsBeanResolverConfig.class).autowire();
+
+		this.mockMvc.perform(get("/")).andExpect(status().isOk());
+		this.mockMvc.perform(post("/")).andExpect(status().isForbidden());
+	}
+
+	// SEC-2461
+	@Test
+	public void loadConfigWhenMultipleWebSecurityConfigurationThenContextLoads() {
+		this.spring.register(ParentConfig.class).autowire();
+
+		this.child.register(ChildConfig.class);
+		this.child.getContext().setParent(this.spring.getContext());
+		this.child.autowire();
+
+		assertThat(this.spring.getContext().getBean("springSecurityFilterChain")).isNotNull();
+		assertThat(this.child.getContext().getBean("springSecurityFilterChain")).isNotNull();
+
+		assertThat(this.spring.getContext().containsBean("springSecurityFilterChain")).isTrue();
+		assertThat(this.child.getContext().containsBean("springSecurityFilterChain")).isTrue();
+	}
+
+	// SEC-2773
+	@Test
+	public void getMethodDelegatingApplicationListenerWhenWebSecurityConfigurationThenIsStatic() {
+		Method method = ClassUtils.getMethod(WebSecurityConfiguration.class, "delegatingApplicationListener", null);
+		assertThat(Modifier.isStatic(method.getModifiers())).isTrue();
+	}
+
+	@Test
+	public void loadConfigWhenBeanProxyingEnabledAndSubclassThenFilterChainsCreated() {
+		this.spring.register(GlobalAuthenticationWebSecurityConfigurerAdaptersConfig.class, SubclassConfig.class)
+				.autowire();
+
+		FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
+		List filterChains = filterChainProxy.getFilterChains();
+
+		assertThat(filterChains).hasSize(4);
+	}
+
+	@Test
+	public void loadConfigWhenBothAdapterAndFilterChainConfiguredThenException() {
+		Throwable thrown = catchThrowable(() -> this.spring.register(AdapterAndFilterChainConfig.class).autowire());
+
+		assertThat(thrown).isInstanceOf(BeanCreationException.class)
+				.hasRootCauseExactlyInstanceOf(IllegalStateException.class)
+				.hasMessageContaining("Found WebSecurityConfigurerAdapter as well as SecurityFilterChain.");
+
+	}
+
 	@EnableWebSecurity
 	@Import(AuthenticationTestConfiguration.class)
 	static class SortedWebSecurityConfigurerAdaptersConfig {
@@ -186,29 +360,6 @@ public class WebSecurityConfigurationTests {
 
 	}
 
-	@Test
-	public void loadConfigWhenSecurityFilterChainsHaveOrderThenFilterChainsOrdered() {
-		this.spring.register(SortedSecurityFilterChainConfig.class).autowire();
-
-		FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
-		List filterChains = filterChainProxy.getFilterChains();
-		assertThat(filterChains).hasSize(4);
-
-		MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
-
-		request.setServletPath("/role1/**");
-		assertThat(filterChains.get(0).matches(request)).isTrue();
-
-		request.setServletPath("/role2/**");
-		assertThat(filterChains.get(1).matches(request)).isTrue();
-
-		request.setServletPath("/role3/**");
-		assertThat(filterChains.get(2).matches(request)).isTrue();
-
-		request.setServletPath("/**");
-		assertThat(filterChains.get(3).matches(request)).isTrue();
-	}
-
 	@EnableWebSecurity
 	@Import(AuthenticationTestConfiguration.class)
 	static class SortedSecurityFilterChainConfig {
@@ -241,16 +392,6 @@ public class WebSecurityConfigurationTests {
 
 	}
 
-	@Test
-	public void loadConfigWhenWebSecurityConfigurersHaveSameOrderThenThrowBeanCreationException() {
-		Throwable thrown = catchThrowable(() -> this.spring.register(DuplicateOrderConfig.class).autowire());
-
-		assertThat(thrown).isInstanceOf(BeanCreationException.class)
-				.hasMessageContaining("@Order on WebSecurityConfigurers must be unique")
-				.hasMessageContaining(DuplicateOrderConfig.WebConfigurer1.class.getName())
-				.hasMessageContaining(DuplicateOrderConfig.WebConfigurer2.class.getName());
-	}
-
 	@EnableWebSecurity
 	@Import(AuthenticationTestConfiguration.class)
 	static class DuplicateOrderConfig {
@@ -287,16 +428,6 @@ public class WebSecurityConfigurationTests {
 
 	}
 
-	@Test
-	public void loadConfigWhenWebInvocationPrivilegeEvaluatorSetThenIsRegistered() {
-		PrivilegeEvaluatorConfigurerAdapterConfig.PRIVILEGE_EVALUATOR = mock(WebInvocationPrivilegeEvaluator.class);
-
-		this.spring.register(PrivilegeEvaluatorConfigurerAdapterConfig.class).autowire();
-
-		assertThat(this.spring.getContext().getBean(WebInvocationPrivilegeEvaluator.class))
-				.isSameAs(PrivilegeEvaluatorConfigurerAdapterConfig.PRIVILEGE_EVALUATOR);
-	}
-
 	@EnableWebSecurity
 	static class PrivilegeEvaluatorConfigurerAdapterConfig extends WebSecurityConfigurerAdapter {
 
@@ -309,18 +440,6 @@ public class WebSecurityConfigurationTests {
 
 	}
 
-	@Test
-	public void loadConfigWhenSecurityExpressionHandlerSetThenIsRegistered() {
-		WebSecurityExpressionHandlerConfig.EXPRESSION_HANDLER = mock(SecurityExpressionHandler.class);
-		when(WebSecurityExpressionHandlerConfig.EXPRESSION_HANDLER.getExpressionParser())
-				.thenReturn(mock(ExpressionParser.class));
-
-		this.spring.register(WebSecurityExpressionHandlerConfig.class).autowire();
-
-		assertThat(this.spring.getContext().getBean(SecurityExpressionHandler.class))
-				.isSameAs(WebSecurityExpressionHandlerConfig.EXPRESSION_HANDLER);
-	}
-
 	@EnableWebSecurity
 	static class WebSecurityExpressionHandlerConfig extends WebSecurityConfigurerAdapter {
 
@@ -343,15 +462,6 @@ public class WebSecurityConfigurationTests {
 
 	}
 
-	@Test
-	public void loadConfigWhenSecurityExpressionHandlerIsNullThenException() {
-		Throwable thrown = catchThrowable(
-				() -> this.spring.register(NullWebSecurityExpressionHandlerConfig.class).autowire());
-
-		assertThat(thrown).isInstanceOf(BeanCreationException.class);
-		assertThat(thrown).hasRootCauseExactlyInstanceOf(IllegalArgumentException.class);
-	}
-
 	@EnableWebSecurity
 	static class NullWebSecurityExpressionHandlerConfig extends WebSecurityConfigurerAdapter {
 
@@ -362,14 +472,6 @@ public class WebSecurityConfigurationTests {
 
 	}
 
-	@Test
-	public void loadConfigWhenDefaultSecurityExpressionHandlerThenDefaultIsRegistered() {
-		this.spring.register(WebSecurityExpressionHandlerDefaultsConfig.class).autowire();
-
-		assertThat(this.spring.getContext().getBean(SecurityExpressionHandler.class))
-				.isInstanceOf(DefaultWebSecurityExpressionHandler.class);
-	}
-
 	@EnableWebSecurity
 	static class WebSecurityExpressionHandlerDefaultsConfig extends WebSecurityConfigurerAdapter {
 
@@ -384,21 +486,6 @@ public class WebSecurityConfigurationTests {
 
 	}
 
-	@Test
-	public void securityExpressionHandlerWhenRoleHierarchyBeanThenRoleHierarchyUsed() {
-		this.spring.register(WebSecurityExpressionHandlerRoleHierarchyBeanConfig.class).autowire();
-		TestingAuthenticationToken authentication = new TestingAuthenticationToken("user", "notused", "ROLE_ADMIN");
-		FilterInvocation invocation = new FilterInvocation(new MockHttpServletRequest("GET", ""),
-				new MockHttpServletResponse(), new MockFilterChain());
-
-		AbstractSecurityExpressionHandler handler = this.spring.getContext()
-				.getBean(AbstractSecurityExpressionHandler.class);
-		EvaluationContext evaluationContext = handler.createEvaluationContext(authentication, invocation);
-		Expression expression = handler.getExpressionParser().parseExpression("hasRole('ROLE_USER')");
-		boolean granted = expression.getValue(evaluationContext, Boolean.class);
-		assertThat(granted).isTrue();
-	}
-
 	@EnableWebSecurity
 	static class WebSecurityExpressionHandlerRoleHierarchyBeanConfig extends WebSecurityConfigurerAdapter {
 
@@ -411,21 +498,6 @@ public class WebSecurityConfigurationTests {
 
 	}
 
-	@Test
-	public void securityExpressionHandlerWhenPermissionEvaluatorBeanThenPermissionEvaluatorUsed() {
-		this.spring.register(WebSecurityExpressionHandlerPermissionEvaluatorBeanConfig.class).autowire();
-		TestingAuthenticationToken authentication = new TestingAuthenticationToken("user", "notused");
-		FilterInvocation invocation = new FilterInvocation(new MockHttpServletRequest("GET", ""),
-				new MockHttpServletResponse(), new MockFilterChain());
-
-		AbstractSecurityExpressionHandler handler = this.spring.getContext()
-				.getBean(AbstractSecurityExpressionHandler.class);
-		EvaluationContext evaluationContext = handler.createEvaluationContext(authentication, invocation);
-		Expression expression = handler.getExpressionParser().parseExpression("hasPermission(#study,'DELETE')");
-		boolean granted = expression.getValue(evaluationContext, Boolean.class);
-		assertThat(granted).isTrue();
-	}
-
 	@EnableWebSecurity
 	static class WebSecurityExpressionHandlerPermissionEvaluatorBeanConfig extends WebSecurityConfigurerAdapter {
 
@@ -449,14 +521,6 @@ public class WebSecurityConfigurationTests {
 
 	}
 
-	@Test
-	public void loadConfigWhenDefaultWebInvocationPrivilegeEvaluatorThenDefaultIsRegistered() {
-		this.spring.register(WebInvocationPrivilegeEvaluatorDefaultsConfig.class).autowire();
-
-		assertThat(this.spring.getContext().getBean(WebInvocationPrivilegeEvaluator.class))
-				.isInstanceOf(DefaultWebInvocationPrivilegeEvaluator.class);
-	}
-
 	@EnableWebSecurity
 	static class WebInvocationPrivilegeEvaluatorDefaultsConfig extends WebSecurityConfigurerAdapter {
 
@@ -471,14 +535,6 @@ public class WebSecurityConfigurationTests {
 
 	}
 
-	@Test
-	public void loadConfigWhenSecurityFilterChainBeanThenDefaultWebInvocationPrivilegeEvaluatorIsRegistered() {
-		this.spring.register(AuthorizeRequestsFilterChainConfig.class).autowire();
-
-		assertThat(this.spring.getContext().getBean(WebInvocationPrivilegeEvaluator.class))
-				.isInstanceOf(DefaultWebInvocationPrivilegeEvaluator.class);
-	}
-
 	@EnableWebSecurity
 	static class AuthorizeRequestsFilterChainConfig {
 
@@ -489,15 +545,6 @@ public class WebSecurityConfigurationTests {
 
 	}
 
-	// SEC-2303
-	@Test
-	public void loadConfigWhenDefaultSecurityExpressionHandlerThenBeanResolverSet() throws Exception {
-		this.spring.register(DefaultExpressionHandlerSetsBeanResolverConfig.class).autowire();
-
-		this.mockMvc.perform(get("/")).andExpect(status().isOk());
-		this.mockMvc.perform(post("/")).andExpect(status().isForbidden());
-	}
-
 	@EnableWebSecurity
 	static class DefaultExpressionHandlerSetsBeanResolverConfig extends WebSecurityConfigurerAdapter {
 
@@ -510,6 +557,11 @@ public class WebSecurityConfigurationTests {
 			// @formatter:on
 		}
 
+		@Bean
+		public MyBean b() {
+			return new MyBean();
+		}
+
 		@RestController
 		public class HomeController {
 
@@ -520,11 +572,6 @@ public class WebSecurityConfigurationTests {
 
 		}
 
-		@Bean
-		public MyBean b() {
-			return new MyBean();
-		}
-
 		static class MyBean {
 
 			public boolean deny() {
@@ -539,25 +586,6 @@ public class WebSecurityConfigurationTests {
 
 	}
 
-	@Rule
-	public SpringTestRule child = new SpringTestRule();
-
-	// SEC-2461
-	@Test
-	public void loadConfigWhenMultipleWebSecurityConfigurationThenContextLoads() {
-		this.spring.register(ParentConfig.class).autowire();
-
-		this.child.register(ChildConfig.class);
-		this.child.getContext().setParent(this.spring.getContext());
-		this.child.autowire();
-
-		assertThat(this.spring.getContext().getBean("springSecurityFilterChain")).isNotNull();
-		assertThat(this.child.getContext().getBean("springSecurityFilterChain")).isNotNull();
-
-		assertThat(this.spring.getContext().containsBean("springSecurityFilterChain")).isTrue();
-		assertThat(this.child.getContext().containsBean("springSecurityFilterChain")).isTrue();
-	}
-
 	@EnableWebSecurity
 	static class ParentConfig extends WebSecurityConfigurerAdapter {
 
@@ -573,24 +601,6 @@ public class WebSecurityConfigurationTests {
 
 	}
 
-	// SEC-2773
-	@Test
-	public void getMethodDelegatingApplicationListenerWhenWebSecurityConfigurationThenIsStatic() {
-		Method method = ClassUtils.getMethod(WebSecurityConfiguration.class, "delegatingApplicationListener", null);
-		assertThat(Modifier.isStatic(method.getModifiers())).isTrue();
-	}
-
-	@Test
-	public void loadConfigWhenBeanProxyingEnabledAndSubclassThenFilterChainsCreated() {
-		this.spring.register(GlobalAuthenticationWebSecurityConfigurerAdaptersConfig.class, SubclassConfig.class)
-				.autowire();
-
-		FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
-		List filterChains = filterChainProxy.getFilterChains();
-
-		assertThat(filterChains).hasSize(4);
-	}
-
 	@Configuration
 	static class SubclassConfig extends WebSecurityConfiguration {
 
@@ -637,20 +647,17 @@ public class WebSecurityConfigurationTests {
 
 	}
 
-	@Test
-	public void loadConfigWhenBothAdapterAndFilterChainConfiguredThenException() {
-		Throwable thrown = catchThrowable(() -> this.spring.register(AdapterAndFilterChainConfig.class).autowire());
-
-		assertThat(thrown).isInstanceOf(BeanCreationException.class)
-				.hasRootCauseExactlyInstanceOf(IllegalStateException.class)
-				.hasMessageContaining("Found WebSecurityConfigurerAdapter as well as SecurityFilterChain.");
-
-	}
-
 	@EnableWebSecurity
 	@Import(AuthenticationTestConfiguration.class)
 	static class AdapterAndFilterChainConfig {
 
+		@Order(2)
+		@Bean
+		SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
+			return http.antMatcher("/filter/**").authorizeRequests(authorize -> authorize.anyRequest().authenticated())
+					.build();
+		}
+
 		@Order(1)
 		@Configuration
 		static class WebConfigurer extends WebSecurityConfigurerAdapter {
@@ -662,13 +669,6 @@ public class WebSecurityConfigurationTests {
 
 		}
 
-		@Order(2)
-		@Bean
-		SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
-			return http.antMatcher("/filter/**").authorizeRequests(authorize -> authorize.anyRequest().authenticated())
-					.build();
-		}
-
 	}
 
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AnonymousConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AnonymousConfigurerTests.java
index 306fd90162..05d7c530bd 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AnonymousConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AnonymousConfigurerTests.java
@@ -55,6 +55,27 @@ public class AnonymousConfigurerTests {
 		this.mockMvc.perform(get("/")).andExpect(content().string("principal"));
 	}
 
+	@Test
+	public void requestWhenAnonymousPrincipalInLambdaThenPrincipalUsed() throws Exception {
+		this.spring.register(AnonymousPrincipalInLambdaConfig.class, PrincipalController.class).autowire();
+
+		this.mockMvc.perform(get("/")).andExpect(content().string("principal"));
+	}
+
+	@Test
+	public void requestWhenAnonymousDisabledInLambdaThenRespondsWithForbidden() throws Exception {
+		this.spring.register(AnonymousDisabledInLambdaConfig.class, PrincipalController.class).autowire();
+
+		this.mockMvc.perform(get("/")).andExpect(status().isForbidden());
+	}
+
+	@Test
+	public void requestWhenAnonymousWithDefaultsInLambdaThenRespondsWithOk() throws Exception {
+		this.spring.register(AnonymousWithDefaultsInLambdaConfig.class, PrincipalController.class).autowire();
+
+		this.mockMvc.perform(get("/")).andExpect(status().isOk());
+	}
+
 	@EnableWebSecurity
 	@EnableWebMvc
 	static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
@@ -73,13 +94,6 @@ public class AnonymousConfigurerTests {
 
 	}
 
-	@Test
-	public void requestWhenAnonymousPrincipalInLambdaThenPrincipalUsed() throws Exception {
-		this.spring.register(AnonymousPrincipalInLambdaConfig.class, PrincipalController.class).autowire();
-
-		this.mockMvc.perform(get("/")).andExpect(content().string("principal"));
-	}
-
 	@EnableWebSecurity
 	@EnableWebMvc
 	static class AnonymousPrincipalInLambdaConfig extends WebSecurityConfigurerAdapter {
@@ -97,13 +111,6 @@ public class AnonymousConfigurerTests {
 
 	}
 
-	@Test
-	public void requestWhenAnonymousDisabledInLambdaThenRespondsWithForbidden() throws Exception {
-		this.spring.register(AnonymousDisabledInLambdaConfig.class, PrincipalController.class).autowire();
-
-		this.mockMvc.perform(get("/")).andExpect(status().isForbidden());
-	}
-
 	@EnableWebSecurity
 	static class AnonymousDisabledInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -130,13 +137,6 @@ public class AnonymousConfigurerTests {
 
 	}
 
-	@Test
-	public void requestWhenAnonymousWithDefaultsInLambdaThenRespondsWithOk() throws Exception {
-		this.spring.register(AnonymousWithDefaultsInLambdaConfig.class, PrincipalController.class).autowire();
-
-		this.mockMvc.perform(get("/")).andExpect(status().isOk());
-	}
-
 	@EnableWebSecurity
 	static class AnonymousWithDefaultsInLambdaConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeRequestsTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeRequestsTests.java
index f2388b2184..fca0698300 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeRequestsTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeRequestsTests.java
@@ -99,29 +99,6 @@ public class AuthorizeRequestsTests {
 		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
 	}
 
-	@EnableWebSecurity
-	@Configuration
-	static class AntMatchersNoPatternsConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.antMatchers(HttpMethod.POST).denyAll();
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-			// @formatter:off
-			auth
-				.inMemoryAuthentication();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void postWhenPostDenyAllInLambdaThenRespondsWithForbidden() throws Exception {
 		loadConfig(AntMatchersNoPatternsInLambdaConfig.class);
@@ -132,31 +109,6 @@ public class AuthorizeRequestsTests {
 		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
 	}
 
-	@EnableWebSecurity
-	@Configuration
-	static class AntMatchersNoPatternsInLambdaConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests(authorizeRequests ->
-					authorizeRequests
-						.antMatchers(HttpMethod.POST).denyAll()
-				);
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-			// @formatter:off
-			auth
-				.inMemoryAuthentication();
-			// @formatter:on
-		}
-
-	}
-
 	// SEC-2256
 	@Test
 	public void antMatchersPathVariables() throws Exception {
@@ -195,30 +147,6 @@ public class AuthorizeRequestsTests {
 		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
 	}
 
-	@EnableWebSecurity
-	@Configuration
-	static class AntPatchersPathVariables extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-				.requestMatchers(new AntPathRequestMatcher("/user/{user}", null, false)).access("#user == 'user'")
-				.anyRequest().denyAll();
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-			// @formatter:off
-			auth
-				.inMemoryAuthentication();
-			// @formatter:on
-		}
-
-	}
-
 	// gh-3786
 	@Test
 	public void antMatchersPathVariablesCaseInsensitiveCamelCaseVariables() throws Exception {
@@ -238,30 +166,6 @@ public class AuthorizeRequestsTests {
 		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
 	}
 
-	@EnableWebSecurity
-	@Configuration
-	static class AntMatchersPathVariablesCamelCaseVariables extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-				.requestMatchers(new AntPathRequestMatcher("/user/{userName}", null, false)).access("#userName == 'user'")
-				.anyRequest().denyAll();
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-			// @formatter:off
-			auth
-				.inMemoryAuthentication();
-			// @formatter:on
-		}
-
-	}
-
 	// gh-3394
 	@Test
 	public void roleHiearchy() throws Exception {
@@ -278,36 +182,6 @@ public class AuthorizeRequestsTests {
 		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
 	}
 
-	@EnableWebSecurity
-	@Configuration
-	static class RoleHiearchyConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.anyRequest().hasRole("ADMIN");
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-			// @formatter:off
-			auth
-				.inMemoryAuthentication();
-			// @formatter:on
-		}
-
-		@Bean
-		public RoleHierarchy roleHiearchy() {
-			RoleHierarchyImpl result = new RoleHierarchyImpl();
-			result.setHierarchy("ROLE_USER > ROLE_ADMIN");
-			return result;
-		}
-
-	}
-
 	@Test
 	public void mvcMatcher() throws Exception {
 		loadConfig(MvcMatcherConfig.class, LegacyMvcMatchingConfig.class);
@@ -332,41 +206,6 @@ public class AuthorizeRequestsTests {
 		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
 	}
 
-	@EnableWebSecurity
-	@Configuration
-	@EnableWebMvc
-	static class MvcMatcherConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.httpBasic().and()
-				.authorizeRequests()
-					.mvcMatchers("/path").denyAll();
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-			// @formatter:off
-			auth
-				.inMemoryAuthentication();
-			// @formatter:on
-		}
-
-		@RestController
-		static class PathController {
-
-			@RequestMapping("/path")
-			public String path() {
-				return "path";
-			}
-
-		}
-
-	}
-
 	@Test
 	public void requestWhenMvcMatcherDenyAllThenRespondsWithUnauthorized() throws Exception {
 		loadConfig(MvcMatcherInLambdaConfig.class, LegacyMvcMatchingConfig.class);
@@ -391,121 +230,6 @@ public class AuthorizeRequestsTests {
 		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
 	}
 
-	@EnableWebSecurity
-	@Configuration
-	@EnableWebMvc
-	static class MvcMatcherInLambdaConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.httpBasic(withDefaults())
-				.authorizeRequests(authorizeRequests ->
-					authorizeRequests
-						.mvcMatchers("/path").denyAll()
-				);
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-			// @formatter:off
-			auth
-				.inMemoryAuthentication();
-			// @formatter:on
-		}
-
-		@RestController
-		static class PathController {
-
-			@RequestMapping("/path")
-			public String path() {
-				return "path";
-			}
-
-		}
-
-	}
-
-	@Test
-	public void mvcMatcherServletPath() throws Exception {
-		loadConfig(MvcMatcherServletPathConfig.class, LegacyMvcMatchingConfig.class);
-
-		this.request.setServletPath("/spring");
-		this.request.setRequestURI("/spring/path");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
-
-		setup();
-
-		this.request.setServletPath("/spring");
-		this.request.setRequestURI("/spring/path.html");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
-
-		setup();
-
-		this.request.setServletPath("/spring");
-		this.request.setRequestURI("/spring/path/");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
-
-		setup();
-
-		this.request.setServletPath("/foo");
-		this.request.setRequestURI("/foo/path");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
-
-		setup();
-
-		this.request.setServletPath("/");
-		this.request.setRequestURI("/path");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
-	}
-
-	@EnableWebSecurity
-	@Configuration
-	@EnableWebMvc
-	static class MvcMatcherServletPathConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.httpBasic().and()
-				.authorizeRequests()
-					.mvcMatchers("/path").servletPath("/spring").denyAll();
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-			// @formatter:off
-			auth
-				.inMemoryAuthentication();
-			// @formatter:on
-		}
-
-		@RestController
-		static class PathController {
-
-			@RequestMapping("/path")
-			public String path() {
-				return "path";
-			}
-
-		}
-
-	}
-
 	@Test
 	public void requestWhenMvcMatcherServletPathDenyAllThenMatchesOnServletPath() throws Exception {
 		loadConfig(MvcMatcherServletPathInLambdaConfig.class, LegacyMvcMatchingConfig.class);
@@ -549,6 +273,327 @@ public class AuthorizeRequestsTests {
 		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
 	}
 
+	@Test
+	public void mvcMatcherPathVariables() throws Exception {
+		loadConfig(MvcMatcherPathVariablesConfig.class);
+
+		this.request.setRequestURI("/user/user");
+
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
+
+		this.setup();
+		this.request.setRequestURI("/user/deny");
+
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
+	}
+
+	@Test
+	public void requestWhenMvcMatcherPathVariablesThenMatchesOnPathVariables() throws Exception {
+		loadConfig(MvcMatcherPathVariablesInLambdaConfig.class);
+
+		this.request.setRequestURI("/user/user");
+
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
+
+		this.setup();
+		this.request.setRequestURI("/user/deny");
+
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
+	}
+
+	@Test
+	public void mvcMatcherServletPath() throws Exception {
+		loadConfig(MvcMatcherServletPathConfig.class, LegacyMvcMatchingConfig.class);
+
+		this.request.setServletPath("/spring");
+		this.request.setRequestURI("/spring/path");
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
+
+		setup();
+
+		this.request.setServletPath("/spring");
+		this.request.setRequestURI("/spring/path.html");
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
+
+		setup();
+
+		this.request.setServletPath("/spring");
+		this.request.setRequestURI("/spring/path/");
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
+
+		setup();
+
+		this.request.setServletPath("/foo");
+		this.request.setRequestURI("/foo/path");
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
+
+		setup();
+
+		this.request.setServletPath("/");
+		this.request.setRequestURI("/path");
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
+	}
+
+	public void loadConfig(Class... configs) {
+		this.context = new AnnotationConfigWebApplicationContext();
+		this.context.register(configs);
+		this.context.setServletContext(this.servletContext);
+		this.context.refresh();
+
+		this.context.getAutowireCapableBeanFactory().autowireBean(this);
+	}
+
+	@EnableWebSecurity
+	@Configuration
+	static class AntMatchersNoPatternsConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.antMatchers(HttpMethod.POST).denyAll();
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	@Configuration
+	static class AntMatchersNoPatternsInLambdaConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests(authorizeRequests ->
+					authorizeRequests
+						.antMatchers(HttpMethod.POST).denyAll()
+				);
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	@Configuration
+	static class AntPatchersPathVariables extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+				.requestMatchers(new AntPathRequestMatcher("/user/{user}", null, false)).access("#user == 'user'")
+				.anyRequest().denyAll();
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	@Configuration
+	static class AntMatchersPathVariablesCamelCaseVariables extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+				.requestMatchers(new AntPathRequestMatcher("/user/{userName}", null, false)).access("#userName == 'user'")
+				.anyRequest().denyAll();
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	@Configuration
+	static class RoleHiearchyConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("ADMIN");
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication();
+			// @formatter:on
+		}
+
+		@Bean
+		public RoleHierarchy roleHiearchy() {
+			RoleHierarchyImpl result = new RoleHierarchyImpl();
+			result.setHierarchy("ROLE_USER > ROLE_ADMIN");
+			return result;
+		}
+
+	}
+
+	@EnableWebSecurity
+	@Configuration
+	@EnableWebMvc
+	static class MvcMatcherConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.httpBasic().and()
+				.authorizeRequests()
+					.mvcMatchers("/path").denyAll();
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication();
+			// @formatter:on
+		}
+
+		@RestController
+		static class PathController {
+
+			@RequestMapping("/path")
+			public String path() {
+				return "path";
+			}
+
+		}
+
+	}
+
+	@EnableWebSecurity
+	@Configuration
+	@EnableWebMvc
+	static class MvcMatcherInLambdaConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.httpBasic(withDefaults())
+				.authorizeRequests(authorizeRequests ->
+					authorizeRequests
+						.mvcMatchers("/path").denyAll()
+				);
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication();
+			// @formatter:on
+		}
+
+		@RestController
+		static class PathController {
+
+			@RequestMapping("/path")
+			public String path() {
+				return "path";
+			}
+
+		}
+
+	}
+
+	@EnableWebSecurity
+	@Configuration
+	@EnableWebMvc
+	static class MvcMatcherServletPathConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.httpBasic().and()
+				.authorizeRequests()
+					.mvcMatchers("/path").servletPath("/spring").denyAll();
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication();
+			// @formatter:on
+		}
+
+		@RestController
+		static class PathController {
+
+			@RequestMapping("/path")
+			public String path() {
+				return "path";
+			}
+
+		}
+
+	}
+
 	@EnableWebSecurity
 	@Configuration
 	@EnableWebMvc
@@ -586,24 +631,6 @@ public class AuthorizeRequestsTests {
 
 	}
 
-	@Test
-	public void mvcMatcherPathVariables() throws Exception {
-		loadConfig(MvcMatcherPathVariablesConfig.class);
-
-		this.request.setRequestURI("/user/user");
-
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
-
-		this.setup();
-		this.request.setRequestURI("/user/deny");
-
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
-	}
-
 	@EnableWebSecurity
 	@Configuration
 	@EnableWebMvc
@@ -639,24 +666,6 @@ public class AuthorizeRequestsTests {
 
 	}
 
-	@Test
-	public void requestWhenMvcMatcherPathVariablesThenMatchesOnPathVariables() throws Exception {
-		loadConfig(MvcMatcherPathVariablesInLambdaConfig.class);
-
-		this.request.setRequestURI("/user/user");
-
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
-
-		this.setup();
-		this.request.setRequestURI("/user/deny");
-
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
-	}
-
 	@EnableWebSecurity
 	@Configuration
 	@EnableWebMvc
@@ -739,13 +748,4 @@ public class AuthorizeRequestsTests {
 
 	}
 
-	public void loadConfig(Class... configs) {
-		this.context = new AnnotationConfigWebApplicationContext();
-		this.context.register(configs);
-		this.context.setServletContext(this.servletContext);
-		this.context.refresh();
-
-		this.context.getAutowireCapableBeanFactory().autowireBean(this);
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurerTests.java
index d448f8e3cd..c385a6aacb 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurerTests.java
@@ -84,6 +84,20 @@ public class ChannelSecurityConfigurerTests {
 		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(ChannelProcessingFilter.class));
 	}
 
+	@Test
+	public void requiresChannelWhenInvokesTwiceThenUsesOriginalRequiresSecure() throws Exception {
+		this.spring.register(DuplicateInvocationsDoesNotOverrideConfig.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(redirectedUrl("https://localhost/"));
+	}
+
+	@Test
+	public void requestWhenRequiresChannelConfiguredInLambdaThenRedirectsToHttps() throws Exception {
+		this.spring.register(RequiresChannelInLambdaConfig.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(redirectedUrl("https://localhost/"));
+	}
+
 	@EnableWebSecurity
 	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
 
@@ -114,13 +128,6 @@ public class ChannelSecurityConfigurerTests {
 
 	}
 
-	@Test
-	public void requiresChannelWhenInvokesTwiceThenUsesOriginalRequiresSecure() throws Exception {
-		this.spring.register(DuplicateInvocationsDoesNotOverrideConfig.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(redirectedUrl("https://localhost/"));
-	}
-
 	@EnableWebSecurity
 	static class DuplicateInvocationsDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
 
@@ -137,13 +144,6 @@ public class ChannelSecurityConfigurerTests {
 
 	}
 
-	@Test
-	public void requestWhenRequiresChannelConfiguredInLambdaThenRedirectsToHttps() throws Exception {
-		this.spring.register(RequiresChannelInLambdaConfig.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(redirectedUrl("https://localhost/"));
-	}
-
 	@EnableWebSecurity
 	static class RequiresChannelInLambdaConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CorsConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CorsConfigurerTests.java
index 0311831080..c883479ace 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CorsConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CorsConfigurerTests.java
@@ -70,22 +70,6 @@ public class CorsConfigurerTests {
 						"Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext");
 	}
 
-	@EnableWebSecurity
-	static class DefaultCorsConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.anyRequest().authenticated()
-					.and()
-				.cors();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenCrossOriginAnnotationThenRespondsWithCorsHeaders() throws Exception {
 		this.spring.register(MvcCorsConfig.class).autowire();
@@ -106,6 +90,124 @@ public class CorsConfigurerTests {
 				.andExpect(header().exists("X-Content-Type-Options"));
 	}
 
+	@Test
+	public void getWhenDefaultsInLambdaAndCrossOriginAnnotationThenRespondsWithCorsHeaders() throws Exception {
+		this.spring.register(MvcCorsInLambdaConfig.class).autowire();
+
+		this.mvc.perform(get("/").header(HttpHeaders.ORIGIN, "https://example.com"))
+				.andExpect(header().exists("Access-Control-Allow-Origin"))
+				.andExpect(header().exists("X-Content-Type-Options"));
+	}
+
+	@Test
+	public void optionsWhenDefaultsInLambdaAndCrossOriginAnnotationThenRespondsWithCorsHeaders() throws Exception {
+		this.spring.register(MvcCorsInLambdaConfig.class).autowire();
+
+		this.mvc.perform(options("/")
+				.header(org.springframework.http.HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpMethod.POST.name())
+				.header(HttpHeaders.ORIGIN, "https://example.com")).andExpect(status().isOk())
+				.andExpect(header().exists("Access-Control-Allow-Origin"))
+				.andExpect(header().exists("X-Content-Type-Options"));
+	}
+
+	@Test
+	public void getWhenCorsConfigurationSourceBeanThenRespondsWithCorsHeaders() throws Exception {
+		this.spring.register(ConfigSourceConfig.class).autowire();
+
+		this.mvc.perform(get("/").header(HttpHeaders.ORIGIN, "https://example.com"))
+				.andExpect(header().exists("Access-Control-Allow-Origin"))
+				.andExpect(header().exists("X-Content-Type-Options"));
+	}
+
+	@Test
+	public void optionsWhenCorsConfigurationSourceBeanThenRespondsWithCorsHeaders() throws Exception {
+		this.spring.register(ConfigSourceConfig.class).autowire();
+
+		this.mvc.perform(options("/")
+				.header(org.springframework.http.HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpMethod.POST.name())
+				.header(HttpHeaders.ORIGIN, "https://example.com")).andExpect(status().isOk())
+				.andExpect(header().exists("Access-Control-Allow-Origin"))
+				.andExpect(header().exists("X-Content-Type-Options"));
+	}
+
+	@Test
+	public void getWhenMvcCorsInLambdaConfigAndCorsConfigurationSourceBeanThenRespondsWithCorsHeaders()
+			throws Exception {
+		this.spring.register(ConfigSourceInLambdaConfig.class).autowire();
+
+		this.mvc.perform(get("/").header(HttpHeaders.ORIGIN, "https://example.com"))
+				.andExpect(header().exists("Access-Control-Allow-Origin"))
+				.andExpect(header().exists("X-Content-Type-Options"));
+	}
+
+	@Test
+	public void optionsWhenMvcCorsInLambdaConfigAndCorsConfigurationSourceBeanThenRespondsWithCorsHeaders()
+			throws Exception {
+		this.spring.register(ConfigSourceInLambdaConfig.class).autowire();
+
+		this.mvc.perform(options("/")
+				.header(org.springframework.http.HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpMethod.POST.name())
+				.header(HttpHeaders.ORIGIN, "https://example.com")).andExpect(status().isOk())
+				.andExpect(header().exists("Access-Control-Allow-Origin"))
+				.andExpect(header().exists("X-Content-Type-Options"));
+	}
+
+	@Test
+	public void getWhenCorsFilterBeanThenRespondsWithCorsHeaders() throws Exception {
+		this.spring.register(CorsFilterConfig.class).autowire();
+
+		this.mvc.perform(get("/").header(HttpHeaders.ORIGIN, "https://example.com"))
+				.andExpect(header().exists("Access-Control-Allow-Origin"))
+				.andExpect(header().exists("X-Content-Type-Options"));
+	}
+
+	@Test
+	public void optionsWhenCorsFilterBeanThenRespondsWithCorsHeaders() throws Exception {
+		this.spring.register(CorsFilterConfig.class).autowire();
+
+		this.mvc.perform(options("/")
+				.header(org.springframework.http.HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpMethod.POST.name())
+				.header(HttpHeaders.ORIGIN, "https://example.com")).andExpect(status().isOk())
+				.andExpect(header().exists("Access-Control-Allow-Origin"))
+				.andExpect(header().exists("X-Content-Type-Options"));
+	}
+
+	@Test
+	public void getWhenConfigSourceInLambdaConfigAndCorsFilterBeanThenRespondsWithCorsHeaders() throws Exception {
+		this.spring.register(CorsFilterInLambdaConfig.class).autowire();
+
+		this.mvc.perform(get("/").header(HttpHeaders.ORIGIN, "https://example.com"))
+				.andExpect(header().exists("Access-Control-Allow-Origin"))
+				.andExpect(header().exists("X-Content-Type-Options"));
+	}
+
+	@Test
+	public void optionsWhenConfigSourceInLambdaConfigAndCorsFilterBeanThenRespondsWithCorsHeaders() throws Exception {
+		this.spring.register(CorsFilterInLambdaConfig.class).autowire();
+
+		this.mvc.perform(options("/")
+				.header(org.springframework.http.HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpMethod.POST.name())
+				.header(HttpHeaders.ORIGIN, "https://example.com")).andExpect(status().isOk())
+				.andExpect(header().exists("Access-Control-Allow-Origin"))
+				.andExpect(header().exists("X-Content-Type-Options"));
+	}
+
+	@EnableWebSecurity
+	static class DefaultCorsConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().authenticated()
+					.and()
+				.cors();
+			// @formatter:on
+		}
+
+	}
+
 	@EnableWebMvc
 	@EnableWebSecurity
 	static class MvcCorsConfig extends WebSecurityConfigurerAdapter {
@@ -134,26 +236,6 @@ public class CorsConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenDefaultsInLambdaAndCrossOriginAnnotationThenRespondsWithCorsHeaders() throws Exception {
-		this.spring.register(MvcCorsInLambdaConfig.class).autowire();
-
-		this.mvc.perform(get("/").header(HttpHeaders.ORIGIN, "https://example.com"))
-				.andExpect(header().exists("Access-Control-Allow-Origin"))
-				.andExpect(header().exists("X-Content-Type-Options"));
-	}
-
-	@Test
-	public void optionsWhenDefaultsInLambdaAndCrossOriginAnnotationThenRespondsWithCorsHeaders() throws Exception {
-		this.spring.register(MvcCorsInLambdaConfig.class).autowire();
-
-		this.mvc.perform(options("/")
-				.header(org.springframework.http.HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpMethod.POST.name())
-				.header(HttpHeaders.ORIGIN, "https://example.com")).andExpect(status().isOk())
-				.andExpect(header().exists("Access-Control-Allow-Origin"))
-				.andExpect(header().exists("X-Content-Type-Options"));
-	}
-
 	@EnableWebMvc
 	@EnableWebSecurity
 	static class MvcCorsInLambdaConfig extends WebSecurityConfigurerAdapter {
@@ -183,26 +265,6 @@ public class CorsConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenCorsConfigurationSourceBeanThenRespondsWithCorsHeaders() throws Exception {
-		this.spring.register(ConfigSourceConfig.class).autowire();
-
-		this.mvc.perform(get("/").header(HttpHeaders.ORIGIN, "https://example.com"))
-				.andExpect(header().exists("Access-Control-Allow-Origin"))
-				.andExpect(header().exists("X-Content-Type-Options"));
-	}
-
-	@Test
-	public void optionsWhenCorsConfigurationSourceBeanThenRespondsWithCorsHeaders() throws Exception {
-		this.spring.register(ConfigSourceConfig.class).autowire();
-
-		this.mvc.perform(options("/")
-				.header(org.springframework.http.HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpMethod.POST.name())
-				.header(HttpHeaders.ORIGIN, "https://example.com")).andExpect(status().isOk())
-				.andExpect(header().exists("Access-Control-Allow-Origin"))
-				.andExpect(header().exists("X-Content-Type-Options"));
-	}
-
 	@EnableWebSecurity
 	static class ConfigSourceConfig extends WebSecurityConfigurerAdapter {
 
@@ -229,28 +291,6 @@ public class CorsConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenMvcCorsInLambdaConfigAndCorsConfigurationSourceBeanThenRespondsWithCorsHeaders()
-			throws Exception {
-		this.spring.register(ConfigSourceInLambdaConfig.class).autowire();
-
-		this.mvc.perform(get("/").header(HttpHeaders.ORIGIN, "https://example.com"))
-				.andExpect(header().exists("Access-Control-Allow-Origin"))
-				.andExpect(header().exists("X-Content-Type-Options"));
-	}
-
-	@Test
-	public void optionsWhenMvcCorsInLambdaConfigAndCorsConfigurationSourceBeanThenRespondsWithCorsHeaders()
-			throws Exception {
-		this.spring.register(ConfigSourceInLambdaConfig.class).autowire();
-
-		this.mvc.perform(options("/")
-				.header(org.springframework.http.HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpMethod.POST.name())
-				.header(HttpHeaders.ORIGIN, "https://example.com")).andExpect(status().isOk())
-				.andExpect(header().exists("Access-Control-Allow-Origin"))
-				.andExpect(header().exists("X-Content-Type-Options"));
-	}
-
 	@EnableWebSecurity
 	static class ConfigSourceInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -278,26 +318,6 @@ public class CorsConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenCorsFilterBeanThenRespondsWithCorsHeaders() throws Exception {
-		this.spring.register(CorsFilterConfig.class).autowire();
-
-		this.mvc.perform(get("/").header(HttpHeaders.ORIGIN, "https://example.com"))
-				.andExpect(header().exists("Access-Control-Allow-Origin"))
-				.andExpect(header().exists("X-Content-Type-Options"));
-	}
-
-	@Test
-	public void optionsWhenCorsFilterBeanThenRespondsWithCorsHeaders() throws Exception {
-		this.spring.register(CorsFilterConfig.class).autowire();
-
-		this.mvc.perform(options("/")
-				.header(org.springframework.http.HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpMethod.POST.name())
-				.header(HttpHeaders.ORIGIN, "https://example.com")).andExpect(status().isOk())
-				.andExpect(header().exists("Access-Control-Allow-Origin"))
-				.andExpect(header().exists("X-Content-Type-Options"));
-	}
-
 	@EnableWebSecurity
 	static class CorsFilterConfig extends WebSecurityConfigurerAdapter {
 
@@ -324,26 +344,6 @@ public class CorsConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenConfigSourceInLambdaConfigAndCorsFilterBeanThenRespondsWithCorsHeaders() throws Exception {
-		this.spring.register(CorsFilterInLambdaConfig.class).autowire();
-
-		this.mvc.perform(get("/").header(HttpHeaders.ORIGIN, "https://example.com"))
-				.andExpect(header().exists("Access-Control-Allow-Origin"))
-				.andExpect(header().exists("X-Content-Type-Options"));
-	}
-
-	@Test
-	public void optionsWhenConfigSourceInLambdaConfigAndCorsFilterBeanThenRespondsWithCorsHeaders() throws Exception {
-		this.spring.register(CorsFilterInLambdaConfig.class).autowire();
-
-		this.mvc.perform(options("/")
-				.header(org.springframework.http.HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpMethod.POST.name())
-				.header(HttpHeaders.ORIGIN, "https://example.com")).andExpect(status().isOk())
-				.andExpect(header().exists("Access-Control-Allow-Origin"))
-				.andExpect(header().exists("X-Content-Type-Options"));
-	}
-
 	@EnableWebSecurity
 	static class CorsFilterInLambdaConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerIgnoringRequestMatchersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerIgnoringRequestMatchersTests.java
index 9825c8ea99..bba69c31a7 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerIgnoringRequestMatchersTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerIgnoringRequestMatchersTests.java
@@ -56,6 +56,40 @@ public class CsrfConfigurerIgnoringRequestMatchersTests {
 		this.mvc.perform(post("/path")).andExpect(status().isOk());
 	}
 
+	@Test
+	public void requestWhenIgnoringRequestMatchersInLambdaThenAugmentedByConfiguredRequestMatcher() throws Exception {
+		this.spring.register(IgnoringRequestInLambdaMatchers.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/path")).andExpect(status().isForbidden());
+
+		this.mvc.perform(post("/path")).andExpect(status().isOk());
+	}
+
+	@Test
+	public void requestWhenIgnoringRequestMatcherThenUnionsWithConfiguredIgnoringAntMatchers() throws Exception {
+
+		this.spring.register(IgnoringPathsAndMatchers.class, BasicController.class).autowire();
+
+		this.mvc.perform(put("/csrf")).andExpect(status().isForbidden());
+
+		this.mvc.perform(post("/csrf")).andExpect(status().isOk());
+
+		this.mvc.perform(put("/no-csrf")).andExpect(status().isOk());
+	}
+
+	@Test
+	public void requestWhenIgnoringRequestMatcherInLambdaThenUnionsWithConfiguredIgnoringAntMatchers()
+			throws Exception {
+
+		this.spring.register(IgnoringPathsAndMatchersInLambdaConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(put("/csrf")).andExpect(status().isForbidden());
+
+		this.mvc.perform(post("/csrf")).andExpect(status().isOk());
+
+		this.mvc.perform(put("/no-csrf")).andExpect(status().isOk());
+	}
+
 	@EnableWebSecurity
 	static class IgnoringRequestMatchers extends WebSecurityConfigurerAdapter {
 
@@ -73,15 +107,6 @@ public class CsrfConfigurerIgnoringRequestMatchersTests {
 
 	}
 
-	@Test
-	public void requestWhenIgnoringRequestMatchersInLambdaThenAugmentedByConfiguredRequestMatcher() throws Exception {
-		this.spring.register(IgnoringRequestInLambdaMatchers.class, BasicController.class).autowire();
-
-		this.mvc.perform(get("/path")).andExpect(status().isForbidden());
-
-		this.mvc.perform(post("/path")).andExpect(status().isOk());
-	}
-
 	@EnableWebSecurity
 	static class IgnoringRequestInLambdaMatchers extends WebSecurityConfigurerAdapter {
 
@@ -101,18 +126,6 @@ public class CsrfConfigurerIgnoringRequestMatchersTests {
 
 	}
 
-	@Test
-	public void requestWhenIgnoringRequestMatcherThenUnionsWithConfiguredIgnoringAntMatchers() throws Exception {
-
-		this.spring.register(IgnoringPathsAndMatchers.class, BasicController.class).autowire();
-
-		this.mvc.perform(put("/csrf")).andExpect(status().isForbidden());
-
-		this.mvc.perform(post("/csrf")).andExpect(status().isOk());
-
-		this.mvc.perform(put("/no-csrf")).andExpect(status().isOk());
-	}
-
 	@EnableWebSecurity
 	static class IgnoringPathsAndMatchers extends WebSecurityConfigurerAdapter {
 
@@ -130,19 +143,6 @@ public class CsrfConfigurerIgnoringRequestMatchersTests {
 
 	}
 
-	@Test
-	public void requestWhenIgnoringRequestMatcherInLambdaThenUnionsWithConfiguredIgnoringAntMatchers()
-			throws Exception {
-
-		this.spring.register(IgnoringPathsAndMatchersInLambdaConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(put("/csrf")).andExpect(status().isForbidden());
-
-		this.mvc.perform(post("/csrf")).andExpect(status().isOk());
-
-		this.mvc.perform(put("/no-csrf")).andExpect(status().isOk());
-	}
-
 	@EnableWebSecurity
 	static class IgnoringPathsAndMatchersInLambdaConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerNoWebMvcTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerNoWebMvcTests.java
index 74e98391d9..1a5a64cfbb 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerNoWebMvcTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerNoWebMvcTests.java
@@ -68,6 +68,13 @@ public class CsrfConfigurerNoWebMvcTests {
 				.isNotEqualTo(CsrfRequestDataValueProcessor.class);
 	}
 
+	private void loadContext(Class configs) {
+		AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
+		annotationConfigApplicationContext.register(configs);
+		annotationConfigApplicationContext.refresh();
+		this.context = annotationConfigApplicationContext;
+	}
+
 	@EnableWebSecurity
 	static class EnableWebConfig extends WebSecurityConfigurerAdapter {
 
@@ -97,11 +104,4 @@ public class CsrfConfigurerNoWebMvcTests {
 
 	}
 
-	private void loadContext(Class configs) {
-		AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
-		annotationConfigApplicationContext.register(configs);
-		annotationConfigApplicationContext.refresh();
-		this.context = annotationConfigApplicationContext;
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerTests.java
index 95f4585d44..4aa9547949 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerTests.java
@@ -179,27 +179,6 @@ public class CsrfConfigurerTests {
 		assertThat(this.spring.getContext().getBean(RequestDataValueProcessor.class)).isNotNull();
 	}
 
-	@Configuration
-	static class AllowHttpMethodsFirewallConfig {
-
-		@Bean
-		StrictHttpFirewall strictHttpFirewall() {
-			StrictHttpFirewall result = new StrictHttpFirewall();
-			result.setUnsafeAllowAnyHttpMethod(true);
-			return result;
-		}
-
-	}
-
-	@EnableWebSecurity
-	static class CsrfAppliedDefaultConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) {
-		}
-
-	}
-
 	@Test
 	public void postWhenCsrfDisabledThenRespondsWithOk() throws Exception {
 		this.spring.register(DisableCsrfConfig.class, BasicController.class).autowire();
@@ -207,20 +186,6 @@ public class CsrfConfigurerTests {
 		this.mvc.perform(post("/")).andExpect(status().isOk());
 	}
 
-	@EnableWebSecurity
-	static class DisableCsrfConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.csrf()
-					.disable();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void postWhenCsrfDisabledInLambdaThenRespondsWithOk() throws Exception {
 		this.spring.register(DisableCsrfInLambdaConfig.class, BasicController.class).autowire();
@@ -228,19 +193,6 @@ public class CsrfConfigurerTests {
 		this.mvc.perform(post("/")).andExpect(status().isOk());
 	}
 
-	@EnableWebSecurity
-	static class DisableCsrfInLambdaConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.csrf(AbstractHttpConfigurer::disable);
-			// @formatter:on
-		}
-
-	}
-
 	// SEC-2498
 	@Test
 	public void loginWhenCsrfDisabledThenRedirectsToPreviousPostRequest() throws Exception {
@@ -253,34 +205,6 @@ public class CsrfConfigurerTests {
 				.andExpect(redirectedUrl("http://localhost/to-save"));
 	}
 
-	@EnableWebSecurity
-	static class DisableCsrfEnablesRequestCacheConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.anyRequest().authenticated()
-					.and()
-				.formLogin()
-					.and()
-				.csrf()
-					.disable();
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-			// @formatter:off
-			auth
-				.inMemoryAuthentication()
-				.withUser(PasswordEncodedUser.user());
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void loginWhenCsrfEnabledThenDoesNotRedirectToPreviousPostRequest() throws Exception {
 		CsrfDisablesPostRequestFromRequestCacheConfig.REPO = mock(CsrfTokenRepository.class);
@@ -315,36 +239,6 @@ public class CsrfConfigurerTests {
 				.loadToken(any(HttpServletRequest.class));
 	}
 
-	@EnableWebSecurity
-	static class CsrfDisablesPostRequestFromRequestCacheConfig extends WebSecurityConfigurerAdapter {
-
-		static CsrfTokenRepository REPO;
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.anyRequest().authenticated()
-					.and()
-				.formLogin()
-					.and()
-				.csrf()
-					.csrfTokenRepository(REPO);
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-			// @formatter:off
-			auth
-				.inMemoryAuthentication()
-					.withUser(PasswordEncodedUser.user());
-			// @formatter:on
-		}
-
-	}
-
 	// SEC-2422
 	@Test
 	public void postWhenCsrfEnabledAndSessionIsExpiredThenRespondsWithForbidden() throws Exception {
@@ -357,22 +251,6 @@ public class CsrfConfigurerTests {
 				.andExpect(status().isForbidden());
 	}
 
-	@EnableWebSecurity
-	static class InvalidSessionUrlConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.csrf()
-					.and()
-				.sessionManagement()
-					.invalidSessionUrl("/error/sessionError");
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void requireCsrfProtectionMatcherWhenRequestDoesNotMatchThenRespondsWithOk() throws Exception {
 		this.spring.register(RequireCsrfProtectionMatcherConfig.class, BasicController.class).autowire();
@@ -390,22 +268,6 @@ public class CsrfConfigurerTests {
 		this.mvc.perform(get("/")).andExpect(status().isForbidden());
 	}
 
-	@EnableWebSecurity
-	static class RequireCsrfProtectionMatcherConfig extends WebSecurityConfigurerAdapter {
-
-		static RequestMatcher MATCHER;
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.csrf()
-					.requireCsrfProtectionMatcher(MATCHER);
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void requireCsrfProtectionMatcherInLambdaWhenRequestDoesNotMatchThenRespondsWithOk() throws Exception {
 		RequireCsrfProtectionMatcherInLambdaConfig.MATCHER = mock(RequestMatcher.class);
@@ -424,21 +286,6 @@ public class CsrfConfigurerTests {
 		this.mvc.perform(get("/")).andExpect(status().isForbidden());
 	}
 
-	@EnableWebSecurity
-	static class RequireCsrfProtectionMatcherInLambdaConfig extends WebSecurityConfigurerAdapter {
-
-		static RequestMatcher MATCHER;
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.csrf(csrf -> csrf.requireCsrfProtectionMatcher(MATCHER));
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenCustomCsrfTokenRepositoryThenRepositoryIsUsed() throws Exception {
 		CsrfTokenRepositoryConfig.REPO = mock(CsrfTokenRepository.class);
@@ -476,6 +323,247 @@ public class CsrfConfigurerTests {
 				any(HttpServletResponse.class));
 	}
 
+	@Test
+	public void getWhenCustomCsrfTokenRepositoryInLambdaThenRepositoryIsUsed() throws Exception {
+		CsrfTokenRepositoryInLambdaConfig.REPO = mock(CsrfTokenRepository.class);
+		when(CsrfTokenRepositoryInLambdaConfig.REPO.loadToken(any()))
+				.thenReturn(new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "token"));
+		this.spring.register(CsrfTokenRepositoryInLambdaConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(status().isOk());
+		verify(CsrfTokenRepositoryInLambdaConfig.REPO).loadToken(any(HttpServletRequest.class));
+	}
+
+	@Test
+	public void getWhenCustomAccessDeniedHandlerThenHandlerIsUsed() throws Exception {
+		AccessDeniedHandlerConfig.DENIED_HANDLER = mock(AccessDeniedHandler.class);
+		this.spring.register(AccessDeniedHandlerConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(post("/")).andExpect(status().isOk());
+
+		verify(AccessDeniedHandlerConfig.DENIED_HANDLER).handle(any(HttpServletRequest.class),
+				any(HttpServletResponse.class), any());
+	}
+
+	@Test
+	public void loginWhenNoCsrfTokenThenRespondsWithForbidden() throws Exception {
+		this.spring.register(FormLoginConfig.class).autowire();
+
+		this.mvc.perform(post("/login").param("username", "user").param("password", "password"))
+				.andExpect(status().isForbidden()).andExpect(unauthenticated());
+	}
+
+	@Test
+	public void logoutWhenNoCsrfTokenThenRespondsWithForbidden() throws Exception {
+		this.spring.register(FormLoginConfig.class).autowire();
+
+		this.mvc.perform(post("/logout").with(user("username"))).andExpect(status().isForbidden())
+				.andExpect(authenticated());
+	}
+
+	// SEC-2543
+	@Test
+	public void logoutWhenCsrfEnabledAndGetRequestThenDoesNotLogout() throws Exception {
+		this.spring.register(FormLoginConfig.class).autowire();
+
+		this.mvc.perform(get("/logout").with(user("username"))).andExpect(authenticated());
+	}
+
+	@Test
+	public void logoutWhenGetRequestAndGetEnabledForLogoutThenLogsOut() throws Exception {
+		this.spring.register(LogoutAllowsGetConfig.class).autowire();
+
+		this.mvc.perform(get("/logout").with(user("username"))).andExpect(unauthenticated());
+	}
+
+	// SEC-2749
+	@Test
+	public void configureWhenRequireCsrfProtectionMatcherNullThenException() {
+		assertThatThrownBy(() -> this.spring.register(NullRequireCsrfProtectionMatcherConfig.class).autowire())
+				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
+	}
+
+	@Test
+	public void getWhenDefaultCsrfTokenRepositoryThenDoesNotCreateSession() throws Exception {
+		this.spring.register(DefaultDoesNotCreateSession.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/")).andReturn();
+
+		assertThat(mvcResult.getRequest().getSession(false)).isNull();
+	}
+
+	@Test
+	public void getWhenNullAuthenticationStrategyThenException() {
+		assertThatThrownBy(() -> this.spring.register(NullAuthenticationStrategy.class).autowire())
+				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
+	}
+
+	@Test
+	public void csrfAuthenticationStrategyConfiguredThenStrategyUsed() throws Exception {
+		CsrfAuthenticationStrategyConfig.STRATEGY = mock(SessionAuthenticationStrategy.class);
+
+		this.spring.register(CsrfAuthenticationStrategyConfig.class).autowire();
+
+		this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"))
+				.andExpect(redirectedUrl("/"));
+
+		verify(CsrfAuthenticationStrategyConfig.STRATEGY, atLeastOnce()).onAuthentication(any(Authentication.class),
+				any(HttpServletRequest.class), any(HttpServletResponse.class));
+	}
+
+	@Configuration
+	static class AllowHttpMethodsFirewallConfig {
+
+		@Bean
+		StrictHttpFirewall strictHttpFirewall() {
+			StrictHttpFirewall result = new StrictHttpFirewall();
+			result.setUnsafeAllowAnyHttpMethod(true);
+			return result;
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class CsrfAppliedDefaultConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) {
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class DisableCsrfConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.csrf()
+					.disable();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class DisableCsrfInLambdaConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.csrf(AbstractHttpConfigurer::disable);
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class DisableCsrfEnablesRequestCacheConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().authenticated()
+					.and()
+				.formLogin()
+					.and()
+				.csrf()
+					.disable();
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication()
+				.withUser(PasswordEncodedUser.user());
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class CsrfDisablesPostRequestFromRequestCacheConfig extends WebSecurityConfigurerAdapter {
+
+		static CsrfTokenRepository REPO;
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().authenticated()
+					.and()
+				.formLogin()
+					.and()
+				.csrf()
+					.csrfTokenRepository(REPO);
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication()
+					.withUser(PasswordEncodedUser.user());
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class InvalidSessionUrlConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.csrf()
+					.and()
+				.sessionManagement()
+					.invalidSessionUrl("/error/sessionError");
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class RequireCsrfProtectionMatcherConfig extends WebSecurityConfigurerAdapter {
+
+		static RequestMatcher MATCHER;
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.csrf()
+					.requireCsrfProtectionMatcher(MATCHER);
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class RequireCsrfProtectionMatcherInLambdaConfig extends WebSecurityConfigurerAdapter {
+
+		static RequestMatcher MATCHER;
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.csrf(csrf -> csrf.requireCsrfProtectionMatcher(MATCHER));
+			// @formatter:on
+		}
+
+	}
+
 	@EnableWebSecurity
 	static class CsrfTokenRepositoryConfig extends WebSecurityConfigurerAdapter {
 
@@ -503,17 +591,6 @@ public class CsrfConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenCustomCsrfTokenRepositoryInLambdaThenRepositoryIsUsed() throws Exception {
-		CsrfTokenRepositoryInLambdaConfig.REPO = mock(CsrfTokenRepository.class);
-		when(CsrfTokenRepositoryInLambdaConfig.REPO.loadToken(any()))
-				.thenReturn(new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "token"));
-		this.spring.register(CsrfTokenRepositoryInLambdaConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(status().isOk());
-		verify(CsrfTokenRepositoryInLambdaConfig.REPO).loadToken(any(HttpServletRequest.class));
-	}
-
 	@EnableWebSecurity
 	static class CsrfTokenRepositoryInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -530,17 +607,6 @@ public class CsrfConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenCustomAccessDeniedHandlerThenHandlerIsUsed() throws Exception {
-		AccessDeniedHandlerConfig.DENIED_HANDLER = mock(AccessDeniedHandler.class);
-		this.spring.register(AccessDeniedHandlerConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(post("/")).andExpect(status().isOk());
-
-		verify(AccessDeniedHandlerConfig.DENIED_HANDLER).handle(any(HttpServletRequest.class),
-				any(HttpServletResponse.class), any());
-	}
-
 	@EnableWebSecurity
 	static class AccessDeniedHandlerConfig extends WebSecurityConfigurerAdapter {
 
@@ -557,30 +623,6 @@ public class CsrfConfigurerTests {
 
 	}
 
-	@Test
-	public void loginWhenNoCsrfTokenThenRespondsWithForbidden() throws Exception {
-		this.spring.register(FormLoginConfig.class).autowire();
-
-		this.mvc.perform(post("/login").param("username", "user").param("password", "password"))
-				.andExpect(status().isForbidden()).andExpect(unauthenticated());
-	}
-
-	@Test
-	public void logoutWhenNoCsrfTokenThenRespondsWithForbidden() throws Exception {
-		this.spring.register(FormLoginConfig.class).autowire();
-
-		this.mvc.perform(post("/logout").with(user("username"))).andExpect(status().isForbidden())
-				.andExpect(authenticated());
-	}
-
-	// SEC-2543
-	@Test
-	public void logoutWhenCsrfEnabledAndGetRequestThenDoesNotLogout() throws Exception {
-		this.spring.register(FormLoginConfig.class).autowire();
-
-		this.mvc.perform(get("/logout").with(user("username"))).andExpect(authenticated());
-	}
-
 	@EnableWebSecurity
 	static class FormLoginConfig extends WebSecurityConfigurerAdapter {
 
@@ -594,13 +636,6 @@ public class CsrfConfigurerTests {
 
 	}
 
-	@Test
-	public void logoutWhenGetRequestAndGetEnabledForLogoutThenLogsOut() throws Exception {
-		this.spring.register(LogoutAllowsGetConfig.class).autowire();
-
-		this.mvc.perform(get("/logout").with(user("username"))).andExpect(unauthenticated());
-	}
-
 	@EnableWebSecurity
 	static class LogoutAllowsGetConfig extends WebSecurityConfigurerAdapter {
 
@@ -617,13 +652,6 @@ public class CsrfConfigurerTests {
 
 	}
 
-	// SEC-2749
-	@Test
-	public void configureWhenRequireCsrfProtectionMatcherNullThenException() {
-		assertThatThrownBy(() -> this.spring.register(NullRequireCsrfProtectionMatcherConfig.class).autowire())
-				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
-	}
-
 	@EnableWebSecurity
 	static class NullRequireCsrfProtectionMatcherConfig extends WebSecurityConfigurerAdapter {
 
@@ -638,15 +666,6 @@ public class CsrfConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenDefaultCsrfTokenRepositoryThenDoesNotCreateSession() throws Exception {
-		this.spring.register(DefaultDoesNotCreateSession.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/")).andReturn();
-
-		assertThat(mvcResult.getRequest().getSession(false)).isNull();
-	}
-
 	@EnableWebSecurity
 	static class DefaultDoesNotCreateSession extends WebSecurityConfigurerAdapter {
 
@@ -688,12 +707,6 @@ public class CsrfConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenNullAuthenticationStrategyThenException() {
-		assertThatThrownBy(() -> this.spring.register(NullAuthenticationStrategy.class).autowire())
-				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
-	}
-
 	@EnableWebSecurity
 	static class CsrfAuthenticationStrategyConfig extends WebSecurityConfigurerAdapter {
 
@@ -721,19 +734,6 @@ public class CsrfConfigurerTests {
 
 	}
 
-	@Test
-	public void csrfAuthenticationStrategyConfiguredThenStrategyUsed() throws Exception {
-		CsrfAuthenticationStrategyConfig.STRATEGY = mock(SessionAuthenticationStrategy.class);
-
-		this.spring.register(CsrfAuthenticationStrategyConfig.class).autowire();
-
-		this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"))
-				.andExpect(redirectedUrl("/"));
-
-		verify(CsrfAuthenticationStrategyConfig.STRATEGY, atLeastOnce()).onAuthentication(any(Authentication.class),
-				any(HttpServletRequest.class), any(HttpServletResponse.class));
-	}
-
 	@RestController
 	static class BasicController {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultFiltersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultFiltersTests.java
index 716027edf0..0de52befb4 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultFiltersTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultFiltersTests.java
@@ -77,20 +77,6 @@ public class DefaultFiltersTests {
 		assertThat(this.spring.getContext().getBean(FilterChainProxy.class)).isNotNull();
 	}
 
-	@EnableWebSecurity
-	static class FilterChainProxyBuilderMissingConfig {
-
-		@Autowired
-		public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
-			// @formatter:off
-			auth
-				.inMemoryAuthentication()
-					.withUser("user").password("password").roles("USER");
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void nullWebInvocationPrivilegeEvaluator() {
 		this.spring.register(NullWebInvocationPrivilegeEvaluatorConfig.class, UserDetailsServiceConfig.class);
@@ -105,30 +91,6 @@ public class DefaultFiltersTests {
 		assertThat(filter).isEqualTo(1);
 	}
 
-	@Configuration
-	static class UserDetailsServiceConfig {
-
-		@Bean
-		public UserDetailsService userDetailsService() {
-			return new InMemoryUserDetailsManager(PasswordEncodedUser.user(), PasswordEncodedUser.admin());
-		}
-
-	}
-
-	@EnableWebSecurity
-	static class NullWebInvocationPrivilegeEvaluatorConfig extends WebSecurityConfigurerAdapter {
-
-		NullWebInvocationPrivilegeEvaluatorConfig() {
-			super(true);
-		}
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			http.formLogin();
-		}
-
-	}
-
 	@Test
 	public void filterChainProxyBuilderIgnoringResources() {
 		this.spring.register(FilterChainProxyBuilderIgnoringConfig.class, UserDetailsServiceConfig.class);
@@ -156,6 +118,60 @@ public class DefaultFiltersTests {
 		assertThat(classes.contains(FilterSecurityInterceptor.class)).isTrue();
 	}
 
+	@Test
+	public void defaultFiltersPermitAll() throws IOException, ServletException {
+		this.spring.register(DefaultFiltersConfigPermitAll.class, UserDetailsServiceConfig.class);
+		MockHttpServletResponse response = new MockHttpServletResponse();
+		MockHttpServletRequest request = new MockHttpServletRequest("POST", "");
+		request.setServletPath("/logout");
+
+		CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN");
+		new HttpSessionCsrfTokenRepository().saveToken(csrfToken, request, response);
+		request.setParameter(csrfToken.getParameterName(), csrfToken.getToken());
+
+		this.spring.getContext().getBean("springSecurityFilterChain", Filter.class).doFilter(request, response,
+				new MockFilterChain());
+		assertThat(response.getRedirectedUrl()).isEqualTo("/login?logout");
+	}
+
+	@EnableWebSecurity
+	static class FilterChainProxyBuilderMissingConfig {
+
+		@Autowired
+		public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER");
+			// @formatter:on
+		}
+
+	}
+
+	@Configuration
+	static class UserDetailsServiceConfig {
+
+		@Bean
+		public UserDetailsService userDetailsService() {
+			return new InMemoryUserDetailsManager(PasswordEncodedUser.user(), PasswordEncodedUser.admin());
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class NullWebInvocationPrivilegeEvaluatorConfig extends WebSecurityConfigurerAdapter {
+
+		NullWebInvocationPrivilegeEvaluatorConfig() {
+			super(true);
+		}
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http.formLogin();
+		}
+
+	}
+
 	@EnableWebSecurity
 	static class FilterChainProxyBuilderIgnoringConfig extends WebSecurityConfigurerAdapter {
 
@@ -179,22 +195,6 @@ public class DefaultFiltersTests {
 
 	}
 
-	@Test
-	public void defaultFiltersPermitAll() throws IOException, ServletException {
-		this.spring.register(DefaultFiltersConfigPermitAll.class, UserDetailsServiceConfig.class);
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		MockHttpServletRequest request = new MockHttpServletRequest("POST", "");
-		request.setServletPath("/logout");
-
-		CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN");
-		new HttpSessionCsrfTokenRepository().saveToken(csrfToken, request, response);
-		request.setParameter(csrfToken.getParameterName(), csrfToken.getToken());
-
-		this.spring.getContext().getBean("springSecurityFilterChain", Filter.class).doFilter(request, response,
-				new MockFilterChain());
-		assertThat(response.getRedirectedUrl()).isEqualTo("/login?logout");
-	}
-
 	@EnableWebSecurity
 	static class DefaultFiltersConfigPermitAll extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurerTests.java
index 43e409ec30..d2110741cf 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurerTests.java
@@ -176,31 +176,6 @@ public class DefaultLoginPageConfigurerTests {
 						+ "      \n" + "\n" + ""));
 	}
 
-	@EnableWebSecurity
-	static class DefaultLoginPageConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.anyRequest().hasRole("USER")
-					.and()
-				.formLogin();
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-			// @formatter:off
-			auth
-				.inMemoryAuthentication()
-					.withUser(PasswordEncodedUser.user());
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void loginPageWhenLoggedOutAndCustomLogoutSuccessHandlerThenDoesNotRenderLoginPage() throws Exception {
 		this.spring.register(DefaultLoginPageCustomLogoutSuccessHandlerConfig.class).autowire();
@@ -208,25 +183,6 @@ public class DefaultLoginPageConfigurerTests {
 		this.mvc.perform(get("/login?logout")).andExpect(content().string(""));
 	}
 
-	@EnableWebSecurity
-	static class DefaultLoginPageCustomLogoutSuccessHandlerConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.anyRequest().hasRole("USER")
-					.and()
-				.logout()
-					.logoutSuccessHandler(new SimpleUrlLogoutSuccessHandler())
-					.and()
-				.formLogin();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void loginPageWhenLoggedOutAndCustomLogoutSuccessUrlThenDoesNotRenderLoginPage() throws Exception {
 		this.spring.register(DefaultLoginPageCustomLogoutSuccessUrlConfig.class).autowire();
@@ -234,25 +190,6 @@ public class DefaultLoginPageConfigurerTests {
 		this.mvc.perform(get("/login?logout")).andExpect(content().string(""));
 	}
 
-	@EnableWebSecurity
-	static class DefaultLoginPageCustomLogoutSuccessUrlConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.anyRequest().hasRole("USER")
-					.and()
-				.logout()
-					.logoutSuccessUrl("/login?logout")
-					.and()
-				.formLogin();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void loginPageWhenRememberConfigureThenDefaultLoginPageWithRememberMeCheckbox() throws Exception {
 		this.spring.register(DefaultLoginPageWithRememberMeConfig.class).autowire();
@@ -283,24 +220,6 @@ public class DefaultLoginPageConfigurerTests {
 						+ "      \n" + "\n" + ""));
 	}
 
-	@EnableWebSecurity
-	static class DefaultLoginPageWithRememberMeConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.anyRequest().hasRole("USER")
-					.and()
-				.formLogin()
-					.and()
-				.rememberMe();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void loginPageWhenOpenIdLoginConfiguredThenOpedIdLoginPage() throws Exception {
 		this.spring.register(DefaultLoginPageWithOpenIDConfig.class).autowire();
@@ -327,22 +246,6 @@ public class DefaultLoginPageConfigurerTests {
 						+ "      \n" + "\n" + ""));
 	}
 
-	@EnableWebSecurity
-	static class DefaultLoginPageWithOpenIDConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.anyRequest().hasRole("USER")
-					.and()
-				.openidLogin();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void loginPageWhenOpenIdLoginAndFormLoginAndRememberMeConfiguredThenOpedIdLoginPage() throws Exception {
 		this.spring.register(DefaultLoginPageWithFormLoginOpenIDRememberMeConfig.class).autowire();
@@ -383,55 +286,6 @@ public class DefaultLoginPageConfigurerTests {
 						+ "      \n" + "\n" + ""));
 	}
 
-	@EnableWebSecurity
-	static class DefaultLoginPageWithFormLoginOpenIDRememberMeConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.anyRequest().hasRole("USER")
-					.and()
-				.rememberMe()
-					.and()
-				.formLogin()
-					.and()
-				.openidLogin();
-			// @formatter:on
-		}
-
-	}
-
-	@Test
-	public void configureWhenAuthenticationEntryPointThenNoDefaultLoginPageGeneratingFilter() {
-		this.spring.register(DefaultLoginWithCustomAuthenticationEntryPointConfig.class).autowire();
-
-		FilterChainProxy filterChain = this.spring.getContext().getBean(FilterChainProxy.class);
-		assertThat(filterChain.getFilterChains().get(0).getFilters().stream()
-				.filter(filter -> filter.getClass().isAssignableFrom(DefaultLoginPageGeneratingFilter.class)).count())
-						.isZero();
-	}
-
-	@EnableWebSecurity
-	static class DefaultLoginWithCustomAuthenticationEntryPointConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.exceptionHandling()
-					.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login"))
-					.and()
-				.authorizeRequests()
-					.anyRequest().hasRole("USER")
-					.and()
-				.formLogin();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnDefaultLoginPageGeneratingFilter() {
 		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
@@ -465,6 +319,152 @@ public class DefaultLoginPageConfigurerTests {
 		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(ExceptionTranslationFilter.class));
 	}
 
+	@Test
+	public void configureWhenAuthenticationEntryPointThenNoDefaultLoginPageGeneratingFilter() {
+		this.spring.register(DefaultLoginWithCustomAuthenticationEntryPointConfig.class).autowire();
+
+		FilterChainProxy filterChain = this.spring.getContext().getBean(FilterChainProxy.class);
+		assertThat(filterChain.getFilterChains().get(0).getFilters().stream()
+				.filter(filter -> filter.getClass().isAssignableFrom(DefaultLoginPageGeneratingFilter.class)).count())
+						.isZero();
+	}
+
+	@EnableWebSecurity
+	static class DefaultLoginPageConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin();
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication()
+					.withUser(PasswordEncodedUser.user());
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class DefaultLoginPageCustomLogoutSuccessHandlerConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.logout()
+					.logoutSuccessHandler(new SimpleUrlLogoutSuccessHandler())
+					.and()
+				.formLogin();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class DefaultLoginPageCustomLogoutSuccessUrlConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.logout()
+					.logoutSuccessUrl("/login?logout")
+					.and()
+				.formLogin();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class DefaultLoginPageWithRememberMeConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin()
+					.and()
+				.rememberMe();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class DefaultLoginPageWithOpenIDConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.openidLogin();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class DefaultLoginPageWithFormLoginOpenIDRememberMeConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.rememberMe()
+					.and()
+				.formLogin()
+					.and()
+				.openidLogin();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class DefaultLoginWithCustomAuthenticationEntryPointConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.exceptionHandling()
+					.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login"))
+					.and()
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin();
+			// @formatter:on
+		}
+
+	}
+
 	@EnableWebSecurity
 	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerAccessDeniedHandlerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerAccessDeniedHandlerTests.java
index ab6021c5c0..4bfc897690 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerAccessDeniedHandlerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerAccessDeniedHandlerTests.java
@@ -60,6 +60,26 @@ public class ExceptionHandlingConfigurerAccessDeniedHandlerTests {
 		this.mvc.perform(get("/goodbye")).andExpect(status().isForbidden());
 	}
 
+	@Test
+	@WithMockUser(roles = "ANYTHING")
+	public void getWhenAccessDeniedOverriddenInLambdaThenCustomizesResponseByRequest() throws Exception {
+		this.spring.register(RequestMatcherBasedAccessDeniedHandlerInLambdaConfig.class).autowire();
+
+		this.mvc.perform(get("/hello")).andExpect(status().isIAmATeapot());
+
+		this.mvc.perform(get("/goodbye")).andExpect(status().isForbidden());
+	}
+
+	@Test
+	@WithMockUser(roles = "ANYTHING")
+	public void getWhenAccessDeniedOverriddenByOnlyOneHandlerThenAllRequestsUseThatHandler() throws Exception {
+		this.spring.register(SingleRequestMatcherAccessDeniedHandlerConfig.class).autowire();
+
+		this.mvc.perform(get("/hello")).andExpect(status().isIAmATeapot());
+
+		this.mvc.perform(get("/goodbye")).andExpect(status().isIAmATeapot());
+	}
+
 	@EnableWebSecurity
 	static class RequestMatcherBasedAccessDeniedHandlerConfig extends WebSecurityConfigurerAdapter {
 
@@ -85,16 +105,6 @@ public class ExceptionHandlingConfigurerAccessDeniedHandlerTests {
 
 	}
 
-	@Test
-	@WithMockUser(roles = "ANYTHING")
-	public void getWhenAccessDeniedOverriddenInLambdaThenCustomizesResponseByRequest() throws Exception {
-		this.spring.register(RequestMatcherBasedAccessDeniedHandlerInLambdaConfig.class).autowire();
-
-		this.mvc.perform(get("/hello")).andExpect(status().isIAmATeapot());
-
-		this.mvc.perform(get("/goodbye")).andExpect(status().isForbidden());
-	}
-
 	@EnableWebSecurity
 	static class RequestMatcherBasedAccessDeniedHandlerInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -125,16 +135,6 @@ public class ExceptionHandlingConfigurerAccessDeniedHandlerTests {
 
 	}
 
-	@Test
-	@WithMockUser(roles = "ANYTHING")
-	public void getWhenAccessDeniedOverriddenByOnlyOneHandlerThenAllRequestsUseThatHandler() throws Exception {
-		this.spring.register(SingleRequestMatcherAccessDeniedHandlerConfig.class).autowire();
-
-		this.mvc.perform(get("/hello")).andExpect(status().isIAmATeapot());
-
-		this.mvc.perform(get("/goodbye")).andExpect(status().isIAmATeapot());
-	}
-
 	@EnableWebSecurity
 	static class SingleRequestMatcherAccessDeniedHandlerConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerTests.java
index 54b341f14f..3728529db4 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerTests.java
@@ -70,35 +70,6 @@ public class ExceptionHandlingConfigurerTests {
 		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(ExceptionTranslationFilter.class));
 	}
 
-	@EnableWebSecurity
-	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
-
-		static ObjectPostProcessor objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.exceptionHandling();
-			// @formatter:on
-		}
-
-		@Bean
-		static ObjectPostProcessor objectPostProcessor() {
-			return objectPostProcessor;
-		}
-
-	}
-
-	static class ReflectingObjectPostProcessor implements ObjectPostProcessor {
-
-		@Override
-		public  O postProcess(O object) {
-			return object;
-		}
-
-	}
-
 	// SEC-2199
 	@Test
 	public void getWhenAcceptHeaderIsApplicationXhtmlXmlThenRespondsWith302() throws Exception {
@@ -226,6 +197,71 @@ public class ExceptionHandlingConfigurerTests {
 				.andExpect(status().isUnauthorized());
 	}
 
+	@Test
+	public void getWhenCustomContentNegotiationStrategyThenStrategyIsUsed() throws Exception {
+		this.spring.register(OverrideContentNegotiationStrategySharedObjectConfig.class, DefaultSecurityConfig.class)
+				.autowire();
+
+		this.mvc.perform(get("/"));
+
+		verify(OverrideContentNegotiationStrategySharedObjectConfig.CNS, atLeastOnce())
+				.resolveMediaTypes(any(NativeWebRequest.class));
+	}
+
+	@Test
+	public void getWhenUsingDefaultsAndUnauthenticatedThenRedirectsToLogin() throws Exception {
+		this.spring.register(DefaultHttpConfig.class).autowire();
+
+		this.mvc.perform(get("/").header(HttpHeaders.ACCEPT, "bogus/type"))
+				.andExpect(redirectedUrl("http://localhost/login"));
+	}
+
+	@Test
+	public void getWhenDeclaringHttpBasicBeforeFormLoginThenRespondsWith401() throws Exception {
+		this.spring.register(BasicAuthenticationEntryPointBeforeFormLoginConfig.class).autowire();
+
+		this.mvc.perform(get("/").header(HttpHeaders.ACCEPT, "bogus/type")).andExpect(status().isUnauthorized());
+	}
+
+	@Test
+	public void getWhenInvokingExceptionHandlingTwiceThenOriginalEntryPointUsed() throws Exception {
+		this.spring.register(InvokeTwiceDoesNotOverrideConfig.class).autowire();
+
+		this.mvc.perform(get("/"));
+
+		verify(InvokeTwiceDoesNotOverrideConfig.AEP).commence(any(HttpServletRequest.class),
+				any(HttpServletResponse.class), any(AuthenticationException.class));
+	}
+
+	@EnableWebSecurity
+	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
+
+		static ObjectPostProcessor objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.exceptionHandling();
+			// @formatter:on
+		}
+
+		@Bean
+		static ObjectPostProcessor objectPostProcessor() {
+			return objectPostProcessor;
+		}
+
+	}
+
+	static class ReflectingObjectPostProcessor implements ObjectPostProcessor {
+
+		@Override
+		public  O postProcess(O object) {
+			return object;
+		}
+
+	}
+
 	@EnableWebSecurity
 	static class DefaultSecurityConfig {
 
@@ -267,17 +303,6 @@ public class ExceptionHandlingConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenCustomContentNegotiationStrategyThenStrategyIsUsed() throws Exception {
-		this.spring.register(OverrideContentNegotiationStrategySharedObjectConfig.class, DefaultSecurityConfig.class)
-				.autowire();
-
-		this.mvc.perform(get("/"));
-
-		verify(OverrideContentNegotiationStrategySharedObjectConfig.CNS, atLeastOnce())
-				.resolveMediaTypes(any(NativeWebRequest.class));
-	}
-
 	@EnableWebSecurity
 	static class OverrideContentNegotiationStrategySharedObjectConfig extends WebSecurityConfigurerAdapter {
 
@@ -290,26 +315,11 @@ public class ExceptionHandlingConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenUsingDefaultsAndUnauthenticatedThenRedirectsToLogin() throws Exception {
-		this.spring.register(DefaultHttpConfig.class).autowire();
-
-		this.mvc.perform(get("/").header(HttpHeaders.ACCEPT, "bogus/type"))
-				.andExpect(redirectedUrl("http://localhost/login"));
-	}
-
 	@EnableWebSecurity
 	static class DefaultHttpConfig extends WebSecurityConfigurerAdapter {
 
 	}
 
-	@Test
-	public void getWhenDeclaringHttpBasicBeforeFormLoginThenRespondsWith401() throws Exception {
-		this.spring.register(BasicAuthenticationEntryPointBeforeFormLoginConfig.class).autowire();
-
-		this.mvc.perform(get("/").header(HttpHeaders.ACCEPT, "bogus/type")).andExpect(status().isUnauthorized());
-	}
-
 	@EnableWebSecurity
 	static class BasicAuthenticationEntryPointBeforeFormLoginConfig extends WebSecurityConfigurerAdapter {
 
@@ -328,16 +338,6 @@ public class ExceptionHandlingConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenInvokingExceptionHandlingTwiceThenOriginalEntryPointUsed() throws Exception {
-		this.spring.register(InvokeTwiceDoesNotOverrideConfig.class).autowire();
-
-		this.mvc.perform(get("/"));
-
-		verify(InvokeTwiceDoesNotOverrideConfig.AEP).commence(any(HttpServletRequest.class),
-				any(HttpServletResponse.class), any(AuthenticationException.class));
-	}
-
 	@EnableWebSecurity
 	static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurerTests.java
index 1ce457ff8b..dcb870439c 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurerTests.java
@@ -90,20 +90,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 						"role should not start with 'ROLE_' since it is automatically inserted. Got 'ROLE_USER'");
 	}
 
-	@EnableWebSecurity
-	static class HasRoleStartingWithRoleConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.anyRequest().hasRole("ROLE_USER");
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void configureWhenNoCustomAccessDecisionManagerThenUsesAffirmativeBased() {
 		this.spring.register(NoSpecificAccessDecisionManagerConfig.class).autowire();
@@ -111,27 +97,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 		verify(NoSpecificAccessDecisionManagerConfig.objectPostProcessor).postProcess(any(AffirmativeBased.class));
 	}
 
-	@EnableWebSecurity
-	static class NoSpecificAccessDecisionManagerConfig extends WebSecurityConfigurerAdapter {
-
-		static ObjectPostProcessor objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.anyRequest().hasRole("USER");
-			// @formatter:on
-		}
-
-		@Bean
-		static ObjectPostProcessor objectPostProcessor() {
-			return objectPostProcessor;
-		}
-
-	}
-
 	@Test
 	public void configureWhenAuthorizedRequestsAndNoRequestsThenException() {
 		assertThatThrownBy(() -> this.spring.register(NoRequestsConfig.class).autowire())
@@ -139,40 +104,12 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 						"At least one mapping is required (i.e. authorizeRequests().anyRequest().authenticated())");
 	}
 
-	@EnableWebSecurity
-	static class NoRequestsConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void configureWhenAnyRequestIncompleteMappingThenException() {
 		assertThatThrownBy(() -> this.spring.register(IncompleteMappingConfig.class).autowire())
 				.isInstanceOf(BeanCreationException.class).hasMessageContaining("An incomplete mapping was found for ");
 	}
 
-	@EnableWebSecurity
-	static class IncompleteMappingConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.antMatchers("/a").authenticated()
-					.anyRequest();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenHasAnyAuthorityRoleUserConfiguredAndAuthorityIsRoleUserThenRespondsWithOk() throws Exception {
 		this.spring.register(RoleUserAnyAuthorityConfig.class, BasicController.class).autowire();
@@ -197,22 +134,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 		this.mvc.perform(get("/")).andExpect(status().isUnauthorized());
 	}
 
-	@EnableWebSecurity
-	static class RoleUserAnyAuthorityConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.httpBasic()
-					.and()
-				.authorizeRequests()
-					.anyRequest().hasAnyAuthority("ROLE_USER");
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenHasAuthorityRoleUserConfiguredAndAuthorityIsRoleUserThenRespondsWithOk() throws Exception {
 		this.spring.register(RoleUserAuthorityConfig.class, BasicController.class).autowire();
@@ -237,22 +158,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 		this.mvc.perform(get("/")).andExpect(status().isUnauthorized());
 	}
 
-	@EnableWebSecurity
-	static class RoleUserAuthorityConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.httpBasic()
-					.and()
-				.authorizeRequests()
-					.anyRequest().hasAuthority("ROLE_USER");
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenAuthorityRoleUserOrAdminRequiredAndAuthorityIsRoleUserThenRespondsWithOk() throws Exception {
 		this.spring.register(RoleUserOrRoleAdminAuthorityConfig.class, BasicController.class).autowire();
@@ -285,22 +190,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 		this.mvc.perform(get("/")).andExpect(status().isUnauthorized());
 	}
 
-	@EnableWebSecurity
-	static class RoleUserOrRoleAdminAuthorityConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.httpBasic()
-					.and()
-				.authorizeRequests()
-					.anyRequest().hasAnyAuthority("ROLE_USER", "ROLE_ADMIN");
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenHasAnyRoleUserConfiguredAndRoleIsUserThenRespondsWithOk() throws Exception {
 		this.spring.register(RoleUserConfig.class, BasicController.class).autowire();
@@ -315,20 +204,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 		this.mvc.perform(get("/").with(user("user").roles("ADMIN"))).andExpect(status().isForbidden());
 	}
 
-	@EnableWebSecurity
-	static class RoleUserConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.anyRequest().hasAnyRole("USER");
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenRoleUserOrAdminConfiguredAndRoleIsUserThenRespondsWithOk() throws Exception {
 		this.spring.register(RoleUserOrAdminConfig.class, BasicController.class).autowire();
@@ -350,20 +225,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 		this.mvc.perform(get("/").with(user("user").roles("OTHER"))).andExpect(status().isForbidden());
 	}
 
-	@EnableWebSecurity
-	static class RoleUserOrAdminConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.anyRequest().hasAnyRole("USER", "ADMIN");
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenHasIpAddressConfiguredAndIpAddressMatchesThenRespondsWithOk() throws Exception {
 		this.spring.register(HasIpAddressConfig.class, BasicController.class).autowire();
@@ -384,22 +245,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 		})).andExpect(status().isUnauthorized());
 	}
 
-	@EnableWebSecurity
-	static class HasIpAddressConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.httpBasic()
-					.and()
-				.authorizeRequests()
-					.anyRequest().hasIpAddress("192.168.1.0");
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenAnonymousConfiguredAndAnonymousUserThenRespondsWithOk() throws Exception {
 		this.spring.register(AnonymousConfig.class, BasicController.class).autowire();
@@ -414,22 +259,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 		this.mvc.perform(get("/").with(user("user"))).andExpect(status().isForbidden());
 	}
 
-	@EnableWebSecurity
-	static class AnonymousConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.httpBasic()
-					.and()
-				.authorizeRequests()
-					.anyRequest().anonymous();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenRememberMeConfiguredAndNoUserThenRespondsWithUnauthorized() throws Exception {
 		this.spring.register(RememberMeConfig.class, BasicController.class).autowire();
@@ -446,6 +275,377 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 				.andExpect(status().isOk());
 	}
 
+	@Test
+	public void getWhenDenyAllConfiguredAndNoUserThenRespondsWithUnauthorized() throws Exception {
+		this.spring.register(DenyAllConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(status().isUnauthorized());
+	}
+
+	@Test
+	public void getWheDenyAllConfiguredAndUserLoggedInThenRespondsWithForbidden() throws Exception {
+		this.spring.register(DenyAllConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/").with(user("user").roles("USER"))).andExpect(status().isForbidden());
+	}
+
+	@Test
+	public void getWhenNotDenyAllConfiguredAndNoUserThenRespondsWithOk() throws Exception {
+		this.spring.register(NotDenyAllConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(status().isOk());
+	}
+
+	@Test
+	public void getWhenNotDenyAllConfiguredAndRememberMeTokenThenRespondsWithOk() throws Exception {
+		this.spring.register(NotDenyAllConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/").with(authentication(
+				new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))))
+				.andExpect(status().isOk());
+	}
+
+	@Test
+	public void getWhenFullyAuthenticatedConfiguredAndRememberMeTokenThenRespondsWithUnauthorized() throws Exception {
+		this.spring.register(FullyAuthenticatedConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/").with(authentication(
+				new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))))
+				.andExpect(status().isUnauthorized());
+	}
+
+	@Test
+	public void getWhenFullyAuthenticatedConfiguredAndUserThenRespondsWithOk() throws Exception {
+		this.spring.register(FullyAuthenticatedConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/").with(user("user").roles("USER"))).andExpect(status().isOk());
+	}
+
+	@Test
+	public void getWhenAccessRoleUserOrGetRequestConfiguredThenRespondsWithOk() throws Exception {
+		this.spring.register(AccessConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(status().isOk());
+	}
+
+	@Test
+	public void postWhenAccessRoleUserOrGetRequestConfiguredAndRoleUserThenRespondsWithOk() throws Exception {
+		this.spring.register(AccessConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(post("/").with(csrf()).with(user("user").roles("USER"))).andExpect(status().isOk());
+	}
+
+	@Test
+	public void postWhenAccessRoleUserOrGetRequestConfiguredThenRespondsWithUnauthorized() throws Exception {
+		this.spring.register(AccessConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(post("/").with(csrf())).andExpect(status().isUnauthorized());
+	}
+
+	@Test
+	public void authorizeRequestsWhenInvokedTwiceThenUsesOriginalConfiguration() throws Exception {
+		this.spring.register(InvokeTwiceDoesNotResetConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(post("/").with(csrf())).andExpect(status().isUnauthorized());
+	}
+
+	@Test
+	public void configureWhenUsingAllAuthorizeRequestPropertiesThenCompiles() {
+		this.spring.register(AllPropertiesWorkConfig.class).autowire();
+	}
+
+	@Test
+	public void configureWhenRegisteringObjectPostProcessorThenApplicationListenerInvokedOnAuthorizedEvent()
+			throws Exception {
+		this.spring.register(AuthorizedRequestsWithPostProcessorConfig.class).autowire();
+
+		this.mvc.perform(get("/"));
+
+		verify(AuthorizedRequestsWithPostProcessorConfig.AL).onApplicationEvent(any(AuthorizedEvent.class));
+	}
+
+	@Test
+	public void getWhenPermissionCheckAndRoleDoesNotMatchThenRespondsWithForbidden() throws Exception {
+		this.spring.register(UseBeansInExpressions.class, WildcardController.class).autowire();
+
+		this.mvc.perform(get("/admin").with(user("user").roles("USER"))).andExpect(status().isForbidden());
+	}
+
+	@Test
+	public void getWhenPermissionCheckAndRoleMatchesThenRespondsWithOk() throws Exception {
+		this.spring.register(UseBeansInExpressions.class, WildcardController.class).autowire();
+
+		this.mvc.perform(get("/user").with(user("user").roles("USER"))).andExpect(status().isOk());
+	}
+
+	@Test
+	public void getWhenPermissionCheckAndAuthenticationNameMatchesThenRespondsWithOk() throws Exception {
+		this.spring.register(UseBeansInExpressions.class, WildcardController.class).autowire();
+
+		this.mvc.perform(get("/allow").with(user("user").roles("USER"))).andExpect(status().isOk());
+	}
+
+	@Test
+	public void getWhenPermissionCheckAndAuthenticationNameDoesNotMatchThenRespondsWithForbidden() throws Exception {
+		this.spring.register(UseBeansInExpressions.class, WildcardController.class).autowire();
+
+		this.mvc.perform(get("/deny").with(user("user").roles("USER"))).andExpect(status().isForbidden());
+	}
+
+	@Test
+	public void getWhenCustomExpressionHandlerAndRoleDoesNotMatchThenRespondsWithForbidden() throws Exception {
+		this.spring.register(CustomExpressionRootConfig.class, WildcardController.class).autowire();
+
+		this.mvc.perform(get("/admin").with(user("user").roles("USER"))).andExpect(status().isForbidden());
+	}
+
+	@Test
+	public void getWhenCustomExpressionHandlerAndRoleMatchesThenRespondsWithOk() throws Exception {
+		this.spring.register(CustomExpressionRootConfig.class, WildcardController.class).autowire();
+
+		this.mvc.perform(get("/user").with(user("user").roles("USER"))).andExpect(status().isOk());
+	}
+
+	@Test
+	public void getWhenCustomExpressionHandlerAndAuthenticationNameMatchesThenRespondsWithOk() throws Exception {
+		this.spring.register(CustomExpressionRootConfig.class, WildcardController.class).autowire();
+
+		this.mvc.perform(get("/allow").with(user("user").roles("USER"))).andExpect(status().isOk());
+	}
+
+	@Test
+	public void getWhenCustomExpressionHandlerAndAuthenticationNameDoesNotMatchThenRespondsWithForbidden()
+			throws Exception {
+		this.spring.register(CustomExpressionRootConfig.class, WildcardController.class).autowire();
+
+		this.mvc.perform(get("/deny").with(user("user").roles("USER"))).andExpect(status().isForbidden());
+	}
+
+	// SEC-3011
+	@Test
+	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnAccessDecisionManager() {
+		this.spring.register(Sec3011Config.class).autowire();
+
+		verify(Sec3011Config.objectPostProcessor).postProcess(any(AccessDecisionManager.class));
+	}
+
+	@Test
+	public void getWhenRegisteringPermissionEvaluatorAndPermissionWithIdAndTypeMatchesThenRespondsWithOk()
+			throws Exception {
+		this.spring.register(PermissionEvaluatorConfig.class, WildcardController.class).autowire();
+
+		this.mvc.perform(get("/allow")).andExpect(status().isOk());
+	}
+
+	@Test
+	public void getWhenRegisteringPermissionEvaluatorAndPermissionWithIdAndTypeDoesNotMatchThenRespondsWithForbidden()
+			throws Exception {
+		this.spring.register(PermissionEvaluatorConfig.class, WildcardController.class).autowire();
+
+		this.mvc.perform(get("/deny")).andExpect(status().isForbidden());
+	}
+
+	@Test
+	public void getWhenRegisteringPermissionEvaluatorAndPermissionWithObjectMatchesThenRespondsWithOk()
+			throws Exception {
+		this.spring.register(PermissionEvaluatorConfig.class, WildcardController.class).autowire();
+
+		this.mvc.perform(get("/allowObject")).andExpect(status().isOk());
+	}
+
+	@Test
+	public void getWhenRegisteringPermissionEvaluatorAndPermissionWithObjectDoesNotMatchThenRespondsWithForbidden()
+			throws Exception {
+		this.spring.register(PermissionEvaluatorConfig.class, WildcardController.class).autowire();
+
+		this.mvc.perform(get("/denyObject")).andExpect(status().isForbidden());
+	}
+
+	@Test
+	public void getWhenRegisteringRoleHierarchyAndRelatedRoleAllowedThenRespondsWithOk() throws Exception {
+		this.spring.register(RoleHierarchyConfig.class, WildcardController.class).autowire();
+
+		this.mvc.perform(get("/allow").with(user("user").roles("USER"))).andExpect(status().isOk());
+	}
+
+	@Test
+	public void getWhenRegisteringRoleHierarchyAndNoRelatedRolesAllowedThenRespondsWithForbidden() throws Exception {
+		this.spring.register(RoleHierarchyConfig.class, WildcardController.class).autowire();
+
+		this.mvc.perform(get("/deny").with(user("user").roles("USER"))).andExpect(status().isForbidden());
+	}
+
+	@EnableWebSecurity
+	static class HasRoleStartingWithRoleConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("ROLE_USER");
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class NoSpecificAccessDecisionManagerConfig extends WebSecurityConfigurerAdapter {
+
+		static ObjectPostProcessor objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER");
+			// @formatter:on
+		}
+
+		@Bean
+		static ObjectPostProcessor objectPostProcessor() {
+			return objectPostProcessor;
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class NoRequestsConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class IncompleteMappingConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.antMatchers("/a").authenticated()
+					.anyRequest();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class RoleUserAnyAuthorityConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.httpBasic()
+					.and()
+				.authorizeRequests()
+					.anyRequest().hasAnyAuthority("ROLE_USER");
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class RoleUserAuthorityConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.httpBasic()
+					.and()
+				.authorizeRequests()
+					.anyRequest().hasAuthority("ROLE_USER");
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class RoleUserOrRoleAdminAuthorityConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.httpBasic()
+					.and()
+				.authorizeRequests()
+					.anyRequest().hasAnyAuthority("ROLE_USER", "ROLE_ADMIN");
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class RoleUserConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().hasAnyRole("USER");
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class RoleUserOrAdminConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().hasAnyRole("USER", "ADMIN");
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class HasIpAddressConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.httpBasic()
+					.and()
+				.authorizeRequests()
+					.anyRequest().hasIpAddress("192.168.1.0");
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class AnonymousConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.httpBasic()
+					.and()
+				.authorizeRequests()
+					.anyRequest().anonymous();
+			// @formatter:on
+		}
+
+	}
+
 	@EnableWebSecurity
 	static class RememberMeConfig extends WebSecurityConfigurerAdapter {
 
@@ -473,20 +673,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenDenyAllConfiguredAndNoUserThenRespondsWithUnauthorized() throws Exception {
-		this.spring.register(DenyAllConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(status().isUnauthorized());
-	}
-
-	@Test
-	public void getWheDenyAllConfiguredAndUserLoggedInThenRespondsWithForbidden() throws Exception {
-		this.spring.register(DenyAllConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(get("/").with(user("user").roles("USER"))).andExpect(status().isForbidden());
-	}
-
 	@EnableWebSecurity
 	static class DenyAllConfig extends WebSecurityConfigurerAdapter {
 
@@ -503,22 +689,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenNotDenyAllConfiguredAndNoUserThenRespondsWithOk() throws Exception {
-		this.spring.register(NotDenyAllConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(status().isOk());
-	}
-
-	@Test
-	public void getWhenNotDenyAllConfiguredAndRememberMeTokenThenRespondsWithOk() throws Exception {
-		this.spring.register(NotDenyAllConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(get("/").with(authentication(
-				new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))))
-				.andExpect(status().isOk());
-	}
-
 	@EnableWebSecurity
 	static class NotDenyAllConfig extends WebSecurityConfigurerAdapter {
 
@@ -535,22 +705,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenFullyAuthenticatedConfiguredAndRememberMeTokenThenRespondsWithUnauthorized() throws Exception {
-		this.spring.register(FullyAuthenticatedConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(get("/").with(authentication(
-				new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))))
-				.andExpect(status().isUnauthorized());
-	}
-
-	@Test
-	public void getWhenFullyAuthenticatedConfiguredAndUserThenRespondsWithOk() throws Exception {
-		this.spring.register(FullyAuthenticatedConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(get("/").with(user("user").roles("USER"))).andExpect(status().isOk());
-	}
-
 	@EnableWebSecurity
 	static class FullyAuthenticatedConfig extends WebSecurityConfigurerAdapter {
 
@@ -569,27 +723,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenAccessRoleUserOrGetRequestConfiguredThenRespondsWithOk() throws Exception {
-		this.spring.register(AccessConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(status().isOk());
-	}
-
-	@Test
-	public void postWhenAccessRoleUserOrGetRequestConfiguredAndRoleUserThenRespondsWithOk() throws Exception {
-		this.spring.register(AccessConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(post("/").with(csrf()).with(user("user").roles("USER"))).andExpect(status().isOk());
-	}
-
-	@Test
-	public void postWhenAccessRoleUserOrGetRequestConfiguredThenRespondsWithUnauthorized() throws Exception {
-		this.spring.register(AccessConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(post("/").with(csrf())).andExpect(status().isUnauthorized());
-	}
-
 	@EnableWebSecurity
 	static class AccessConfig extends WebSecurityConfigurerAdapter {
 
@@ -608,13 +741,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 
 	}
 
-	@Test
-	public void authorizeRequestsWhenInvokedTwiceThenUsesOriginalConfiguration() throws Exception {
-		this.spring.register(InvokeTwiceDoesNotResetConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(post("/").with(csrf())).andExpect(status().isUnauthorized());
-	}
-
 	@EnableWebSecurity
 	static class InvokeTwiceDoesNotResetConfig extends WebSecurityConfigurerAdapter {
 
@@ -633,11 +759,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 
 	}
 
-	@Test
-	public void configureWhenUsingAllAuthorizeRequestPropertiesThenCompiles() {
-		this.spring.register(AllPropertiesWorkConfig.class).autowire();
-	}
-
 	@EnableWebSecurity
 	static class AllPropertiesWorkConfig extends WebSecurityConfigurerAdapter {
 
@@ -661,16 +782,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 
 	}
 
-	@Test
-	public void configureWhenRegisteringObjectPostProcessorThenApplicationListenerInvokedOnAuthorizedEvent()
-			throws Exception {
-		this.spring.register(AuthorizedRequestsWithPostProcessorConfig.class).autowire();
-
-		this.mvc.perform(get("/"));
-
-		verify(AuthorizedRequestsWithPostProcessorConfig.AL).onApplicationEvent(any(AuthorizedEvent.class));
-	}
-
 	@EnableWebSecurity
 	static class AuthorizedRequestsWithPostProcessorConfig extends WebSecurityConfigurerAdapter {
 
@@ -700,34 +811,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenPermissionCheckAndRoleDoesNotMatchThenRespondsWithForbidden() throws Exception {
-		this.spring.register(UseBeansInExpressions.class, WildcardController.class).autowire();
-
-		this.mvc.perform(get("/admin").with(user("user").roles("USER"))).andExpect(status().isForbidden());
-	}
-
-	@Test
-	public void getWhenPermissionCheckAndRoleMatchesThenRespondsWithOk() throws Exception {
-		this.spring.register(UseBeansInExpressions.class, WildcardController.class).autowire();
-
-		this.mvc.perform(get("/user").with(user("user").roles("USER"))).andExpect(status().isOk());
-	}
-
-	@Test
-	public void getWhenPermissionCheckAndAuthenticationNameMatchesThenRespondsWithOk() throws Exception {
-		this.spring.register(UseBeansInExpressions.class, WildcardController.class).autowire();
-
-		this.mvc.perform(get("/allow").with(user("user").roles("USER"))).andExpect(status().isOk());
-	}
-
-	@Test
-	public void getWhenPermissionCheckAndAuthenticationNameDoesNotMatchThenRespondsWithForbidden() throws Exception {
-		this.spring.register(UseBeansInExpressions.class, WildcardController.class).autowire();
-
-		this.mvc.perform(get("/deny").with(user("user").roles("USER"))).andExpect(status().isForbidden());
-	}
-
 	@EnableWebSecurity
 	static class UseBeansInExpressions extends WebSecurityConfigurerAdapter {
 
@@ -758,35 +841,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenCustomExpressionHandlerAndRoleDoesNotMatchThenRespondsWithForbidden() throws Exception {
-		this.spring.register(CustomExpressionRootConfig.class, WildcardController.class).autowire();
-
-		this.mvc.perform(get("/admin").with(user("user").roles("USER"))).andExpect(status().isForbidden());
-	}
-
-	@Test
-	public void getWhenCustomExpressionHandlerAndRoleMatchesThenRespondsWithOk() throws Exception {
-		this.spring.register(CustomExpressionRootConfig.class, WildcardController.class).autowire();
-
-		this.mvc.perform(get("/user").with(user("user").roles("USER"))).andExpect(status().isOk());
-	}
-
-	@Test
-	public void getWhenCustomExpressionHandlerAndAuthenticationNameMatchesThenRespondsWithOk() throws Exception {
-		this.spring.register(CustomExpressionRootConfig.class, WildcardController.class).autowire();
-
-		this.mvc.perform(get("/allow").with(user("user").roles("USER"))).andExpect(status().isOk());
-	}
-
-	@Test
-	public void getWhenCustomExpressionHandlerAndAuthenticationNameDoesNotMatchThenRespondsWithForbidden()
-			throws Exception {
-		this.spring.register(CustomExpressionRootConfig.class, WildcardController.class).autowire();
-
-		this.mvc.perform(get("/deny").with(user("user").roles("USER"))).andExpect(status().isForbidden());
-	}
-
 	@EnableWebSecurity
 	static class CustomExpressionRootConfig extends WebSecurityConfigurerAdapter {
 
@@ -837,14 +891,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 
 	}
 
-	// SEC-3011
-	@Test
-	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnAccessDecisionManager() {
-		this.spring.register(Sec3011Config.class).autowire();
-
-		verify(Sec3011Config.objectPostProcessor).postProcess(any(AccessDecisionManager.class));
-	}
-
 	@EnableWebSecurity
 	static class Sec3011Config extends WebSecurityConfigurerAdapter {
 
@@ -874,38 +920,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenRegisteringPermissionEvaluatorAndPermissionWithIdAndTypeMatchesThenRespondsWithOk()
-			throws Exception {
-		this.spring.register(PermissionEvaluatorConfig.class, WildcardController.class).autowire();
-
-		this.mvc.perform(get("/allow")).andExpect(status().isOk());
-	}
-
-	@Test
-	public void getWhenRegisteringPermissionEvaluatorAndPermissionWithIdAndTypeDoesNotMatchThenRespondsWithForbidden()
-			throws Exception {
-		this.spring.register(PermissionEvaluatorConfig.class, WildcardController.class).autowire();
-
-		this.mvc.perform(get("/deny")).andExpect(status().isForbidden());
-	}
-
-	@Test
-	public void getWhenRegisteringPermissionEvaluatorAndPermissionWithObjectMatchesThenRespondsWithOk()
-			throws Exception {
-		this.spring.register(PermissionEvaluatorConfig.class, WildcardController.class).autowire();
-
-		this.mvc.perform(get("/allowObject")).andExpect(status().isOk());
-	}
-
-	@Test
-	public void getWhenRegisteringPermissionEvaluatorAndPermissionWithObjectDoesNotMatchThenRespondsWithForbidden()
-			throws Exception {
-		this.spring.register(PermissionEvaluatorConfig.class, WildcardController.class).autowire();
-
-		this.mvc.perform(get("/denyObject")).andExpect(status().isForbidden());
-	}
-
 	@EnableWebSecurity
 	static class PermissionEvaluatorConfig extends WebSecurityConfigurerAdapter {
 
@@ -941,20 +955,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenRegisteringRoleHierarchyAndRelatedRoleAllowedThenRespondsWithOk() throws Exception {
-		this.spring.register(RoleHierarchyConfig.class, WildcardController.class).autowire();
-
-		this.mvc.perform(get("/allow").with(user("user").roles("USER"))).andExpect(status().isOk());
-	}
-
-	@Test
-	public void getWhenRegisteringRoleHierarchyAndNoRelatedRolesAllowedThenRespondsWithForbidden() throws Exception {
-		this.spring.register(RoleHierarchyConfig.class, WildcardController.class).autowire();
-
-		this.mvc.perform(get("/deny").with(user("user").roles("USER"))).andExpect(status().isForbidden());
-	}
-
 	@EnableWebSecurity
 	static class RoleHierarchyConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurerTests.java
index 7d3592b5a5..d3aff8f656 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurerTests.java
@@ -77,23 +77,6 @@ public class FormLoginConfigurerTests {
 		verify(config.requestCache).getRequest(any(), any());
 	}
 
-	@EnableWebSecurity
-	static class RequestCacheConfig extends WebSecurityConfigurerAdapter {
-
-		private RequestCache requestCache = mock(RequestCache.class);
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.formLogin().and()
-				.requestCache()
-					.requestCache(this.requestCache);
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void requestCacheAsBean() throws Exception {
 		this.spring.register(RequestCacheBeanConfig.class, AuthenticationTestConfiguration.class).autowire();
@@ -105,16 +88,6 @@ public class FormLoginConfigurerTests {
 		verify(requestCache).getRequest(any(), any());
 	}
 
-	@EnableWebSecurity
-	static class RequestCacheBeanConfig {
-
-		@Bean
-		RequestCache requestCache() {
-			return mock(RequestCache.class);
-		}
-
-	}
-
 	@Test
 	public void loginWhenFormLoginConfiguredThenHasDefaultUsernameAndPasswordParameterNames() throws Exception {
 		this.spring.register(FormLoginConfig.class).autowire();
@@ -160,41 +133,6 @@ public class FormLoginConfigurerTests {
 				.andExpect(redirectedUrl("http://localhost/login"));
 	}
 
-	@EnableWebSecurity
-	static class FormLoginConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		public void configure(WebSecurity web) {
-			// @formatter:off
-			web
-				.ignoring()
-					.antMatchers("/resources/**");
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.anyRequest().hasRole("USER")
-					.and()
-				.formLogin()
-					.loginPage("/login");
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-			// @formatter:off
-			auth
-				.inMemoryAuthentication()
-					.withUser(PasswordEncodedUser.user());
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void loginWhenFormLoginDefaultsInLambdaThenHasDefaultUsernameAndPasswordParameterNames() throws Exception {
 		this.spring.register(FormLoginInLambdaConfig.class).autowire();
@@ -240,32 +178,6 @@ public class FormLoginConfigurerTests {
 				.andExpect(redirectedUrl("http://localhost/login"));
 	}
 
-	@EnableWebSecurity
-	static class FormLoginInLambdaConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests(authorizeRequests ->
-					authorizeRequests
-						.anyRequest().hasRole("USER")
-				)
-				.formLogin(withDefaults());
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-			// @formatter:off
-			auth
-				.inMemoryAuthentication()
-					.withUser(PasswordEncodedUser.user());
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getLoginPageWhenFormLoginPermitAllThenPermittedAndNoRedirect() throws Exception {
 		this.spring.register(FormLoginConfigPermitAll.class).autowire();
@@ -288,23 +200,6 @@ public class FormLoginConfigurerTests {
 				.andExpect(redirectedUrl("/login?error"));
 	}
 
-	@EnableWebSecurity
-	static class FormLoginConfigPermitAll extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.anyRequest().hasRole("USER")
-					.and()
-				.formLogin()
-					.permitAll();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getLoginPageWhenCustomLoginPageThenPermittedAndNoRedirect() throws Exception {
 		this.spring.register(FormLoginDefaultsConfig.class).autowire();
@@ -341,6 +236,198 @@ public class FormLoginConfigurerTests {
 		this.mockMvc.perform(get("/authenticate?logout")).andExpect(redirectedUrl(null));
 	}
 
+	@Test
+	public void getLoginPageWhenCustomLoginPageInLambdaThenPermittedAndNoRedirect() throws Exception {
+		this.spring.register(FormLoginDefaultsInLambdaConfig.class).autowire();
+
+		this.mockMvc.perform(get("/authenticate")).andExpect(redirectedUrl(null));
+	}
+
+	@Test
+	public void loginWhenCustomLoginProcessingUrlThenRedirectsToHome() throws Exception {
+		this.spring.register(FormLoginLoginProcessingUrlConfig.class).autowire();
+
+		this.mockMvc.perform(formLogin("/loginCheck")).andExpect(status().isFound()).andExpect(redirectedUrl("/"));
+	}
+
+	@Test
+	public void loginWhenCustomLoginProcessingUrlInLambdaThenRedirectsToHome() throws Exception {
+		this.spring.register(FormLoginLoginProcessingUrlInLambdaConfig.class).autowire();
+
+		this.mockMvc.perform(formLogin("/loginCheck")).andExpect(status().isFound()).andExpect(redirectedUrl("/"));
+	}
+
+	@Test
+	public void requestWhenCustomPortMapperThenPortMapperUsed() throws Exception {
+		FormLoginUsesPortMapperConfig.PORT_MAPPER = mock(PortMapper.class);
+		when(FormLoginUsesPortMapperConfig.PORT_MAPPER.lookupHttpsPort(any())).thenReturn(9443);
+		this.spring.register(FormLoginUsesPortMapperConfig.class).autowire();
+
+		this.mockMvc.perform(get("http://localhost:9090")).andExpect(status().isFound())
+				.andExpect(redirectedUrl("https://localhost:9443/login"));
+
+		verify(FormLoginUsesPortMapperConfig.PORT_MAPPER).lookupHttpsPort(any());
+	}
+
+	@Test
+	public void failureUrlWhenPermitAllAndFailureHandlerThenSecured() throws Exception {
+		this.spring.register(PermitAllIgnoresFailureHandlerConfig.class).autowire();
+
+		this.mockMvc.perform(get("/login?error")).andExpect(status().isFound())
+				.andExpect(redirectedUrl("http://localhost/login"));
+	}
+
+	@Test
+	public void formLoginWhenInvokedTwiceThenUsesOriginalUsernameParameter() throws Exception {
+		this.spring.register(DuplicateInvocationsDoesNotOverrideConfig.class).autowire();
+
+		this.mockMvc.perform(formLogin().user("custom-username", "user")).andExpect(authenticated());
+	}
+
+	@Test
+	public void loginWhenInvalidLoginAndFailureForwardUrlThenForwardsToFailureForwardUrl() throws Exception {
+		this.spring.register(FormLoginUserForwardAuthenticationSuccessAndFailureConfig.class).autowire();
+
+		this.mockMvc.perform(formLogin().user("invalid")).andExpect(forwardedUrl("/failure_forward_url"));
+	}
+
+	@Test
+	public void loginWhenSuccessForwardUrlThenForwardsToSuccessForwardUrl() throws Exception {
+		this.spring.register(FormLoginUserForwardAuthenticationSuccessAndFailureConfig.class).autowire();
+
+		this.mockMvc.perform(formLogin()).andExpect(forwardedUrl("/success_forward_url"));
+	}
+
+	@Test
+	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnUsernamePasswordAuthenticationFilter() {
+		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
+		this.spring.register(ObjectPostProcessorConfig.class).autowire();
+
+		verify(ObjectPostProcessorConfig.objectPostProcessor)
+				.postProcess(any(UsernamePasswordAuthenticationFilter.class));
+	}
+
+	@Test
+	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnLoginUrlAuthenticationEntryPoint() {
+		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
+		this.spring.register(ObjectPostProcessorConfig.class).autowire();
+
+		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(LoginUrlAuthenticationEntryPoint.class));
+	}
+
+	@Test
+	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnExceptionTranslationFilter() {
+		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
+		this.spring.register(ObjectPostProcessorConfig.class).autowire();
+
+		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(ExceptionTranslationFilter.class));
+	}
+
+	@EnableWebSecurity
+	static class RequestCacheConfig extends WebSecurityConfigurerAdapter {
+
+		private RequestCache requestCache = mock(RequestCache.class);
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.formLogin().and()
+				.requestCache()
+					.requestCache(this.requestCache);
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class RequestCacheBeanConfig {
+
+		@Bean
+		RequestCache requestCache() {
+			return mock(RequestCache.class);
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class FormLoginConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		public void configure(WebSecurity web) {
+			// @formatter:off
+			web
+				.ignoring()
+					.antMatchers("/resources/**");
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin()
+					.loginPage("/login");
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication()
+					.withUser(PasswordEncodedUser.user());
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class FormLoginInLambdaConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests(authorizeRequests ->
+					authorizeRequests
+						.anyRequest().hasRole("USER")
+				)
+				.formLogin(withDefaults());
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication()
+					.withUser(PasswordEncodedUser.user());
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class FormLoginConfigPermitAll extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin()
+					.permitAll();
+			// @formatter:on
+		}
+
+	}
+
 	@EnableWebSecurity
 	static class FormLoginDefaultsConfig extends WebSecurityConfigurerAdapter {
 
@@ -362,13 +449,6 @@ public class FormLoginConfigurerTests {
 
 	}
 
-	@Test
-	public void getLoginPageWhenCustomLoginPageInLambdaThenPermittedAndNoRedirect() throws Exception {
-		this.spring.register(FormLoginDefaultsInLambdaConfig.class).autowire();
-
-		this.mockMvc.perform(get("/authenticate")).andExpect(redirectedUrl(null));
-	}
-
 	@EnableWebSecurity
 	static class FormLoginDefaultsInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -391,13 +471,6 @@ public class FormLoginConfigurerTests {
 
 	}
 
-	@Test
-	public void loginWhenCustomLoginProcessingUrlThenRedirectsToHome() throws Exception {
-		this.spring.register(FormLoginLoginProcessingUrlConfig.class).autowire();
-
-		this.mockMvc.perform(formLogin("/loginCheck")).andExpect(status().isFound()).andExpect(redirectedUrl("/"));
-	}
-
 	@EnableWebSecurity
 	static class FormLoginLoginProcessingUrlConfig extends WebSecurityConfigurerAdapter {
 
@@ -434,13 +507,6 @@ public class FormLoginConfigurerTests {
 
 	}
 
-	@Test
-	public void loginWhenCustomLoginProcessingUrlInLambdaThenRedirectsToHome() throws Exception {
-		this.spring.register(FormLoginLoginProcessingUrlInLambdaConfig.class).autowire();
-
-		this.mockMvc.perform(formLogin("/loginCheck")).andExpect(status().isFound()).andExpect(redirectedUrl("/"));
-	}
-
 	@EnableWebSecurity
 	static class FormLoginLoginProcessingUrlInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -479,18 +545,6 @@ public class FormLoginConfigurerTests {
 
 	}
 
-	@Test
-	public void requestWhenCustomPortMapperThenPortMapperUsed() throws Exception {
-		FormLoginUsesPortMapperConfig.PORT_MAPPER = mock(PortMapper.class);
-		when(FormLoginUsesPortMapperConfig.PORT_MAPPER.lookupHttpsPort(any())).thenReturn(9443);
-		this.spring.register(FormLoginUsesPortMapperConfig.class).autowire();
-
-		this.mockMvc.perform(get("http://localhost:9090")).andExpect(status().isFound())
-				.andExpect(redirectedUrl("https://localhost:9443/login"));
-
-		verify(FormLoginUsesPortMapperConfig.PORT_MAPPER).lookupHttpsPort(any());
-	}
-
 	@EnableWebSecurity
 	static class FormLoginUsesPortMapperConfig extends WebSecurityConfigurerAdapter {
 
@@ -516,14 +570,6 @@ public class FormLoginConfigurerTests {
 
 	}
 
-	@Test
-	public void failureUrlWhenPermitAllAndFailureHandlerThenSecured() throws Exception {
-		this.spring.register(PermitAllIgnoresFailureHandlerConfig.class).autowire();
-
-		this.mockMvc.perform(get("/login?error")).andExpect(status().isFound())
-				.andExpect(redirectedUrl("http://localhost/login"));
-	}
-
 	@EnableWebSecurity
 	static class PermitAllIgnoresFailureHandlerConfig extends WebSecurityConfigurerAdapter {
 
@@ -544,13 +590,6 @@ public class FormLoginConfigurerTests {
 
 	}
 
-	@Test
-	public void formLoginWhenInvokedTwiceThenUsesOriginalUsernameParameter() throws Exception {
-		this.spring.register(DuplicateInvocationsDoesNotOverrideConfig.class).autowire();
-
-		this.mockMvc.perform(formLogin().user("custom-username", "user")).andExpect(authenticated());
-	}
-
 	@EnableWebSecurity
 	static class DuplicateInvocationsDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
 
@@ -576,20 +615,6 @@ public class FormLoginConfigurerTests {
 
 	}
 
-	@Test
-	public void loginWhenInvalidLoginAndFailureForwardUrlThenForwardsToFailureForwardUrl() throws Exception {
-		this.spring.register(FormLoginUserForwardAuthenticationSuccessAndFailureConfig.class).autowire();
-
-		this.mockMvc.perform(formLogin().user("invalid")).andExpect(forwardedUrl("/failure_forward_url"));
-	}
-
-	@Test
-	public void loginWhenSuccessForwardUrlThenForwardsToSuccessForwardUrl() throws Exception {
-		this.spring.register(FormLoginUserForwardAuthenticationSuccessAndFailureConfig.class).autowire();
-
-		this.mockMvc.perform(formLogin()).andExpect(forwardedUrl("/success_forward_url"));
-	}
-
 	@EnableWebSecurity
 	static class FormLoginUserForwardAuthenticationSuccessAndFailureConfig extends WebSecurityConfigurerAdapter {
 
@@ -620,31 +645,6 @@ public class FormLoginConfigurerTests {
 
 	}
 
-	@Test
-	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnUsernamePasswordAuthenticationFilter() {
-		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
-		this.spring.register(ObjectPostProcessorConfig.class).autowire();
-
-		verify(ObjectPostProcessorConfig.objectPostProcessor)
-				.postProcess(any(UsernamePasswordAuthenticationFilter.class));
-	}
-
-	@Test
-	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnLoginUrlAuthenticationEntryPoint() {
-		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
-		this.spring.register(ObjectPostProcessorConfig.class).autowire();
-
-		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(LoginUrlAuthenticationEntryPoint.class));
-	}
-
-	@Test
-	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnExceptionTranslationFilter() {
-		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
-		this.spring.register(ObjectPostProcessorConfig.class).autowire();
-
-		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(ExceptionTranslationFilter.class));
-	}
-
 	@EnableWebSecurity
 	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerEagerHeadersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerEagerHeadersTests.java
index 908c61fecd..0586a75bac 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerEagerHeadersTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerEagerHeadersTests.java
@@ -47,6 +47,18 @@ public class HeadersConfigurerEagerHeadersTests {
 	@Autowired
 	MockMvc mvc;
 
+	@Test
+	public void requestWhenHeadersEagerlyConfiguredThenHeadersAreWritten() throws Exception {
+		this.spring.register(HeadersAtTheBeginningOfRequestConfig.class).autowire();
+
+		this.mvc.perform(get("/").secure(true)).andExpect(header().string("X-Content-Type-Options", "nosniff"))
+				.andExpect(header().string("X-Frame-Options", "DENY"))
+				.andExpect(header().string("Strict-Transport-Security", "max-age=31536000 ; includeSubDomains"))
+				.andExpect(header().string(CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate"))
+				.andExpect(header().string(EXPIRES, "0")).andExpect(header().string(PRAGMA, "no-cache"))
+				.andExpect(header().string("X-XSS-Protection", "1; mode=block"));
+	}
+
 	@EnableWebSecurity
 	public static class HeadersAtTheBeginningOfRequestConfig extends WebSecurityConfigurerAdapter {
 
@@ -65,16 +77,4 @@ public class HeadersConfigurerEagerHeadersTests {
 
 	}
 
-	@Test
-	public void requestWhenHeadersEagerlyConfiguredThenHeadersAreWritten() throws Exception {
-		this.spring.register(HeadersAtTheBeginningOfRequestConfig.class).autowire();
-
-		this.mvc.perform(get("/").secure(true)).andExpect(header().string("X-Content-Type-Options", "nosniff"))
-				.andExpect(header().string("X-Frame-Options", "DENY"))
-				.andExpect(header().string("Strict-Transport-Security", "max-age=31536000 ; includeSubDomains"))
-				.andExpect(header().string(CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate"))
-				.andExpect(header().string(EXPIRES, "0")).andExpect(header().string(PRAGMA, "no-cache"))
-				.andExpect(header().string("X-XSS-Protection", "1; mode=block"));
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerTests.java
index b5e0df70fe..275f89c498 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerTests.java
@@ -77,19 +77,6 @@ public class HeadersConfigurerTests {
 				HttpHeaders.CACHE_CONTROL, HttpHeaders.EXPIRES, HttpHeaders.PRAGMA, HttpHeaders.X_XSS_PROTECTION);
 	}
 
-	@EnableWebSecurity
-	static class HeadersConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenHeadersConfiguredInLambdaThenDefaultHeadersInResponse() throws Exception {
 		this.spring.register(HeadersInLambdaConfig.class).autowire();
@@ -108,19 +95,6 @@ public class HeadersConfigurerTests {
 				HttpHeaders.CACHE_CONTROL, HttpHeaders.EXPIRES, HttpHeaders.PRAGMA, HttpHeaders.X_XSS_PROTECTION);
 	}
 
-	@EnableWebSecurity
-	static class HeadersInLambdaConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers(withDefaults());
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenHeaderDefaultsDisabledAndContentTypeConfiguredThenOnlyContentTypeHeaderInResponse()
 			throws Exception {
@@ -131,21 +105,6 @@ public class HeadersConfigurerTests {
 		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_CONTENT_TYPE_OPTIONS);
 	}
 
-	@EnableWebSecurity
-	static class ContentTypeOptionsConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers()
-					.defaultsDisabled()
-					.contentTypeOptions();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenOnlyContentTypeConfiguredInLambdaThenOnlyContentTypeHeaderInResponse() throws Exception {
 		this.spring.register(ContentTypeOptionsInLambdaConfig.class).autowire();
@@ -155,23 +114,6 @@ public class HeadersConfigurerTests {
 		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_CONTENT_TYPE_OPTIONS);
 	}
 
-	@EnableWebSecurity
-	static class ContentTypeOptionsInLambdaConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers(headers ->
-					headers
-						.defaultsDisabled()
-						.contentTypeOptions(withDefaults())
-				);
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenHeaderDefaultsDisabledAndFrameOptionsConfiguredThenOnlyFrameOptionsHeaderInResponse()
 			throws Exception {
@@ -182,21 +124,6 @@ public class HeadersConfigurerTests {
 		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_FRAME_OPTIONS);
 	}
 
-	@EnableWebSecurity
-	static class FrameOptionsConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers()
-					.defaultsDisabled()
-					.frameOptions();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenHeaderDefaultsDisabledAndHstsConfiguredThenOnlyStrictTransportSecurityHeaderInResponse()
 			throws Exception {
@@ -209,21 +136,6 @@ public class HeadersConfigurerTests {
 		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.STRICT_TRANSPORT_SECURITY);
 	}
 
-	@EnableWebSecurity
-	static class HstsConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers()
-					.defaultsDisabled()
-					.httpStrictTransportSecurity();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenHeaderDefaultsDisabledAndCacheControlConfiguredThenCacheControlAndExpiresAndPragmaHeadersInResponse()
 			throws Exception {
@@ -237,21 +149,6 @@ public class HeadersConfigurerTests {
 				HttpHeaders.EXPIRES, HttpHeaders.PRAGMA);
 	}
 
-	@EnableWebSecurity
-	static class CacheControlConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers()
-					.defaultsDisabled()
-					.cacheControl();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenOnlyCacheControlConfiguredInLambdaThenCacheControlAndExpiresAndPragmaHeadersInResponse()
 			throws Exception {
@@ -265,23 +162,6 @@ public class HeadersConfigurerTests {
 				HttpHeaders.EXPIRES, HttpHeaders.PRAGMA);
 	}
 
-	@EnableWebSecurity
-	static class CacheControlInLambdaConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers(headers ->
-					headers
-						.defaultsDisabled()
-						.cacheControl(withDefaults())
-				);
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenHeaderDefaultsDisabledAndXssProtectionConfiguredThenOnlyXssProtectionHeaderInResponse()
 			throws Exception {
@@ -292,21 +172,6 @@ public class HeadersConfigurerTests {
 		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_XSS_PROTECTION);
 	}
 
-	@EnableWebSecurity
-	static class XssProtectionConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers()
-					.defaultsDisabled()
-					.xssProtection();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenOnlyXssProtectionConfiguredInLambdaThenOnlyXssProtectionHeaderInResponse() throws Exception {
 		this.spring.register(XssProtectionInLambdaConfig.class).autowire();
@@ -316,23 +181,6 @@ public class HeadersConfigurerTests {
 		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_XSS_PROTECTION);
 	}
 
-	@EnableWebSecurity
-	static class XssProtectionInLambdaConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers(headers ->
-					headers
-						.defaultsDisabled()
-						.xssProtection(withDefaults())
-				);
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenFrameOptionsSameOriginConfiguredThenFrameOptionsHeaderHasValueSameOrigin() throws Exception {
 		this.spring.register(HeadersCustomSameOriginConfig.class).autowire();
@@ -342,20 +190,6 @@ public class HeadersConfigurerTests {
 				.andReturn();
 	}
 
-	@EnableWebSecurity
-	static class HeadersCustomSameOriginConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers()
-					.frameOptions().sameOrigin();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenFrameOptionsSameOriginConfiguredInLambdaThenFrameOptionsHeaderHasValueSameOrigin()
 			throws Exception {
@@ -366,22 +200,6 @@ public class HeadersConfigurerTests {
 				.andReturn();
 	}
 
-	@EnableWebSecurity
-	static class HeadersCustomSameOriginInLambdaConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers(headers ->
-					headers
-						.frameOptions(frameOptionsConfig -> frameOptionsConfig.sameOrigin())
-				);
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenHeaderDefaultsDisabledAndPublicHpkpWithNoPinThenNoHeadersInResponse() throws Exception {
 		this.spring.register(HpkpConfigNoPins.class).autowire();
@@ -390,21 +208,6 @@ public class HeadersConfigurerTests {
 		assertThat(mvcResult.getResponse().getHeaderNames()).isEmpty();
 	}
 
-	@EnableWebSecurity
-	static class HpkpConfigNoPins extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers()
-					.defaultsDisabled()
-					.httpPublicKeyPinning();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenSecureRequestAndHpkpWithPinThenPublicKeyPinsReportOnlyHeaderInResponse() throws Exception {
 		this.spring.register(HpkpConfig.class).autowire();
@@ -424,6 +227,414 @@ public class HeadersConfigurerTests {
 		assertThat(mvcResult.getResponse().getHeaderNames()).isEmpty();
 	}
 
+	@Test
+	public void getWhenHpkpWithMultiplePinsThenPublicKeyPinsReportOnlyHeaderWithMultiplePinsInResponse()
+			throws Exception {
+		this.spring.register(HpkpConfigWithPins.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header().string(
+				HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY,
+				"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; pin-sha256=\"E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=\""))
+				.andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY);
+	}
+
+	@Test
+	public void getWhenHpkpWithCustomAgeThenPublicKeyPinsReportOnlyHeaderWithCustomAgeInResponse() throws Exception {
+		this.spring.register(HpkpConfigCustomAge.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
+				.andExpect(header().string(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY,
+						"max-age=604800 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\""))
+				.andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY);
+	}
+
+	@Test
+	public void getWhenHpkpWithReportOnlyFalseThenPublicKeyPinsHeaderInResponse() throws Exception {
+		this.spring.register(HpkpConfigTerminateConnection.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
+				.andExpect(header().string(HttpHeaders.PUBLIC_KEY_PINS,
+						"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\""))
+				.andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS);
+	}
+
+	@Test
+	public void getWhenHpkpIncludeSubdomainThenPublicKeyPinsReportOnlyHeaderWithIncludeSubDomainsInResponse()
+			throws Exception {
+		this.spring.register(HpkpConfigIncludeSubDomains.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header().string(
+				HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY,
+				"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; includeSubDomains"))
+				.andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY);
+	}
+
+	@Test
+	public void getWhenHpkpWithReportUriThenPublicKeyPinsReportOnlyHeaderWithReportUriInResponse() throws Exception {
+		this.spring.register(HpkpConfigWithReportURI.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header().string(
+				HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY,
+				"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; report-uri=\"https://example.net/pkp-report\""))
+				.andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY);
+	}
+
+	@Test
+	public void getWhenHpkpWithReportUriAsStringThenPublicKeyPinsReportOnlyHeaderWithReportUriInResponse()
+			throws Exception {
+		this.spring.register(HpkpConfigWithReportURIAsString.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header().string(
+				HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY,
+				"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; report-uri=\"https://example.net/pkp-report\""))
+				.andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY);
+	}
+
+	@Test
+	public void getWhenHpkpWithReportUriInLambdaThenPublicKeyPinsReportOnlyHeaderWithReportUriInResponse()
+			throws Exception {
+		this.spring.register(HpkpWithReportUriInLambdaConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header().string(
+				HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY,
+				"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; report-uri=\"https://example.net/pkp-report\""))
+				.andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY);
+	}
+
+	@Test
+	public void getWhenContentSecurityPolicyConfiguredThenContentSecurityPolicyHeaderInResponse() throws Exception {
+		this.spring.register(ContentSecurityPolicyDefaultConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
+				.andExpect(header().string(HttpHeaders.CONTENT_SECURITY_POLICY, "default-src 'self'")).andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.CONTENT_SECURITY_POLICY);
+	}
+
+	@Test
+	public void getWhenContentSecurityPolicyWithReportOnlyThenContentSecurityPolicyReportOnlyHeaderInResponse()
+			throws Exception {
+		this.spring.register(ContentSecurityPolicyReportOnlyConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
+				.andExpect(header().string(HttpHeaders.CONTENT_SECURITY_POLICY_REPORT_ONLY,
+						"default-src 'self'; script-src trustedscripts.example.com"))
+				.andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames())
+				.containsExactly(HttpHeaders.CONTENT_SECURITY_POLICY_REPORT_ONLY);
+	}
+
+	@Test
+	public void getWhenContentSecurityPolicyWithReportOnlyInLambdaThenContentSecurityPolicyReportOnlyHeaderInResponse()
+			throws Exception {
+		this.spring.register(ContentSecurityPolicyReportOnlyInLambdaConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
+				.andExpect(header().string(HttpHeaders.CONTENT_SECURITY_POLICY_REPORT_ONLY,
+						"default-src 'self'; script-src trustedscripts.example.com"))
+				.andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames())
+				.containsExactly(HttpHeaders.CONTENT_SECURITY_POLICY_REPORT_ONLY);
+	}
+
+	@Test
+	public void configureWhenContentSecurityPolicyEmptyThenException() {
+		assertThatThrownBy(() -> this.spring.register(ContentSecurityPolicyInvalidConfig.class).autowire())
+				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
+	}
+
+	@Test
+	public void configureWhenContentSecurityPolicyEmptyInLambdaThenException() {
+		assertThatThrownBy(() -> this.spring.register(ContentSecurityPolicyInvalidInLambdaConfig.class).autowire())
+				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
+	}
+
+	@Test
+	public void configureWhenContentSecurityPolicyNoPolicyDirectivesInLambdaThenDefaultHeaderValue() throws Exception {
+		this.spring.register(ContentSecurityPolicyNoDirectivesInLambdaConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
+				.andExpect(header().string(HttpHeaders.CONTENT_SECURITY_POLICY, "default-src 'self'")).andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.CONTENT_SECURITY_POLICY);
+	}
+
+	@Test
+	public void getWhenReferrerPolicyConfiguredThenReferrerPolicyHeaderInResponse() throws Exception {
+		this.spring.register(ReferrerPolicyDefaultConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
+				.andExpect(header().string("Referrer-Policy", ReferrerPolicy.NO_REFERRER.getPolicy())).andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly("Referrer-Policy");
+	}
+
+	@Test
+	public void getWhenReferrerPolicyInLambdaThenReferrerPolicyHeaderInResponse() throws Exception {
+		this.spring.register(ReferrerPolicyDefaultInLambdaConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
+				.andExpect(header().string("Referrer-Policy", ReferrerPolicy.NO_REFERRER.getPolicy())).andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly("Referrer-Policy");
+	}
+
+	@Test
+	public void getWhenReferrerPolicyConfiguredWithCustomValueThenReferrerPolicyHeaderWithCustomValueInResponse()
+			throws Exception {
+		this.spring.register(ReferrerPolicyCustomConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
+				.andExpect(header().string("Referrer-Policy", ReferrerPolicy.SAME_ORIGIN.getPolicy())).andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly("Referrer-Policy");
+	}
+
+	@Test
+	public void getWhenReferrerPolicyConfiguredWithCustomValueInLambdaThenCustomValueInResponse() throws Exception {
+		this.spring.register(ReferrerPolicyCustomInLambdaConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
+				.andExpect(header().string("Referrer-Policy", ReferrerPolicy.SAME_ORIGIN.getPolicy())).andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly("Referrer-Policy");
+	}
+
+	@Test
+	public void getWhenFeaturePolicyConfiguredThenFeaturePolicyHeaderInResponse() throws Exception {
+		this.spring.register(FeaturePolicyConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
+				.andExpect(header().string("Feature-Policy", "geolocation 'self'")).andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly("Feature-Policy");
+	}
+
+	@Test
+	public void configureWhenFeaturePolicyEmptyThenException() {
+		assertThatThrownBy(() -> this.spring.register(FeaturePolicyInvalidConfig.class).autowire())
+				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
+	}
+
+	@Test
+	public void getWhenHstsConfiguredWithPreloadThenStrictTransportSecurityHeaderWithPreloadInResponse()
+			throws Exception {
+		this.spring.register(HstsWithPreloadConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header()
+				.string(HttpHeaders.STRICT_TRANSPORT_SECURITY, "max-age=31536000 ; includeSubDomains ; preload"))
+				.andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.STRICT_TRANSPORT_SECURITY);
+	}
+
+	@Test
+	public void getWhenHstsConfiguredWithPreloadInLambdaThenStrictTransportSecurityHeaderWithPreloadInResponse()
+			throws Exception {
+		this.spring.register(HstsWithPreloadInLambdaConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header()
+				.string(HttpHeaders.STRICT_TRANSPORT_SECURITY, "max-age=31536000 ; includeSubDomains ; preload"))
+				.andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.STRICT_TRANSPORT_SECURITY);
+	}
+
+	@EnableWebSecurity
+	static class HeadersConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class HeadersInLambdaConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers(withDefaults());
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class ContentTypeOptionsConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers()
+					.defaultsDisabled()
+					.contentTypeOptions();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class ContentTypeOptionsInLambdaConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers(headers ->
+					headers
+						.defaultsDisabled()
+						.contentTypeOptions(withDefaults())
+				);
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class FrameOptionsConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers()
+					.defaultsDisabled()
+					.frameOptions();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class HstsConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers()
+					.defaultsDisabled()
+					.httpStrictTransportSecurity();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class CacheControlConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers()
+					.defaultsDisabled()
+					.cacheControl();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class CacheControlInLambdaConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers(headers ->
+					headers
+						.defaultsDisabled()
+						.cacheControl(withDefaults())
+				);
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class XssProtectionConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers()
+					.defaultsDisabled()
+					.xssProtection();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class XssProtectionInLambdaConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers(headers ->
+					headers
+						.defaultsDisabled()
+						.xssProtection(withDefaults())
+				);
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class HeadersCustomSameOriginConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers()
+					.frameOptions().sameOrigin();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class HeadersCustomSameOriginInLambdaConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers(headers ->
+					headers
+						.frameOptions(frameOptionsConfig -> frameOptionsConfig.sameOrigin())
+				);
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class HpkpConfigNoPins extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers()
+					.defaultsDisabled()
+					.httpPublicKeyPinning();
+			// @formatter:on
+		}
+
+	}
+
 	@EnableWebSecurity
 	static class HpkpConfig extends WebSecurityConfigurerAdapter {
 
@@ -440,18 +651,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenHpkpWithMultiplePinsThenPublicKeyPinsReportOnlyHeaderWithMultiplePinsInResponse()
-			throws Exception {
-		this.spring.register(HpkpConfigWithPins.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header().string(
-				HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY,
-				"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; pin-sha256=\"E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=\""))
-				.andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY);
-	}
-
 	@EnableWebSecurity
 	static class HpkpConfigWithPins extends WebSecurityConfigurerAdapter {
 
@@ -472,17 +671,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenHpkpWithCustomAgeThenPublicKeyPinsReportOnlyHeaderWithCustomAgeInResponse() throws Exception {
-		this.spring.register(HpkpConfigCustomAge.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
-				.andExpect(header().string(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY,
-						"max-age=604800 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\""))
-				.andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY);
-	}
-
 	@EnableWebSecurity
 	static class HpkpConfigCustomAge extends WebSecurityConfigurerAdapter {
 
@@ -500,17 +688,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenHpkpWithReportOnlyFalseThenPublicKeyPinsHeaderInResponse() throws Exception {
-		this.spring.register(HpkpConfigTerminateConnection.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
-				.andExpect(header().string(HttpHeaders.PUBLIC_KEY_PINS,
-						"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\""))
-				.andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS);
-	}
-
 	@EnableWebSecurity
 	static class HpkpConfigTerminateConnection extends WebSecurityConfigurerAdapter {
 
@@ -528,18 +705,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenHpkpIncludeSubdomainThenPublicKeyPinsReportOnlyHeaderWithIncludeSubDomainsInResponse()
-			throws Exception {
-		this.spring.register(HpkpConfigIncludeSubDomains.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header().string(
-				HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY,
-				"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; includeSubDomains"))
-				.andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY);
-	}
-
 	@EnableWebSecurity
 	static class HpkpConfigIncludeSubDomains extends WebSecurityConfigurerAdapter {
 
@@ -557,17 +722,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenHpkpWithReportUriThenPublicKeyPinsReportOnlyHeaderWithReportUriInResponse() throws Exception {
-		this.spring.register(HpkpConfigWithReportURI.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header().string(
-				HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY,
-				"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; report-uri=\"https://example.net/pkp-report\""))
-				.andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY);
-	}
-
 	@EnableWebSecurity
 	static class HpkpConfigWithReportURI extends WebSecurityConfigurerAdapter {
 
@@ -585,18 +739,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenHpkpWithReportUriAsStringThenPublicKeyPinsReportOnlyHeaderWithReportUriInResponse()
-			throws Exception {
-		this.spring.register(HpkpConfigWithReportURIAsString.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header().string(
-				HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY,
-				"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; report-uri=\"https://example.net/pkp-report\""))
-				.andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY);
-	}
-
 	@EnableWebSecurity
 	static class HpkpConfigWithReportURIAsString extends WebSecurityConfigurerAdapter {
 
@@ -614,18 +756,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenHpkpWithReportUriInLambdaThenPublicKeyPinsReportOnlyHeaderWithReportUriInResponse()
-			throws Exception {
-		this.spring.register(HpkpWithReportUriInLambdaConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header().string(
-				HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY,
-				"max-age=5184000 ; pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\" ; report-uri=\"https://example.net/pkp-report\""))
-				.andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY);
-	}
-
 	@EnableWebSecurity
 	static class HpkpWithReportUriInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -647,15 +777,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenContentSecurityPolicyConfiguredThenContentSecurityPolicyHeaderInResponse() throws Exception {
-		this.spring.register(ContentSecurityPolicyDefaultConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
-				.andExpect(header().string(HttpHeaders.CONTENT_SECURITY_POLICY, "default-src 'self'")).andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.CONTENT_SECURITY_POLICY);
-	}
-
 	@EnableWebSecurity
 	static class ContentSecurityPolicyDefaultConfig extends WebSecurityConfigurerAdapter {
 
@@ -671,19 +792,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenContentSecurityPolicyWithReportOnlyThenContentSecurityPolicyReportOnlyHeaderInResponse()
-			throws Exception {
-		this.spring.register(ContentSecurityPolicyReportOnlyConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
-				.andExpect(header().string(HttpHeaders.CONTENT_SECURITY_POLICY_REPORT_ONLY,
-						"default-src 'self'; script-src trustedscripts.example.com"))
-				.andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames())
-				.containsExactly(HttpHeaders.CONTENT_SECURITY_POLICY_REPORT_ONLY);
-	}
-
 	@EnableWebSecurity
 	static class ContentSecurityPolicyReportOnlyConfig extends WebSecurityConfigurerAdapter {
 
@@ -700,19 +808,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenContentSecurityPolicyWithReportOnlyInLambdaThenContentSecurityPolicyReportOnlyHeaderInResponse()
-			throws Exception {
-		this.spring.register(ContentSecurityPolicyReportOnlyInLambdaConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
-				.andExpect(header().string(HttpHeaders.CONTENT_SECURITY_POLICY_REPORT_ONLY,
-						"default-src 'self'; script-src trustedscripts.example.com"))
-				.andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames())
-				.containsExactly(HttpHeaders.CONTENT_SECURITY_POLICY_REPORT_ONLY);
-	}
-
 	@EnableWebSecurity
 	static class ContentSecurityPolicyReportOnlyInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -734,12 +829,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void configureWhenContentSecurityPolicyEmptyThenException() {
-		assertThatThrownBy(() -> this.spring.register(ContentSecurityPolicyInvalidConfig.class).autowire())
-				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
-	}
-
 	@EnableWebSecurity
 	static class ContentSecurityPolicyInvalidConfig extends WebSecurityConfigurerAdapter {
 
@@ -755,12 +844,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void configureWhenContentSecurityPolicyEmptyInLambdaThenException() {
-		assertThatThrownBy(() -> this.spring.register(ContentSecurityPolicyInvalidInLambdaConfig.class).autowire())
-				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
-	}
-
 	@EnableWebSecurity
 	static class ContentSecurityPolicyInvalidInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -780,15 +863,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void configureWhenContentSecurityPolicyNoPolicyDirectivesInLambdaThenDefaultHeaderValue() throws Exception {
-		this.spring.register(ContentSecurityPolicyNoDirectivesInLambdaConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
-				.andExpect(header().string(HttpHeaders.CONTENT_SECURITY_POLICY, "default-src 'self'")).andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.CONTENT_SECURITY_POLICY);
-	}
-
 	@EnableWebSecurity
 	static class ContentSecurityPolicyNoDirectivesInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -806,15 +880,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenReferrerPolicyConfiguredThenReferrerPolicyHeaderInResponse() throws Exception {
-		this.spring.register(ReferrerPolicyDefaultConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
-				.andExpect(header().string("Referrer-Policy", ReferrerPolicy.NO_REFERRER.getPolicy())).andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly("Referrer-Policy");
-	}
-
 	@EnableWebSecurity
 	static class ReferrerPolicyDefaultConfig extends WebSecurityConfigurerAdapter {
 
@@ -830,15 +895,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenReferrerPolicyInLambdaThenReferrerPolicyHeaderInResponse() throws Exception {
-		this.spring.register(ReferrerPolicyDefaultInLambdaConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
-				.andExpect(header().string("Referrer-Policy", ReferrerPolicy.NO_REFERRER.getPolicy())).andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly("Referrer-Policy");
-	}
-
 	@EnableWebSecurity
 	static class ReferrerPolicyDefaultInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -856,16 +912,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenReferrerPolicyConfiguredWithCustomValueThenReferrerPolicyHeaderWithCustomValueInResponse()
-			throws Exception {
-		this.spring.register(ReferrerPolicyCustomConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
-				.andExpect(header().string("Referrer-Policy", ReferrerPolicy.SAME_ORIGIN.getPolicy())).andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly("Referrer-Policy");
-	}
-
 	@EnableWebSecurity
 	static class ReferrerPolicyCustomConfig extends WebSecurityConfigurerAdapter {
 
@@ -881,15 +927,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenReferrerPolicyConfiguredWithCustomValueInLambdaThenCustomValueInResponse() throws Exception {
-		this.spring.register(ReferrerPolicyCustomInLambdaConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
-				.andExpect(header().string("Referrer-Policy", ReferrerPolicy.SAME_ORIGIN.getPolicy())).andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly("Referrer-Policy");
-	}
-
 	@EnableWebSecurity
 	static class ReferrerPolicyCustomInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -909,15 +946,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenFeaturePolicyConfiguredThenFeaturePolicyHeaderInResponse() throws Exception {
-		this.spring.register(FeaturePolicyConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
-				.andExpect(header().string("Feature-Policy", "geolocation 'self'")).andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly("Feature-Policy");
-	}
-
 	@EnableWebSecurity
 	static class FeaturePolicyConfig extends WebSecurityConfigurerAdapter {
 
@@ -933,12 +961,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void configureWhenFeaturePolicyEmptyThenException() {
-		assertThatThrownBy(() -> this.spring.register(FeaturePolicyInvalidConfig.class).autowire())
-				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
-	}
-
 	@EnableWebSecurity
 	static class FeaturePolicyInvalidConfig extends WebSecurityConfigurerAdapter {
 
@@ -954,17 +976,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenHstsConfiguredWithPreloadThenStrictTransportSecurityHeaderWithPreloadInResponse()
-			throws Exception {
-		this.spring.register(HstsWithPreloadConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header()
-				.string(HttpHeaders.STRICT_TRANSPORT_SECURITY, "max-age=31536000 ; includeSubDomains ; preload"))
-				.andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.STRICT_TRANSPORT_SECURITY);
-	}
-
 	@EnableWebSecurity
 	static class HstsWithPreloadConfig extends WebSecurityConfigurerAdapter {
 
@@ -981,17 +992,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenHstsConfiguredWithPreloadInLambdaThenStrictTransportSecurityHeaderWithPreloadInResponse()
-			throws Exception {
-		this.spring.register(HstsWithPreloadInLambdaConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true)).andExpect(header()
-				.string(HttpHeaders.STRICT_TRANSPORT_SECURITY, "max-age=31536000 ; includeSubDomains ; preload"))
-				.andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.STRICT_TRANSPORT_SECURITY);
-	}
-
 	@EnableWebSecurity
 	static class HstsWithPreloadInLambdaConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurerTests.java
index c3649f7559..6353743976 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurerTests.java
@@ -71,6 +71,52 @@ public class HttpBasicConfigurerTests {
 		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(BasicAuthenticationFilter.class));
 	}
 
+	@Test
+	public void httpBasicWhenUsingDefaultsInLambdaThenResponseIncludesBasicChallenge() throws Exception {
+		this.spring.register(DefaultsLambdaEntryPointConfig.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(status().isUnauthorized())
+				.andExpect(header().string("WWW-Authenticate", "Basic realm=\"Realm\""));
+	}
+
+	// SEC-2198
+	@Test
+	public void httpBasicWhenUsingDefaultsThenResponseIncludesBasicChallenge() throws Exception {
+		this.spring.register(DefaultsEntryPointConfig.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(status().isUnauthorized())
+				.andExpect(header().string("WWW-Authenticate", "Basic realm=\"Realm\""));
+	}
+
+	@Test
+	public void httpBasicWhenUsingCustomAuthenticationEntryPointThenResponseIncludesBasicChallenge() throws Exception {
+		this.spring.register(CustomAuthenticationEntryPointConfig.class).autowire();
+
+		this.mvc.perform(get("/"));
+
+		verify(CustomAuthenticationEntryPointConfig.ENTRY_POINT).commence(any(HttpServletRequest.class),
+				any(HttpServletResponse.class), any(AuthenticationException.class));
+	}
+
+	@Test
+	public void httpBasicWhenInvokedTwiceThenUsesOriginalEntryPoint() throws Exception {
+		this.spring.register(DuplicateDoesNotOverrideConfig.class).autowire();
+
+		this.mvc.perform(get("/"));
+
+		verify(DuplicateDoesNotOverrideConfig.ENTRY_POINT).commence(any(HttpServletRequest.class),
+				any(HttpServletResponse.class), any(AuthenticationException.class));
+	}
+
+	// SEC-3019
+	@Test
+	public void httpBasicWhenRememberMeConfiguredThenSetsRememberMeCookie() throws Exception {
+		this.spring.register(BasicUsesRememberMeConfig.class).autowire();
+
+		this.mvc.perform(get("/").with(httpBasic("user", "password")).param("remember-me", "true"))
+				.andExpect(cookie().exists("remember-me"));
+	}
+
 	@EnableWebSecurity
 	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
 
@@ -100,14 +146,6 @@ public class HttpBasicConfigurerTests {
 
 	}
 
-	@Test
-	public void httpBasicWhenUsingDefaultsInLambdaThenResponseIncludesBasicChallenge() throws Exception {
-		this.spring.register(DefaultsLambdaEntryPointConfig.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(status().isUnauthorized())
-				.andExpect(header().string("WWW-Authenticate", "Basic realm=\"Realm\""));
-	}
-
 	@EnableWebSecurity
 	static class DefaultsLambdaEntryPointConfig extends WebSecurityConfigurerAdapter {
 
@@ -133,15 +171,6 @@ public class HttpBasicConfigurerTests {
 
 	}
 
-	// SEC-2198
-	@Test
-	public void httpBasicWhenUsingDefaultsThenResponseIncludesBasicChallenge() throws Exception {
-		this.spring.register(DefaultsEntryPointConfig.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(status().isUnauthorized())
-				.andExpect(header().string("WWW-Authenticate", "Basic realm=\"Realm\""));
-	}
-
 	@EnableWebSecurity
 	static class DefaultsEntryPointConfig extends WebSecurityConfigurerAdapter {
 
@@ -166,16 +195,6 @@ public class HttpBasicConfigurerTests {
 
 	}
 
-	@Test
-	public void httpBasicWhenUsingCustomAuthenticationEntryPointThenResponseIncludesBasicChallenge() throws Exception {
-		this.spring.register(CustomAuthenticationEntryPointConfig.class).autowire();
-
-		this.mvc.perform(get("/"));
-
-		verify(CustomAuthenticationEntryPointConfig.ENTRY_POINT).commence(any(HttpServletRequest.class),
-				any(HttpServletResponse.class), any(AuthenticationException.class));
-	}
-
 	@EnableWebSecurity
 	static class CustomAuthenticationEntryPointConfig extends WebSecurityConfigurerAdapter {
 
@@ -203,16 +222,6 @@ public class HttpBasicConfigurerTests {
 
 	}
 
-	@Test
-	public void httpBasicWhenInvokedTwiceThenUsesOriginalEntryPoint() throws Exception {
-		this.spring.register(DuplicateDoesNotOverrideConfig.class).autowire();
-
-		this.mvc.perform(get("/"));
-
-		verify(DuplicateDoesNotOverrideConfig.ENTRY_POINT).commence(any(HttpServletRequest.class),
-				any(HttpServletResponse.class), any(AuthenticationException.class));
-	}
-
 	@EnableWebSecurity
 	static class DuplicateDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
 
@@ -242,15 +251,6 @@ public class HttpBasicConfigurerTests {
 
 	}
 
-	// SEC-3019
-	@Test
-	public void httpBasicWhenRememberMeConfiguredThenSetsRememberMeCookie() throws Exception {
-		this.spring.register(BasicUsesRememberMeConfig.class).autowire();
-
-		this.mvc.perform(get("/").with(httpBasic("user", "password")).param("remember-me", "true"))
-				.andExpect(cookie().exists("remember-me"));
-	}
-
 	@EnableWebSecurity
 	@Configuration
 	static class BasicUsesRememberMeConfig extends WebSecurityConfigurerAdapter {
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityAntMatchersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityAntMatchersTests.java
index c78091f7dc..c6449818c2 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityAntMatchersTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityAntMatchersTests.java
@@ -78,6 +78,25 @@ public class HttpSecurityAntMatchersTests {
 		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
 	}
 
+	// SEC-3135
+	@Test
+	public void antMatchersMethodAndEmptyPatterns() throws Exception {
+		loadConfig(AntMatchersEmptyPatternsConfig.class);
+		this.request.setMethod("POST");
+
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
+	}
+
+	public void loadConfig(Class... configs) {
+		this.context = new AnnotationConfigWebApplicationContext();
+		this.context.register(configs);
+		this.context.refresh();
+
+		this.context.getAutowireCapableBeanFactory().autowireBean(this);
+	}
+
 	@EnableWebSecurity
 	@Configuration
 	static class AntMatchersNoPatternsConfig extends WebSecurityConfigurerAdapter {
@@ -104,17 +123,6 @@ public class HttpSecurityAntMatchersTests {
 
 	}
 
-	// SEC-3135
-	@Test
-	public void antMatchersMethodAndEmptyPatterns() throws Exception {
-		loadConfig(AntMatchersEmptyPatternsConfig.class);
-		this.request.setMethod("POST");
-
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
-	}
-
 	@EnableWebSecurity
 	@Configuration
 	static class AntMatchersEmptyPatternsConfig extends WebSecurityConfigurerAdapter {
@@ -142,12 +150,4 @@ public class HttpSecurityAntMatchersTests {
 
 	}
 
-	public void loadConfig(Class... configs) {
-		this.context = new AnnotationConfigWebApplicationContext();
-		this.context.register(configs);
-		this.context.refresh();
-
-		this.context.getAutowireCapableBeanFactory().autowireBean(this);
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java
index 61989ec37f..6e2fed7cc1 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java
@@ -86,6 +86,14 @@ public class HttpSecurityLogoutTests {
 		assertThat(currentContext.getAuthentication()).isNotNull();
 	}
 
+	public void loadConfig(Class... configs) {
+		this.context = new AnnotationConfigWebApplicationContext();
+		this.context.register(configs);
+		this.context.refresh();
+
+		this.context.getAutowireCapableBeanFactory().autowireBean(this);
+	}
+
 	@EnableWebSecurity
 	@Configuration
 	static class ClearAuthenticationFalseConfig extends WebSecurityConfigurerAdapter {
@@ -110,12 +118,4 @@ public class HttpSecurityLogoutTests {
 
 	}
 
-	public void loadConfig(Class... configs) {
-		this.context = new AnnotationConfigWebApplicationContext();
-		this.context.register(configs);
-		this.context.refresh();
-
-		this.context.getAutowireCapableBeanFactory().autowireBean(this);
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityRequestMatchersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityRequestMatchersTests.java
index 606c164b8e..eb07fa41bf 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityRequestMatchersTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityRequestMatchersTests.java
@@ -105,6 +105,119 @@ public class HttpSecurityRequestMatchersTests {
 		assertThat(this.springSecurityFilterChain.getFilters("/path")).isNotEmpty();
 	}
 
+	@Test
+	public void requestMatchersMvcMatcher() throws Exception {
+		loadConfig(RequestMatchersMvcMatcherConfig.class, LegacyMvcMatchingConfig.class);
+
+		this.request.setServletPath("/path");
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
+
+		setup();
+
+		this.request.setServletPath("/path.html");
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
+
+		setup();
+
+		this.request.setServletPath("/path/");
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
+	}
+
+	@Test
+	public void requestMatchersWhenMvcMatcherInLambdaThenPathIsSecured() throws Exception {
+		loadConfig(RequestMatchersMvcMatcherInLambdaConfig.class, LegacyMvcMatchingConfig.class);
+
+		this.request.setServletPath("/path");
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
+
+		setup();
+
+		this.request.setServletPath("/path.html");
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
+
+		setup();
+
+		this.request.setServletPath("/path/");
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
+	}
+
+	@Test
+	public void requestMatchersMvcMatcherServletPath() throws Exception {
+		loadConfig(RequestMatchersMvcMatcherServeltPathConfig.class);
+
+		this.request.setServletPath("/spring");
+		this.request.setRequestURI("/spring/path");
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
+
+		setup();
+
+		this.request.setServletPath("");
+		this.request.setRequestURI("/path");
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
+
+		setup();
+
+		this.request.setServletPath("/other");
+		this.request.setRequestURI("/other/path");
+
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
+	}
+
+	@Test
+	public void requestMatcherWhensMvcMatcherServletPathInLambdaThenPathIsSecured() throws Exception {
+		loadConfig(RequestMatchersMvcMatcherServletPathInLambdaConfig.class);
+
+		this.request.setServletPath("/spring");
+		this.request.setRequestURI("/spring/path");
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
+
+		setup();
+
+		this.request.setServletPath("");
+		this.request.setRequestURI("/path");
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
+
+		setup();
+
+		this.request.setServletPath("/other");
+		this.request.setRequestURI("/other/path");
+
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
+	}
+
+	public void loadConfig(Class... configs) {
+		this.context = new AnnotationConfigWebApplicationContext();
+		this.context.register(configs);
+		this.context.setServletContext(new MockServletContext());
+		this.context.refresh();
+
+		this.context.getAutowireCapableBeanFactory().autowireBean(this);
+	}
+
 	@EnableWebSecurity
 	@Configuration
 	@EnableWebMvc
@@ -141,30 +254,6 @@ public class HttpSecurityRequestMatchersTests {
 
 	}
 
-	@Test
-	public void requestMatchersMvcMatcher() throws Exception {
-		loadConfig(RequestMatchersMvcMatcherConfig.class, LegacyMvcMatchingConfig.class);
-
-		this.request.setServletPath("/path");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
-
-		setup();
-
-		this.request.setServletPath("/path.html");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
-
-		setup();
-
-		this.request.setServletPath("/path/");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
-	}
-
 	@EnableWebSecurity
 	@Configuration
 	@EnableWebMvc
@@ -203,30 +292,6 @@ public class HttpSecurityRequestMatchersTests {
 
 	}
 
-	@Test
-	public void requestMatchersWhenMvcMatcherInLambdaThenPathIsSecured() throws Exception {
-		loadConfig(RequestMatchersMvcMatcherInLambdaConfig.class, LegacyMvcMatchingConfig.class);
-
-		this.request.setServletPath("/path");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
-
-		setup();
-
-		this.request.setServletPath("/path.html");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
-
-		setup();
-
-		this.request.setServletPath("/path/");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
-	}
-
 	@EnableWebSecurity
 	@Configuration
 	@EnableWebMvc
@@ -260,34 +325,6 @@ public class HttpSecurityRequestMatchersTests {
 
 	}
 
-	@Test
-	public void requestMatchersMvcMatcherServletPath() throws Exception {
-		loadConfig(RequestMatchersMvcMatcherServeltPathConfig.class);
-
-		this.request.setServletPath("/spring");
-		this.request.setRequestURI("/spring/path");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
-
-		setup();
-
-		this.request.setServletPath("");
-		this.request.setRequestURI("/path");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
-
-		setup();
-
-		this.request.setServletPath("/other");
-		this.request.setRequestURI("/other/path");
-
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
-	}
-
 	@EnableWebSecurity
 	@Configuration
 	@EnableWebMvc
@@ -327,34 +364,6 @@ public class HttpSecurityRequestMatchersTests {
 
 	}
 
-	@Test
-	public void requestMatcherWhensMvcMatcherServletPathInLambdaThenPathIsSecured() throws Exception {
-		loadConfig(RequestMatchersMvcMatcherServletPathInLambdaConfig.class);
-
-		this.request.setServletPath("/spring");
-		this.request.setRequestURI("/spring/path");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
-
-		setup();
-
-		this.request.setServletPath("");
-		this.request.setRequestURI("/path");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
-
-		setup();
-
-		this.request.setServletPath("/other");
-		this.request.setRequestURI("/other/path");
-
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
-	}
-
 	@EnableWebSecurity
 	@Configuration
 	@EnableWebMvc
@@ -399,13 +408,4 @@ public class HttpSecurityRequestMatchersTests {
 
 	}
 
-	public void loadConfig(Class... configs) {
-		this.context = new AnnotationConfigWebApplicationContext();
-		this.context.register(configs);
-		this.context.setServletContext(new MockServletContext());
-		this.context.refresh();
-
-		this.context.getAutowireCapableBeanFactory().autowireBean(this);
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/Issue55Tests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/Issue55Tests.java
index 5097a3d5ef..b071eadbb0 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/Issue55Tests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/Issue55Tests.java
@@ -60,6 +60,36 @@ public class Issue55Tests {
 		assertThat(filter.getAuthenticationManager().authenticate(token)).isEqualTo(CustomAuthenticationManager.RESULT);
 	}
 
+	@Test
+	public void multiHttpWebSecurityConfigurerAdapterDefaultsToAutowired()
+			throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+		TestingAuthenticationToken token = new TestingAuthenticationToken("test", "this");
+		this.spring.register(MultiWebSecurityConfigurerAdapterDefaultsAuthManagerConfig.class);
+		this.spring.getContext().getBean(FilterChainProxy.class);
+
+		FilterSecurityInterceptor filter = (FilterSecurityInterceptor) findFilter(FilterSecurityInterceptor.class, 0);
+		assertThat(filter.getAuthenticationManager().authenticate(token)).isEqualTo(CustomAuthenticationManager.RESULT);
+
+		FilterSecurityInterceptor secondFilter = (FilterSecurityInterceptor) findFilter(FilterSecurityInterceptor.class,
+				1);
+		assertThat(secondFilter.getAuthenticationManager().authenticate(token))
+				.isEqualTo(CustomAuthenticationManager.RESULT);
+	}
+
+	Filter findFilter(Class filter, int index) {
+		List filters = filterChain(index).getFilters();
+		for (Filter it : filters) {
+			if (filter.isAssignableFrom(it.getClass())) {
+				return it;
+			}
+		}
+		return null;
+	}
+
+	SecurityFilterChain filterChain(int index) {
+		return this.spring.getContext().getBean(FilterChainProxy.class).getFilterChains().get(index);
+	}
+
 	@EnableWebSecurity
 	static class WebSecurityConfigurerAdapterDefaultsAuthManagerConfig {
 
@@ -89,22 +119,6 @@ public class Issue55Tests {
 
 	}
 
-	@Test
-	public void multiHttpWebSecurityConfigurerAdapterDefaultsToAutowired()
-			throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
-		TestingAuthenticationToken token = new TestingAuthenticationToken("test", "this");
-		this.spring.register(MultiWebSecurityConfigurerAdapterDefaultsAuthManagerConfig.class);
-		this.spring.getContext().getBean(FilterChainProxy.class);
-
-		FilterSecurityInterceptor filter = (FilterSecurityInterceptor) findFilter(FilterSecurityInterceptor.class, 0);
-		assertThat(filter.getAuthenticationManager().authenticate(token)).isEqualTo(CustomAuthenticationManager.RESULT);
-
-		FilterSecurityInterceptor secondFilter = (FilterSecurityInterceptor) findFilter(FilterSecurityInterceptor.class,
-				1);
-		assertThat(secondFilter.getAuthenticationManager().authenticate(token))
-				.isEqualTo(CustomAuthenticationManager.RESULT);
-	}
-
 	@EnableWebSecurity
 	static class MultiWebSecurityConfigurerAdapterDefaultsAuthManagerConfig {
 
@@ -160,18 +174,4 @@ public class Issue55Tests {
 
 	}
 
-	Filter findFilter(Class filter, int index) {
-		List filters = filterChain(index).getFilters();
-		for (Filter it : filters) {
-			if (filter.isAssignableFrom(it.getClass())) {
-				return it;
-			}
-		}
-		return null;
-	}
-
-	SecurityFilterChain filterChain(int index) {
-		return this.spring.getContext().getBean(FilterChainProxy.class).getFilterChains().get(index);
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/JeeConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/JeeConfigurerTests.java
index e70283bb82..46b097a6b9 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/JeeConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/JeeConfigurerTests.java
@@ -75,6 +75,63 @@ public class JeeConfigurerTests {
 				.postProcess(any(J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.class));
 	}
 
+	@Test
+	public void jeeWhenInvokedTwiceThenUsesOriginalMappableRoles() throws Exception {
+		this.spring.register(InvokeTwiceDoesNotOverride.class).autowire();
+		Principal user = mock(Principal.class);
+		when(user.getName()).thenReturn("user");
+
+		this.mvc.perform(get("/").principal(user).with(request -> {
+			request.addUserRole("ROLE_ADMIN");
+			request.addUserRole("ROLE_USER");
+			return request;
+		})).andExpect(authenticated().withRoles("USER"));
+	}
+
+	@Test
+	public void requestWhenJeeMappableRolesInLambdaThenAuthenticatedWithMappableRoles() throws Exception {
+		this.spring.register(JeeMappableRolesConfig.class).autowire();
+		Principal user = mock(Principal.class);
+		when(user.getName()).thenReturn("user");
+
+		this.mvc.perform(get("/").principal(user).with(request -> {
+			request.addUserRole("ROLE_ADMIN");
+			request.addUserRole("ROLE_USER");
+			return request;
+		})).andExpect(authenticated().withRoles("USER"));
+	}
+
+	@Test
+	public void requestWhenJeeMappableAuthoritiesInLambdaThenAuthenticatedWithMappableAuthorities() throws Exception {
+		this.spring.register(JeeMappableAuthoritiesConfig.class).autowire();
+		Principal user = mock(Principal.class);
+		when(user.getName()).thenReturn("user");
+
+		this.mvc.perform(get("/").principal(user).with(request -> {
+			request.addUserRole("ROLE_ADMIN");
+			request.addUserRole("ROLE_USER");
+			return request;
+		})).andExpect(authenticated().withAuthorities(AuthorityUtils.createAuthorityList("ROLE_USER")));
+	}
+
+	@Test
+	public void requestWhenCustomAuthenticatedUserDetailsServiceInLambdaThenCustomAuthenticatedUserDetailsServiceUsed()
+			throws Exception {
+		this.spring.register(JeeCustomAuthenticatedUserDetailsServiceConfig.class).autowire();
+		Principal user = mock(Principal.class);
+		User userDetails = new User("user", "N/A", true, true, true, true,
+				AuthorityUtils.createAuthorityList("ROLE_USER"));
+		when(user.getName()).thenReturn("user");
+		when(JeeCustomAuthenticatedUserDetailsServiceConfig.authenticationUserDetailsService.loadUserDetails(any()))
+				.thenReturn(userDetails);
+
+		this.mvc.perform(get("/").principal(user).with(request -> {
+			request.addUserRole("ROLE_ADMIN");
+			request.addUserRole("ROLE_USER");
+			return request;
+		})).andExpect(authenticated().withRoles("USER"));
+	}
+
 	@EnableWebSecurity
 	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
 
@@ -104,19 +161,6 @@ public class JeeConfigurerTests {
 
 	}
 
-	@Test
-	public void jeeWhenInvokedTwiceThenUsesOriginalMappableRoles() throws Exception {
-		this.spring.register(InvokeTwiceDoesNotOverride.class).autowire();
-		Principal user = mock(Principal.class);
-		when(user.getName()).thenReturn("user");
-
-		this.mvc.perform(get("/").principal(user).with(request -> {
-			request.addUserRole("ROLE_ADMIN");
-			request.addUserRole("ROLE_USER");
-			return request;
-		})).andExpect(authenticated().withRoles("USER"));
-	}
-
 	@EnableWebSecurity
 	static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
 
@@ -133,19 +177,6 @@ public class JeeConfigurerTests {
 
 	}
 
-	@Test
-	public void requestWhenJeeMappableRolesInLambdaThenAuthenticatedWithMappableRoles() throws Exception {
-		this.spring.register(JeeMappableRolesConfig.class).autowire();
-		Principal user = mock(Principal.class);
-		when(user.getName()).thenReturn("user");
-
-		this.mvc.perform(get("/").principal(user).with(request -> {
-			request.addUserRole("ROLE_ADMIN");
-			request.addUserRole("ROLE_USER");
-			return request;
-		})).andExpect(authenticated().withRoles("USER"));
-	}
-
 	@EnableWebSecurity
 	public static class JeeMappableRolesConfig extends WebSecurityConfigurerAdapter {
 
@@ -166,19 +197,6 @@ public class JeeConfigurerTests {
 
 	}
 
-	@Test
-	public void requestWhenJeeMappableAuthoritiesInLambdaThenAuthenticatedWithMappableAuthorities() throws Exception {
-		this.spring.register(JeeMappableAuthoritiesConfig.class).autowire();
-		Principal user = mock(Principal.class);
-		when(user.getName()).thenReturn("user");
-
-		this.mvc.perform(get("/").principal(user).with(request -> {
-			request.addUserRole("ROLE_ADMIN");
-			request.addUserRole("ROLE_USER");
-			return request;
-		})).andExpect(authenticated().withAuthorities(AuthorityUtils.createAuthorityList("ROLE_USER")));
-	}
-
 	@EnableWebSecurity
 	public static class JeeMappableAuthoritiesConfig extends WebSecurityConfigurerAdapter {
 
@@ -199,24 +217,6 @@ public class JeeConfigurerTests {
 
 	}
 
-	@Test
-	public void requestWhenCustomAuthenticatedUserDetailsServiceInLambdaThenCustomAuthenticatedUserDetailsServiceUsed()
-			throws Exception {
-		this.spring.register(JeeCustomAuthenticatedUserDetailsServiceConfig.class).autowire();
-		Principal user = mock(Principal.class);
-		User userDetails = new User("user", "N/A", true, true, true, true,
-				AuthorityUtils.createAuthorityList("ROLE_USER"));
-		when(user.getName()).thenReturn("user");
-		when(JeeCustomAuthenticatedUserDetailsServiceConfig.authenticationUserDetailsService.loadUserDetails(any()))
-				.thenReturn(userDetails);
-
-		this.mvc.perform(get("/").principal(user).with(request -> {
-			request.addUserRole("ROLE_ADMIN");
-			request.addUserRole("ROLE_USER");
-			return request;
-		})).andExpect(authenticated().withRoles("USER"));
-	}
-
 	@EnableWebSecurity
 	public static class JeeCustomAuthenticatedUserDetailsServiceConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurerTests.java
index 6e1669710b..4d3905976b 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurerTests.java
@@ -70,82 +70,24 @@ public class LogoutConfigurerTests {
 				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
 	}
 
-	@EnableWebSecurity
-	static class NullLogoutSuccessHandlerConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.logout()
-					.defaultLogoutSuccessHandlerFor(null, mock(RequestMatcher.class));
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void configureWhenDefaultLogoutSuccessHandlerForHasNullLogoutHandlerInLambdaThenException() {
 		assertThatThrownBy(() -> this.spring.register(NullLogoutSuccessHandlerInLambdaConfig.class).autowire())
 				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
 	}
 
-	@EnableWebSecurity
-	static class NullLogoutSuccessHandlerInLambdaConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.logout(logout ->
-					logout.defaultLogoutSuccessHandlerFor(null, mock(RequestMatcher.class))
-				);
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void configureWhenDefaultLogoutSuccessHandlerForHasNullMatcherThenException() {
 		assertThatThrownBy(() -> this.spring.register(NullMatcherConfig.class).autowire())
 				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
 	}
 
-	@EnableWebSecurity
-	static class NullMatcherConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.logout()
-					.defaultLogoutSuccessHandlerFor(mock(LogoutSuccessHandler.class), null);
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void configureWhenDefaultLogoutSuccessHandlerForHasNullMatcherInLambdaThenException() {
 		assertThatThrownBy(() -> this.spring.register(NullMatcherInLambdaConfig.class).autowire())
 				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
 	}
 
-	@EnableWebSecurity
-	static class NullMatcherInLambdaConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.logout(logout ->
-					logout.defaultLogoutSuccessHandlerFor(mock(LogoutSuccessHandler.class), null)
-				);
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnLogoutFilter() {
 		this.spring.register(ObjectPostProcessorConfig.class).autowire();
@@ -153,35 +95,6 @@ public class LogoutConfigurerTests {
 		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(LogoutFilter.class));
 	}
 
-	@EnableWebSecurity
-	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
-
-		static ObjectPostProcessor objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.logout();
-			// @formatter:on
-		}
-
-		@Bean
-		static ObjectPostProcessor objectPostProcessor() {
-			return objectPostProcessor;
-		}
-
-	}
-
-	static class ReflectingObjectPostProcessor implements ObjectPostProcessor {
-
-		@Override
-		public  O postProcess(O object) {
-			return object;
-		}
-
-	}
-
 	@Test
 	public void logoutWhenInvokedTwiceThenUsesOriginalLogoutUrl() throws Exception {
 		this.spring.register(DuplicateDoesNotOverrideConfig.class).autowire();
@@ -190,30 +103,6 @@ public class LogoutConfigurerTests {
 				.andExpect(redirectedUrl("/login?logout"));
 	}
 
-	@EnableWebSecurity
-	static class DuplicateDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.logout()
-					.logoutUrl("/custom/logout")
-					.and()
-				.logout();
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-			// @formatter:off
-			auth
-				.inMemoryAuthentication();
-			// @formatter:on
-		}
-
-	}
-
 	// SEC-2311
 	@Test
 	public void logoutWhenGetRequestAndCsrfDisabledThenRedirectsToLogin() throws Exception {
@@ -243,21 +132,6 @@ public class LogoutConfigurerTests {
 		this.mvc.perform(delete("/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
 	}
 
-	@EnableWebSecurity
-	static class CsrfDisabledConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.csrf()
-					.disable()
-				.logout();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void logoutWhenGetRequestAndCsrfDisabledAndCustomLogoutUrlThenRedirectsToLogin() throws Exception {
 		this.spring.register(CsrfDisabledAndCustomLogoutConfig.class).autowire();
@@ -288,22 +162,6 @@ public class LogoutConfigurerTests {
 				.andExpect(redirectedUrl("/login?logout"));
 	}
 
-	@EnableWebSecurity
-	static class CsrfDisabledAndCustomLogoutConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.csrf()
-					.disable()
-				.logout()
-					.logoutUrl("/custom/logout");
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void logoutWhenCustomLogoutUrlInLambdaThenRedirectsToLogin() throws Exception {
 		this.spring.register(CsrfDisabledAndCustomLogoutInLambdaConfig.class).autowire();
@@ -311,21 +169,6 @@ public class LogoutConfigurerTests {
 		this.mvc.perform(get("/custom/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
 	}
 
-	@EnableWebSecurity
-	static class CsrfDisabledAndCustomLogoutInLambdaConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.csrf()
-					.disable()
-				.logout(logout -> logout.logoutUrl("/custom/logout"));
-			// @formatter:on
-		}
-
-	}
-
 	// SEC-3170
 	@Test
 	public void configureWhenLogoutHandlerNullThenException() {
@@ -333,39 +176,12 @@ public class LogoutConfigurerTests {
 				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
 	}
 
-	@EnableWebSecurity
-	static class NullLogoutHandlerConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.logout()
-					.addLogoutHandler(null);
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void configureWhenLogoutHandlerNullInLambdaThenException() {
 		assertThatThrownBy(() -> this.spring.register(NullLogoutHandlerInLambdaConfig.class).autowire())
 				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
 	}
 
-	@EnableWebSecurity
-	static class NullLogoutHandlerInLambdaConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.logout(logout -> logout.addLogoutHandler(null));
-			// @formatter:on
-		}
-
-	}
-
 	// SEC-3170
 	@Test
 	public void rememberMeWhenRememberMeServicesNotLogoutHandlerThenRedirectsToLogin() throws Exception {
@@ -375,22 +191,6 @@ public class LogoutConfigurerTests {
 				.andExpect(redirectedUrl("/login?logout"));
 	}
 
-	@EnableWebSecurity
-	static class RememberMeNoLogoutHandler extends WebSecurityConfigurerAdapter {
-
-		static RememberMeServices REMEMBER_ME = mock(RememberMeServices.class);
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.rememberMe()
-					.rememberMeServices(REMEMBER_ME);
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void logoutWhenAcceptTextHtmlThenRedirectsToLogin() throws Exception {
 		this.spring.register(BasicSecurityConfig.class).autowire();
@@ -439,11 +239,6 @@ public class LogoutConfigurerTests {
 				.andExpect(status().isNoContent());
 	}
 
-	@EnableWebSecurity
-	static class BasicSecurityConfig extends WebSecurityConfigurerAdapter {
-
-	}
-
 	@Test
 	public void logoutWhenDisabledThenLogoutUrlNotFound() throws Exception {
 		this.spring.register(LogoutDisabledConfig.class).autowire();
@@ -451,6 +246,211 @@ public class LogoutConfigurerTests {
 		this.mvc.perform(post("/logout").with(csrf())).andExpect(status().isNotFound());
 	}
 
+	@EnableWebSecurity
+	static class NullLogoutSuccessHandlerConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.logout()
+					.defaultLogoutSuccessHandlerFor(null, mock(RequestMatcher.class));
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class NullLogoutSuccessHandlerInLambdaConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.logout(logout ->
+					logout.defaultLogoutSuccessHandlerFor(null, mock(RequestMatcher.class))
+				);
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class NullMatcherConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.logout()
+					.defaultLogoutSuccessHandlerFor(mock(LogoutSuccessHandler.class), null);
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class NullMatcherInLambdaConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.logout(logout ->
+					logout.defaultLogoutSuccessHandlerFor(mock(LogoutSuccessHandler.class), null)
+				);
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
+
+		static ObjectPostProcessor objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.logout();
+			// @formatter:on
+		}
+
+		@Bean
+		static ObjectPostProcessor objectPostProcessor() {
+			return objectPostProcessor;
+		}
+
+	}
+
+	static class ReflectingObjectPostProcessor implements ObjectPostProcessor {
+
+		@Override
+		public  O postProcess(O object) {
+			return object;
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class DuplicateDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.logout()
+					.logoutUrl("/custom/logout")
+					.and()
+				.logout();
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class CsrfDisabledConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.csrf()
+					.disable()
+				.logout();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class CsrfDisabledAndCustomLogoutConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.csrf()
+					.disable()
+				.logout()
+					.logoutUrl("/custom/logout");
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class CsrfDisabledAndCustomLogoutInLambdaConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.csrf()
+					.disable()
+				.logout(logout -> logout.logoutUrl("/custom/logout"));
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class NullLogoutHandlerConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.logout()
+					.addLogoutHandler(null);
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class NullLogoutHandlerInLambdaConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.logout(logout -> logout.addLogoutHandler(null));
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class RememberMeNoLogoutHandler extends WebSecurityConfigurerAdapter {
+
+		static RememberMeServices REMEMBER_ME = mock(RememberMeServices.class);
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.rememberMe()
+					.rememberMeServices(REMEMBER_ME);
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class BasicSecurityConfig extends WebSecurityConfigurerAdapter {
+
+	}
+
 	@EnableWebSecurity
 	static class LogoutDisabledConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceDebugTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceDebugTests.java
index c386e59c80..79c48708c1 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceDebugTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceDebugTests.java
@@ -61,11 +61,6 @@ public class NamespaceDebugTests {
 		verify(appender, atLeastOnce()).doAppend(any(ILoggingEvent.class));
 	}
 
-	@EnableWebSecurity(debug = true)
-	static class DebugWebSecurity extends WebSecurityConfigurerAdapter {
-
-	}
-
 	@Test
 	public void requestWhenDebugSetToFalseThenDoesNotLogDebugInformation() throws Exception {
 		Appender appender = mockAppenderFor("Spring Security Debugger");
@@ -75,11 +70,6 @@ public class NamespaceDebugTests {
 		verify(appender, never()).doAppend(any(ILoggingEvent.class));
 	}
 
-	@EnableWebSecurity
-	static class NoDebugWebSecurity extends WebSecurityConfigurerAdapter {
-
-	}
-
 	private Appender mockAppenderFor(String name) {
 		Appender appender = mock(Appender.class);
 		Logger logger = (Logger) LoggerFactory.getLogger(name);
@@ -92,4 +82,14 @@ public class NamespaceDebugTests {
 		return this.spring.getContext().getBean("springSecurityFilterChain").getClass();
 	}
 
+	@EnableWebSecurity(debug = true)
+	static class DebugWebSecurity extends WebSecurityConfigurerAdapter {
+
+	}
+
+	@EnableWebSecurity
+	static class NoDebugWebSecurity extends WebSecurityConfigurerAdapter {
+
+	}
+
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpAnonymousTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpAnonymousTests.java
index ccf73dba40..1ff61c858c 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpAnonymousTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpAnonymousTests.java
@@ -60,6 +60,30 @@ public class NamespaceHttpAnonymousTests {
 		this.mvc.perform(get("/type")).andExpect(content().string(AnonymousAuthenticationToken.class.getSimpleName()));
 	}
 
+	@Test
+	public void anonymousRequestWhenDisablingAnonymousThenDenies() throws Exception {
+		this.spring.register(AnonymousDisabledConfig.class, AnonymousController.class).autowire();
+		this.mvc.perform(get("/type")).andExpect(status().isForbidden());
+	}
+
+	@Test
+	public void requestWhenAnonymousThenSendsAnonymousConfiguredAuthorities() throws Exception {
+		this.spring.register(AnonymousGrantedAuthorityConfig.class, AnonymousController.class).autowire();
+		this.mvc.perform(get("/type")).andExpect(content().string(AnonymousAuthenticationToken.class.getSimpleName()));
+	}
+
+	@Test
+	public void anonymousRequestWhenAnonymousKeyConfiguredThenKeyIsUsed() throws Exception {
+		this.spring.register(AnonymousKeyConfig.class, AnonymousController.class).autowire();
+		this.mvc.perform(get("/key")).andExpect(content().string(String.valueOf("AnonymousKeyConfig".hashCode())));
+	}
+
+	@Test
+	public void anonymousRequestWhenAnonymousUsernameConfiguredThenUsernameIsUsed() throws Exception {
+		this.spring.register(AnonymousUsernameConfig.class, AnonymousController.class).autowire();
+		this.mvc.perform(get("/principal")).andExpect(content().string("AnonymousUsernameConfig"));
+	}
+
 	@EnableWebSecurity
 	static class AnonymousConfig extends WebSecurityConfigurerAdapter {
 
@@ -75,12 +99,6 @@ public class NamespaceHttpAnonymousTests {
 
 	}
 
-	@Test
-	public void anonymousRequestWhenDisablingAnonymousThenDenies() throws Exception {
-		this.spring.register(AnonymousDisabledConfig.class, AnonymousController.class).autowire();
-		this.mvc.perform(get("/type")).andExpect(status().isForbidden());
-	}
-
 	@EnableWebSecurity
 	static class AnonymousDisabledConfig extends WebSecurityConfigurerAdapter {
 
@@ -107,12 +125,6 @@ public class NamespaceHttpAnonymousTests {
 
 	}
 
-	@Test
-	public void requestWhenAnonymousThenSendsAnonymousConfiguredAuthorities() throws Exception {
-		this.spring.register(AnonymousGrantedAuthorityConfig.class, AnonymousController.class).autowire();
-		this.mvc.perform(get("/type")).andExpect(content().string(AnonymousAuthenticationToken.class.getSimpleName()));
-	}
-
 	@EnableWebSecurity
 	static class AnonymousGrantedAuthorityConfig extends WebSecurityConfigurerAdapter {
 
@@ -131,12 +143,6 @@ public class NamespaceHttpAnonymousTests {
 
 	}
 
-	@Test
-	public void anonymousRequestWhenAnonymousKeyConfiguredThenKeyIsUsed() throws Exception {
-		this.spring.register(AnonymousKeyConfig.class, AnonymousController.class).autowire();
-		this.mvc.perform(get("/key")).andExpect(content().string(String.valueOf("AnonymousKeyConfig".hashCode())));
-	}
-
 	@EnableWebSecurity
 	static class AnonymousKeyConfig extends WebSecurityConfigurerAdapter {
 
@@ -154,12 +160,6 @@ public class NamespaceHttpAnonymousTests {
 
 	}
 
-	@Test
-	public void anonymousRequestWhenAnonymousUsernameConfiguredThenUsernameIsUsed() throws Exception {
-		this.spring.register(AnonymousUsernameConfig.class, AnonymousController.class).autowire();
-		this.mvc.perform(get("/principal")).andExpect(content().string("AnonymousUsernameConfig"));
-	}
-
 	@EnableWebSecurity
 	static class AnonymousUsernameConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpBasicTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpBasicTests.java
index 6cd603b95b..153c5e28dd 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpBasicTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpBasicTests.java
@@ -73,6 +73,90 @@ public class NamespaceHttpBasicTests {
 		this.mvc.perform(get("/").with(httpBasic("user", "password"))).andExpect(status().isNotFound());
 	}
 
+	@Test
+	public void basicAuthenticationWhenUsingDefaultsInLambdaThenMatchesNamespace() throws Exception {
+		this.spring.register(HttpBasicLambdaConfig.class, UserConfig.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(status().isUnauthorized());
+
+		this.mvc.perform(get("/").with(httpBasic("user", "invalid"))).andExpect(status().isUnauthorized())
+				.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"Realm\""));
+
+		this.mvc.perform(get("/").with(httpBasic("user", "password"))).andExpect(status().isNotFound());
+	}
+
+	/**
+	 * http@realm equivalent
+	 */
+	@Test
+	public void basicAuthenticationWhenUsingCustomRealmThenMatchesNamespace() throws Exception {
+		this.spring.register(CustomHttpBasicConfig.class, UserConfig.class).autowire();
+
+		this.mvc.perform(get("/").with(httpBasic("user", "invalid"))).andExpect(status().isUnauthorized())
+				.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"Custom Realm\""));
+	}
+
+	@Test
+	public void basicAuthenticationWhenUsingCustomRealmInLambdaThenMatchesNamespace() throws Exception {
+		this.spring.register(CustomHttpBasicLambdaConfig.class, UserConfig.class).autowire();
+
+		this.mvc.perform(get("/").with(httpBasic("user", "invalid"))).andExpect(status().isUnauthorized())
+				.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"Custom Realm\""));
+	}
+
+	/**
+	 * http/http-basic@authentication-details-source-ref equivalent
+	 */
+	@Test
+	public void basicAuthenticationWhenUsingAuthenticationDetailsSourceRefThenMatchesNamespace() throws Exception {
+		this.spring.register(AuthenticationDetailsSourceHttpBasicConfig.class, UserConfig.class).autowire();
+
+		AuthenticationDetailsSource source = this.spring.getContext()
+				.getBean(AuthenticationDetailsSource.class);
+
+		this.mvc.perform(get("/").with(httpBasic("user", "password")));
+
+		verify(source).buildDetails(any(HttpServletRequest.class));
+	}
+
+	@Test
+	public void basicAuthenticationWhenUsingAuthenticationDetailsSourceRefInLambdaThenMatchesNamespace()
+			throws Exception {
+		this.spring.register(AuthenticationDetailsSourceHttpBasicLambdaConfig.class, UserConfig.class).autowire();
+
+		AuthenticationDetailsSource source = this.spring.getContext()
+				.getBean(AuthenticationDetailsSource.class);
+
+		this.mvc.perform(get("/").with(httpBasic("user", "password")));
+
+		verify(source).buildDetails(any(HttpServletRequest.class));
+	}
+
+	/**
+	 * http/http-basic@entry-point-ref
+	 */
+	@Test
+	public void basicAuthenticationWhenUsingEntryPointRefThenMatchesNamespace() throws Exception {
+		this.spring.register(EntryPointRefHttpBasicConfig.class, UserConfig.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(status().is(999));
+
+		this.mvc.perform(get("/").with(httpBasic("user", "invalid"))).andExpect(status().is(999));
+
+		this.mvc.perform(get("/").with(httpBasic("user", "password"))).andExpect(status().isNotFound());
+	}
+
+	@Test
+	public void basicAuthenticationWhenUsingEntryPointRefInLambdaThenMatchesNamespace() throws Exception {
+		this.spring.register(EntryPointRefHttpBasicLambdaConfig.class, UserConfig.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(status().is(999));
+
+		this.mvc.perform(get("/").with(httpBasic("user", "invalid"))).andExpect(status().is(999));
+
+		this.mvc.perform(get("/").with(httpBasic("user", "password"))).andExpect(status().isNotFound());
+	}
+
 	@Configuration
 	static class UserConfig {
 
@@ -107,18 +191,6 @@ public class NamespaceHttpBasicTests {
 
 	}
 
-	@Test
-	public void basicAuthenticationWhenUsingDefaultsInLambdaThenMatchesNamespace() throws Exception {
-		this.spring.register(HttpBasicLambdaConfig.class, UserConfig.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(status().isUnauthorized());
-
-		this.mvc.perform(get("/").with(httpBasic("user", "invalid"))).andExpect(status().isUnauthorized())
-				.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"Realm\""));
-
-		this.mvc.perform(get("/").with(httpBasic("user", "password"))).andExpect(status().isNotFound());
-	}
-
 	@EnableWebSecurity
 	static class HttpBasicLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -136,17 +208,6 @@ public class NamespaceHttpBasicTests {
 
 	}
 
-	/**
-	 * http@realm equivalent
-	 */
-	@Test
-	public void basicAuthenticationWhenUsingCustomRealmThenMatchesNamespace() throws Exception {
-		this.spring.register(CustomHttpBasicConfig.class, UserConfig.class).autowire();
-
-		this.mvc.perform(get("/").with(httpBasic("user", "invalid"))).andExpect(status().isUnauthorized())
-				.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"Custom Realm\""));
-	}
-
 	@EnableWebSecurity
 	static class CustomHttpBasicConfig extends WebSecurityConfigurerAdapter {
 
@@ -163,14 +224,6 @@ public class NamespaceHttpBasicTests {
 
 	}
 
-	@Test
-	public void basicAuthenticationWhenUsingCustomRealmInLambdaThenMatchesNamespace() throws Exception {
-		this.spring.register(CustomHttpBasicLambdaConfig.class, UserConfig.class).autowire();
-
-		this.mvc.perform(get("/").with(httpBasic("user", "invalid"))).andExpect(status().isUnauthorized())
-				.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"Custom Realm\""));
-	}
-
 	@EnableWebSecurity
 	static class CustomHttpBasicLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -188,21 +241,6 @@ public class NamespaceHttpBasicTests {
 
 	}
 
-	/**
-	 * http/http-basic@authentication-details-source-ref equivalent
-	 */
-	@Test
-	public void basicAuthenticationWhenUsingAuthenticationDetailsSourceRefThenMatchesNamespace() throws Exception {
-		this.spring.register(AuthenticationDetailsSourceHttpBasicConfig.class, UserConfig.class).autowire();
-
-		AuthenticationDetailsSource source = this.spring.getContext()
-				.getBean(AuthenticationDetailsSource.class);
-
-		this.mvc.perform(get("/").with(httpBasic("user", "password")));
-
-		verify(source).buildDetails(any(HttpServletRequest.class));
-	}
-
 	@EnableWebSecurity
 	static class AuthenticationDetailsSourceHttpBasicConfig extends WebSecurityConfigurerAdapter {
 
@@ -225,19 +263,6 @@ public class NamespaceHttpBasicTests {
 
 	}
 
-	@Test
-	public void basicAuthenticationWhenUsingAuthenticationDetailsSourceRefInLambdaThenMatchesNamespace()
-			throws Exception {
-		this.spring.register(AuthenticationDetailsSourceHttpBasicLambdaConfig.class, UserConfig.class).autowire();
-
-		AuthenticationDetailsSource source = this.spring.getContext()
-				.getBean(AuthenticationDetailsSource.class);
-
-		this.mvc.perform(get("/").with(httpBasic("user", "password")));
-
-		verify(source).buildDetails(any(HttpServletRequest.class));
-	}
-
 	@EnableWebSecurity
 	static class AuthenticationDetailsSourceHttpBasicLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -260,20 +285,6 @@ public class NamespaceHttpBasicTests {
 
 	}
 
-	/**
-	 * http/http-basic@entry-point-ref
-	 */
-	@Test
-	public void basicAuthenticationWhenUsingEntryPointRefThenMatchesNamespace() throws Exception {
-		this.spring.register(EntryPointRefHttpBasicConfig.class, UserConfig.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(status().is(999));
-
-		this.mvc.perform(get("/").with(httpBasic("user", "invalid"))).andExpect(status().is(999));
-
-		this.mvc.perform(get("/").with(httpBasic("user", "password"))).andExpect(status().isNotFound());
-	}
-
 	@EnableWebSecurity
 	static class EntryPointRefHttpBasicConfig extends WebSecurityConfigurerAdapter {
 
@@ -293,17 +304,6 @@ public class NamespaceHttpBasicTests {
 
 	}
 
-	@Test
-	public void basicAuthenticationWhenUsingEntryPointRefInLambdaThenMatchesNamespace() throws Exception {
-		this.spring.register(EntryPointRefHttpBasicLambdaConfig.class, UserConfig.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(status().is(999));
-
-		this.mvc.perform(get("/").with(httpBasic("user", "invalid"))).andExpect(status().is(999));
-
-		this.mvc.perform(get("/").with(httpBasic("user", "password"))).andExpect(status().isNotFound());
-	}
-
 	@EnableWebSecurity
 	static class EntryPointRefHttpBasicLambdaConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpCustomFilterTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpCustomFilterTests.java
index e2bc0970fd..4355601aa9 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpCustomFilterTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpCustomFilterTests.java
@@ -65,6 +65,37 @@ public class NamespaceHttpCustomFilterTests {
 		assertThatFilters().containsSubsequence(CustomFilter.class, UsernamePasswordAuthenticationFilter.class);
 	}
 
+	@Test
+	public void getFiltersWhenFilterAddedAfterThenBehaviorMatchesNamespace() {
+		this.spring.register(CustomFilterAfterConfig.class, UserDetailsServiceConfig.class).autowire();
+		assertThatFilters().containsSubsequence(UsernamePasswordAuthenticationFilter.class, CustomFilter.class);
+	}
+
+	@Test
+	public void getFiltersWhenFilterAddedThenBehaviorMatchesNamespace() {
+		this.spring.register(CustomFilterPositionConfig.class, UserDetailsServiceConfig.class).autowire();
+		assertThatFilters().containsExactly(CustomFilter.class);
+	}
+
+	@Test
+	public void getFiltersWhenFilterAddedAtPositionThenBehaviorMatchesNamespace() {
+		this.spring.register(CustomFilterPositionAtConfig.class, UserDetailsServiceConfig.class).autowire();
+		assertThatFilters().containsExactly(OtherCustomFilter.class);
+	}
+
+	@Test
+	public void getFiltersWhenCustomAuthenticationManagerThenBehaviorMatchesNamespace() {
+		this.spring.register(NoAuthenticationManagerInHttpConfigurationConfig.class).autowire();
+		assertThatFilters().startsWith(CustomFilter.class);
+	}
+
+	private ListAssert> assertThatFilters() {
+		FilterChainProxy filterChain = this.spring.getContext().getBean(FilterChainProxy.class);
+		List> filters = filterChain.getFilters("/").stream().map(Object::getClass)
+				.collect(Collectors.toList());
+		return assertThat(filters);
+	}
+
 	@EnableWebSecurity
 	static class CustomFilterBeforeConfig extends WebSecurityConfigurerAdapter {
 
@@ -79,12 +110,6 @@ public class NamespaceHttpCustomFilterTests {
 
 	}
 
-	@Test
-	public void getFiltersWhenFilterAddedAfterThenBehaviorMatchesNamespace() {
-		this.spring.register(CustomFilterAfterConfig.class, UserDetailsServiceConfig.class).autowire();
-		assertThatFilters().containsSubsequence(UsernamePasswordAuthenticationFilter.class, CustomFilter.class);
-	}
-
 	@EnableWebSecurity
 	static class CustomFilterAfterConfig extends WebSecurityConfigurerAdapter {
 
@@ -99,12 +124,6 @@ public class NamespaceHttpCustomFilterTests {
 
 	}
 
-	@Test
-	public void getFiltersWhenFilterAddedThenBehaviorMatchesNamespace() {
-		this.spring.register(CustomFilterPositionConfig.class, UserDetailsServiceConfig.class).autowire();
-		assertThatFilters().containsExactly(CustomFilter.class);
-	}
-
 	@EnableWebSecurity
 	static class CustomFilterPositionConfig extends WebSecurityConfigurerAdapter {
 
@@ -125,12 +144,6 @@ public class NamespaceHttpCustomFilterTests {
 
 	}
 
-	@Test
-	public void getFiltersWhenFilterAddedAtPositionThenBehaviorMatchesNamespace() {
-		this.spring.register(CustomFilterPositionAtConfig.class, UserDetailsServiceConfig.class).autowire();
-		assertThatFilters().containsExactly(OtherCustomFilter.class);
-	}
-
 	@EnableWebSecurity
 	static class CustomFilterPositionAtConfig extends WebSecurityConfigurerAdapter {
 
@@ -149,12 +162,6 @@ public class NamespaceHttpCustomFilterTests {
 
 	}
 
-	@Test
-	public void getFiltersWhenCustomAuthenticationManagerThenBehaviorMatchesNamespace() {
-		this.spring.register(NoAuthenticationManagerInHttpConfigurationConfig.class).autowire();
-		assertThatFilters().startsWith(CustomFilter.class);
-	}
-
 	@EnableWebSecurity
 	static class NoAuthenticationManagerInHttpConfigurationConfig extends WebSecurityConfigurerAdapter {
 
@@ -220,11 +227,4 @@ public class NamespaceHttpCustomFilterTests {
 
 	}
 
-	private ListAssert> assertThatFilters() {
-		FilterChainProxy filterChain = this.spring.getContext().getBean(FilterChainProxy.class);
-		List> filters = filterChain.getFilters("/").stream().map(Object::getClass)
-				.collect(Collectors.toList());
-		return assertThat(filters);
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpExpressionHandlerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpExpressionHandlerTests.java
index eeab7c3e11..ac14a32ba3 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpExpressionHandlerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpExpressionHandlerTests.java
@@ -70,6 +70,10 @@ public class NamespaceHttpExpressionHandlerTests {
 		verifyBean("expressionParser", ExpressionParser.class).parseExpression("hasRole('USER')");
 	}
 
+	private  T verifyBean(String beanName, Class beanClass) {
+		return verify(this.spring.getContext().getBean(beanName, beanClass));
+	}
+
 	@EnableWebMvc
 	@EnableWebSecurity
 	private static class ExpressionHandlerConfig extends WebSecurityConfigurerAdapter {
@@ -115,8 +119,4 @@ public class NamespaceHttpExpressionHandlerTests {
 
 	}
 
-	private  T verifyBean(String beanName, Class beanClass) {
-		return verify(this.spring.getContext().getBean(beanName, beanClass));
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFirewallTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFirewallTests.java
index 146db2013d..7ddce408dd 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFirewallTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFirewallTests.java
@@ -56,11 +56,6 @@ public class NamespaceHttpFirewallTests {
 		assertThatCode(() -> this.mvc.perform(get("/public/../private/"))).isInstanceOf(RequestRejectedException.class);
 	}
 
-	@EnableWebSecurity
-	static class HttpFirewallConfig {
-
-	}
-
 	@Test
 	public void requestWithCustomFirewallThenBehaviorMatchesNamespace() {
 		this.rule.register(CustomHttpFirewallConfig.class).autowire();
@@ -68,6 +63,18 @@ public class NamespaceHttpFirewallTests {
 				.isInstanceOf(RequestRejectedException.class);
 	}
 
+	@Test
+	public void requestWithCustomFirewallBeanThenBehaviorMatchesNamespace() {
+		this.rule.register(CustomHttpFirewallBeanConfig.class).autowire();
+		assertThatCode(() -> this.mvc.perform(get("/").param("deny", "true")))
+				.isInstanceOf(RequestRejectedException.class);
+	}
+
+	@EnableWebSecurity
+	static class HttpFirewallConfig {
+
+	}
+
 	@EnableWebSecurity
 	static class CustomHttpFirewallConfig extends WebSecurityConfigurerAdapter {
 
@@ -78,13 +85,6 @@ public class NamespaceHttpFirewallTests {
 
 	}
 
-	@Test
-	public void requestWithCustomFirewallBeanThenBehaviorMatchesNamespace() {
-		this.rule.register(CustomHttpFirewallBeanConfig.class).autowire();
-		assertThatCode(() -> this.mvc.perform(get("/").param("deny", "true")))
-				.isInstanceOf(RequestRejectedException.class);
-	}
-
 	@EnableWebSecurity
 	static class CustomHttpFirewallBeanConfig {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFormLoginTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFormLoginTests.java
index 7dd2827975..6a8b15d8a2 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFormLoginTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFormLoginTests.java
@@ -71,6 +71,36 @@ public class NamespaceHttpFormLoginTests {
 				.andExpect(redirectedUrl("/"));
 	}
 
+	@Test
+	public void formLoginWithCustomEndpointsThenBehaviorMatchesNamespace() throws Exception {
+		this.spring.register(FormLoginCustomConfig.class, UserDetailsServiceConfig.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(redirectedUrl("http://localhost/authentication/login"));
+
+		this.mvc.perform(post("/authentication/login/process").with(csrf()))
+				.andExpect(redirectedUrl("/authentication/login?failed"));
+
+		this.mvc.perform(post("/authentication/login/process").param("username", "user").param("password", "password")
+				.with(csrf())).andExpect(redirectedUrl("/default"));
+	}
+
+	@Test
+	public void formLoginWithCustomHandlersThenBehaviorMatchesNamespace() throws Exception {
+		this.spring.register(FormLoginCustomRefsConfig.class, UserDetailsServiceConfig.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(redirectedUrl("http://localhost/login"));
+
+		this.mvc.perform(post("/login").with(csrf())).andExpect(redirectedUrl("/custom/failure"));
+		verifyBean(WebAuthenticationDetailsSource.class).buildDetails(any(HttpServletRequest.class));
+
+		this.mvc.perform(post("/login").param("username", "user").param("password", "password").with(csrf()))
+				.andExpect(redirectedUrl("/custom/targetUrl"));
+	}
+
+	private  T verifyBean(Class beanClass) {
+		return verify(this.spring.getContext().getBean(beanClass));
+	}
+
 	@EnableWebSecurity
 	static class FormLoginConfig extends WebSecurityConfigurerAdapter {
 
@@ -92,19 +122,6 @@ public class NamespaceHttpFormLoginTests {
 
 	}
 
-	@Test
-	public void formLoginWithCustomEndpointsThenBehaviorMatchesNamespace() throws Exception {
-		this.spring.register(FormLoginCustomConfig.class, UserDetailsServiceConfig.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(redirectedUrl("http://localhost/authentication/login"));
-
-		this.mvc.perform(post("/authentication/login/process").with(csrf()))
-				.andExpect(redirectedUrl("/authentication/login?failed"));
-
-		this.mvc.perform(post("/authentication/login/process").param("username", "user").param("password", "password")
-				.with(csrf())).andExpect(redirectedUrl("/default"));
-	}
-
 	@EnableWebSecurity
 	static class FormLoginCustomConfig extends WebSecurityConfigurerAdapter {
 
@@ -128,19 +145,6 @@ public class NamespaceHttpFormLoginTests {
 
 	}
 
-	@Test
-	public void formLoginWithCustomHandlersThenBehaviorMatchesNamespace() throws Exception {
-		this.spring.register(FormLoginCustomRefsConfig.class, UserDetailsServiceConfig.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(redirectedUrl("http://localhost/login"));
-
-		this.mvc.perform(post("/login").with(csrf())).andExpect(redirectedUrl("/custom/failure"));
-		verifyBean(WebAuthenticationDetailsSource.class).buildDetails(any(HttpServletRequest.class));
-
-		this.mvc.perform(post("/login").param("username", "user").param("password", "password").with(csrf()))
-				.andExpect(redirectedUrl("/custom/targetUrl"));
-	}
-
 	@EnableWebSecurity
 	static class FormLoginCustomRefsConfig extends WebSecurityConfigurerAdapter {
 
@@ -186,8 +190,4 @@ public class NamespaceHttpFormLoginTests {
 
 	}
 
-	private  T verifyBean(Class beanClass) {
-		return verify(this.spring.getContext().getBean(beanClass));
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpHeadersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpHeadersTests.java
index 7ffd4c2dc7..403791c13e 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpHeadersTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpHeadersTests.java
@@ -73,19 +73,6 @@ public class NamespaceHttpHeadersTests {
 		this.mvc.perform(get("/").secure(true)).andExpect(includesDefaults());
 	}
 
-	@EnableWebSecurity
-	static class HeadersDefaultConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void secureRequestWhenCacheControlOnlyThenBehaviorMatchesNamespace() throws Exception {
 		this.spring.register(HeadersCacheControlConfig.class).autowire();
@@ -93,21 +80,6 @@ public class NamespaceHttpHeadersTests {
 		this.mvc.perform(get("/").secure(true)).andExpect(includes("Cache-Control", "Expires", "Pragma"));
 	}
 
-	@EnableWebSecurity
-	static class HeadersCacheControlConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers()
-					.defaultsDisabled()
-					.cacheControl();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void secureRequestWhenHstsOnlyThenBehaviorMatchesNamespace() throws Exception {
 		this.spring.register(HstsConfig.class).autowire();
@@ -115,21 +87,6 @@ public class NamespaceHttpHeadersTests {
 		this.mvc.perform(get("/").secure(true)).andExpect(includes("Strict-Transport-Security"));
 	}
 
-	@EnableWebSecurity
-	static class HstsConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers()
-					.defaultsDisabled()
-					.httpStrictTransportSecurity();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void requestWhenHstsCustomThenBehaviorMatchesNamespace() throws Exception {
 		this.spring.register(HstsCustomConfig.class).autowire();
@@ -138,25 +95,6 @@ public class NamespaceHttpHeadersTests {
 				.andExpect(includes(Collections.singletonMap("Strict-Transport-Security", "max-age=15768000")));
 	}
 
-	@EnableWebSecurity
-	static class HstsCustomConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers()
-					// hsts@request-matcher-ref, hsts@max-age-seconds, hsts@include-subdomains
-					.defaultsDisabled()
-					.httpStrictTransportSecurity()
-						.requestMatcher(AnyRequestMatcher.INSTANCE)
-						.maxAgeInSeconds(15768000)
-						.includeSubDomains(false);
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void requestWhenFrameOptionsSameOriginThenBehaviorMatchesNamespace() throws Exception {
 		this.spring.register(FrameOptionsSameOriginConfig.class).autowire();
@@ -164,26 +102,6 @@ public class NamespaceHttpHeadersTests {
 		this.mvc.perform(get("/")).andExpect(includes(Collections.singletonMap("X-Frame-Options", "SAMEORIGIN")));
 	}
 
-	@EnableWebSecurity
-	static class FrameOptionsSameOriginConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers()
-					// frame-options@policy=SAMEORIGIN
-					.defaultsDisabled()
-					.frameOptions()
-						.sameOrigin();
-			// @formatter:on
-		}
-
-	}
-
-	// frame-options@strategy, frame-options@value, frame-options@parameter are not
-	// provided instead use frame-options@ref
-
 	@Test
 	public void requestWhenFrameOptionsAllowFromThenBehaviorMatchesNamespace() throws Exception {
 		this.spring.register(FrameOptionsAllowFromConfig.class).autowire();
@@ -192,23 +110,6 @@ public class NamespaceHttpHeadersTests {
 				.andExpect(includes(Collections.singletonMap("X-Frame-Options", "ALLOW-FROM https://example.com")));
 	}
 
-	@EnableWebSecurity
-	static class FrameOptionsAllowFromConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers()
-					// frame-options@ref
-					.defaultsDisabled()
-					.addHeaderWriter(new XFrameOptionsHeaderWriter(
-							new StaticAllowFromStrategy(URI.create("https://example.com"))));
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void requestWhenXssOnlyThenBehaviorMatchesNamespace() throws Exception {
 		this.spring.register(XssProtectionConfig.class).autowire();
@@ -216,22 +117,6 @@ public class NamespaceHttpHeadersTests {
 		this.mvc.perform(get("/")).andExpect(includes("X-XSS-Protection"));
 	}
 
-	@EnableWebSecurity
-	static class XssProtectionConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers()
-					// xss-protection
-					.defaultsDisabled()
-					.xssProtection();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void requestWhenXssCustomThenBehaviorMatchesNamespace() throws Exception {
 		this.spring.register(XssProtectionCustomConfig.class).autowire();
@@ -239,24 +124,6 @@ public class NamespaceHttpHeadersTests {
 		this.mvc.perform(get("/")).andExpect(includes(Collections.singletonMap("X-XSS-Protection", "1")));
 	}
 
-	@EnableWebSecurity
-	static class XssProtectionCustomConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers()
-					// xss-protection@enabled and xss-protection@block
-					.defaultsDisabled()
-					.xssProtection()
-						.xssProtectionEnabled(true)
-						.block(false);
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void requestWhenXContentTypeOptionsOnlyThenBehaviorMatchesNamespace() throws Exception {
 		this.spring.register(ContentTypeOptionsConfig.class).autowire();
@@ -264,24 +131,6 @@ public class NamespaceHttpHeadersTests {
 		this.mvc.perform(get("/")).andExpect(includes("X-Content-Type-Options"));
 	}
 
-	@EnableWebSecurity
-	static class ContentTypeOptionsConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers()
-					// content-type-options
-					.defaultsDisabled()
-					.contentTypeOptions();
-			// @formatter:on
-		}
-
-	}
-
-	// header@name / header@value are not provided instead use header@ref
-
 	@Test
 	public void requestWhenCustomHeaderOnlyThenBehaviorMatchesNamespace() throws Exception {
 		this.spring.register(HeaderRefConfig.class).autowire();
@@ -290,21 +139,6 @@ public class NamespaceHttpHeadersTests {
 				.andExpect(includes(Collections.singletonMap("customHeaderName", "customHeaderValue")));
 	}
 
-	@EnableWebSecurity
-	static class HeaderRefConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.headers()
-					.defaultsDisabled()
-					.addHeaderWriter(new StaticHeadersWriter("customHeaderName", "customHeaderValue"));
-			// @formatter:on
-		}
-
-	}
-
 	private static ResultMatcher includesDefaults() {
 		return includes(defaultHeaders);
 	}
@@ -326,4 +160,165 @@ public class NamespaceHttpHeadersTests {
 		};
 	}
 
+	@EnableWebSecurity
+	static class HeadersDefaultConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class HeadersCacheControlConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers()
+					.defaultsDisabled()
+					.cacheControl();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class HstsConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers()
+					.defaultsDisabled()
+					.httpStrictTransportSecurity();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class HstsCustomConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers()
+					// hsts@request-matcher-ref, hsts@max-age-seconds, hsts@include-subdomains
+					.defaultsDisabled()
+					.httpStrictTransportSecurity()
+						.requestMatcher(AnyRequestMatcher.INSTANCE)
+						.maxAgeInSeconds(15768000)
+						.includeSubDomains(false);
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class FrameOptionsSameOriginConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers()
+					// frame-options@policy=SAMEORIGIN
+					.defaultsDisabled()
+					.frameOptions()
+						.sameOrigin();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class FrameOptionsAllowFromConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers()
+					// frame-options@ref
+					.defaultsDisabled()
+					.addHeaderWriter(new XFrameOptionsHeaderWriter(
+							new StaticAllowFromStrategy(URI.create("https://example.com"))));
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class XssProtectionConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers()
+					// xss-protection
+					.defaultsDisabled()
+					.xssProtection();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class XssProtectionCustomConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers()
+					// xss-protection@enabled and xss-protection@block
+					.defaultsDisabled()
+					.xssProtection()
+						.xssProtectionEnabled(true)
+						.block(false);
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class ContentTypeOptionsConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers()
+					// content-type-options
+					.defaultsDisabled()
+					.contentTypeOptions();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class HeaderRefConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers()
+					.defaultsDisabled()
+					.addHeaderWriter(new StaticHeadersWriter("customHeaderName", "customHeaderValue"));
+			// @formatter:on
+		}
+
+	}
+
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpInterceptUrlTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpInterceptUrlTests.java
index 078c69053d..08dcf7f70c 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpInterceptUrlTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpInterceptUrlTests.java
@@ -100,6 +100,10 @@ public class NamespaceHttpInterceptUrlTests {
 		this.mvc.perform(get("https://localhost/user")).andExpect(redirectedUrl("http://localhost/user"));
 	}
 
+	private static Authentication user(String role) {
+		return new UsernamePasswordAuthenticationToken("user", null, AuthorityUtils.createAuthorityList(role));
+	}
+
 	@EnableWebSecurity
 	static class HttpInterceptUrlConfig extends WebSecurityConfigurerAdapter {
 
@@ -173,8 +177,4 @@ public class NamespaceHttpInterceptUrlTests {
 
 	}
 
-	private static Authentication user(String role) {
-		return new UsernamePasswordAuthenticationToken("user", null, AuthorityUtils.createAuthorityList(role));
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpJeeTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpJeeTests.java
index d62421f8fc..7cc239f3ab 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpJeeTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpJeeTests.java
@@ -73,23 +73,6 @@ public class NamespaceHttpJeeTests {
 		})).andExpect(status().isOk()).andExpect(content().string("ROLE_admin,ROLE_user"));
 	}
 
-	@EnableWebSecurity
-	public static class JeeMappableRolesConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.anyRequest().hasRole("user")
-					.and()
-				.jee()
-					.mappableRoles("user", "admin");
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void requestWhenCustomAuthenticatedUserDetailsServiceThenBehaviorMatchesNamespace() throws Exception {
 		this.spring.register(JeeUserServiceRefConfig.class, BaseController.class).autowire();
@@ -108,6 +91,31 @@ public class NamespaceHttpJeeTests {
 		verifyBean(AuthenticationUserDetailsService.class).loadUserDetails(any());
 	}
 
+	private  T bean(Class beanClass) {
+		return this.spring.getContext().getBean(beanClass);
+	}
+
+	private  T verifyBean(Class beanClass) {
+		return verify(this.spring.getContext().getBean(beanClass));
+	}
+
+	@EnableWebSecurity
+	public static class JeeMappableRolesConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("user")
+					.and()
+				.jee()
+					.mappableRoles("user", "admin");
+			// @formatter:on
+		}
+
+	}
+
 	@EnableWebSecurity
 	public static class JeeUserServiceRefConfig extends WebSecurityConfigurerAdapter {
 
@@ -149,12 +157,4 @@ public class NamespaceHttpJeeTests {
 
 	}
 
-	private  T bean(Class beanClass) {
-		return this.spring.getContext().getBean(beanClass);
-	}
-
-	private  T verifyBean(Class beanClass) {
-		return verify(this.spring.getContext().getBean(beanClass));
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.java
index 407499bfb1..5d56d6c05c 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.java
@@ -76,15 +76,6 @@ public class NamespaceHttpLogoutTests {
 				.andExpect(redirectedUrl("/login?logout")).andExpect(noCookies()).andExpect(session(Objects::isNull));
 	}
 
-	@EnableWebSecurity
-	static class HttpLogoutConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) {
-		}
-
-	}
-
 	@Test
 	@WithMockUser
 	public void logoutWhenDisabledInLambdaThenRespondsWithNotFound() throws Exception {
@@ -93,16 +84,6 @@ public class NamespaceHttpLogoutTests {
 		this.mvc.perform(post("/logout").with(csrf()).with(user("user"))).andExpect(status().isNotFound());
 	}
 
-	@EnableWebSecurity
-	static class HttpLogoutDisabledInLambdaConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			http.logout(AbstractHttpConfigurer::disable);
-		}
-
-	}
-
 	/**
 	 * http/logout custom
 	 */
@@ -117,6 +98,73 @@ public class NamespaceHttpLogoutTests {
 				.andExpect(cookie().maxAge("remove", 0)).andExpect(session(Objects::nonNull));
 	}
 
+	@Test
+	@WithMockUser
+	public void logoutWhenUsingVariousCustomizationsInLambdaThenMatchesNamespace() throws Exception {
+		this.spring.register(CustomHttpLogoutInLambdaConfig.class).autowire();
+
+		this.mvc.perform(post("/custom-logout").with(csrf())).andExpect(authenticated(false))
+				.andExpect(redirectedUrl("/logout-success"))
+				.andExpect(result -> assertThat(result.getResponse().getCookies()).hasSize(1))
+				.andExpect(cookie().maxAge("remove", 0)).andExpect(session(Objects::nonNull));
+	}
+
+	/**
+	 * http/logout@success-handler-ref
+	 */
+	@Test
+	@WithMockUser
+	public void logoutWhenUsingSuccessHandlerRefThenMatchesNamespace() throws Exception {
+		this.spring.register(SuccessHandlerRefHttpLogoutConfig.class).autowire();
+
+		this.mvc.perform(post("/logout").with(csrf())).andExpect(authenticated(false))
+				.andExpect(redirectedUrl("/SuccessHandlerRefHttpLogoutConfig")).andExpect(noCookies())
+				.andExpect(session(Objects::isNull));
+	}
+
+	@Test
+	@WithMockUser
+	public void logoutWhenUsingSuccessHandlerRefInLambdaThenMatchesNamespace() throws Exception {
+		this.spring.register(SuccessHandlerRefHttpLogoutInLambdaConfig.class).autowire();
+
+		this.mvc.perform(post("/logout").with(csrf())).andExpect(authenticated(false))
+				.andExpect(redirectedUrl("/SuccessHandlerRefHttpLogoutConfig")).andExpect(noCookies())
+				.andExpect(session(Objects::isNull));
+	}
+
+	ResultMatcher authenticated(boolean authenticated) {
+		return result -> assertThat(Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication())
+				.map(Authentication::isAuthenticated).orElse(false)).isEqualTo(authenticated);
+	}
+
+	ResultMatcher noCookies() {
+		return result -> assertThat(result.getResponse().getCookies()).isEmpty();
+	}
+
+	ResultMatcher session(Predicate sessionPredicate) {
+		return result -> assertThat(result.getRequest().getSession(false))
+				.is(new Condition<>(sessionPredicate, "sessionPredicate failed"));
+	}
+
+	@EnableWebSecurity
+	static class HttpLogoutConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) {
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class HttpLogoutDisabledInLambdaConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http.logout(AbstractHttpConfigurer::disable);
+		}
+
+	}
+
 	@EnableWebSecurity
 	static class CustomHttpLogoutConfig extends WebSecurityConfigurerAdapter {
 
@@ -134,17 +182,6 @@ public class NamespaceHttpLogoutTests {
 
 	}
 
-	@Test
-	@WithMockUser
-	public void logoutWhenUsingVariousCustomizationsInLambdaThenMatchesNamespace() throws Exception {
-		this.spring.register(CustomHttpLogoutInLambdaConfig.class).autowire();
-
-		this.mvc.perform(post("/custom-logout").with(csrf())).andExpect(authenticated(false))
-				.andExpect(redirectedUrl("/logout-success"))
-				.andExpect(result -> assertThat(result.getResponse().getCookies()).hasSize(1))
-				.andExpect(cookie().maxAge("remove", 0)).andExpect(session(Objects::nonNull));
-	}
-
 	@EnableWebSecurity
 	static class CustomHttpLogoutInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -163,19 +200,6 @@ public class NamespaceHttpLogoutTests {
 
 	}
 
-	/**
-	 * http/logout@success-handler-ref
-	 */
-	@Test
-	@WithMockUser
-	public void logoutWhenUsingSuccessHandlerRefThenMatchesNamespace() throws Exception {
-		this.spring.register(SuccessHandlerRefHttpLogoutConfig.class).autowire();
-
-		this.mvc.perform(post("/logout").with(csrf())).andExpect(authenticated(false))
-				.andExpect(redirectedUrl("/SuccessHandlerRefHttpLogoutConfig")).andExpect(noCookies())
-				.andExpect(session(Objects::isNull));
-	}
-
 	@EnableWebSecurity
 	static class SuccessHandlerRefHttpLogoutConfig extends WebSecurityConfigurerAdapter {
 
@@ -192,16 +216,6 @@ public class NamespaceHttpLogoutTests {
 
 	}
 
-	@Test
-	@WithMockUser
-	public void logoutWhenUsingSuccessHandlerRefInLambdaThenMatchesNamespace() throws Exception {
-		this.spring.register(SuccessHandlerRefHttpLogoutInLambdaConfig.class).autowire();
-
-		this.mvc.perform(post("/logout").with(csrf())).andExpect(authenticated(false))
-				.andExpect(redirectedUrl("/SuccessHandlerRefHttpLogoutConfig")).andExpect(noCookies())
-				.andExpect(session(Objects::isNull));
-	}
-
 	@EnableWebSecurity
 	static class SuccessHandlerRefHttpLogoutInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -218,18 +232,4 @@ public class NamespaceHttpLogoutTests {
 
 	}
 
-	ResultMatcher authenticated(boolean authenticated) {
-		return result -> assertThat(Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication())
-				.map(Authentication::isAuthenticated).orElse(false)).isEqualTo(authenticated);
-	}
-
-	ResultMatcher noCookies() {
-		return result -> assertThat(result.getResponse().getCookies()).isEmpty();
-	}
-
-	ResultMatcher session(Predicate sessionPredicate) {
-		return result -> assertThat(result.getRequest().getSession(false))
-				.is(new Condition<>(sessionPredicate, "sessionPredicate failed"));
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpOpenIDLoginTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpOpenIDLoginTests.java
index 1142c5d8f5..81133d4084 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpOpenIDLoginTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpOpenIDLoginTests.java
@@ -92,24 +92,6 @@ public class NamespaceHttpOpenIDLoginTests {
 		this.mvc.perform(post("/login/openid").with(csrf())).andExpect(redirectedUrl("/login?error"));
 	}
 
-	@Configuration
-	@EnableWebSecurity
-	static class OpenIDLoginConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.anyRequest().hasRole("USER")
-					.and()
-				.openidLogin()
-					.permitAll();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void openidLoginWhenAttributeExchangeConfiguredThenFetchAttributesMatchAttributeList() throws Exception {
 		OpenIDLoginAttributeExchangeConfig.CONSUMER_MANAGER = mock(ConsumerManager.class);
@@ -148,6 +130,59 @@ public class NamespaceHttpOpenIDLoginTests {
 		}
 	}
 
+	@Test
+	public void openidLoginWhenUsingCustomEndpointsThenMatchesNamespace() throws Exception {
+		this.spring.register(OpenIDLoginCustomConfig.class).autowire();
+		this.mvc.perform(get("/")).andExpect(redirectedUrl("http://localhost/authentication/login"));
+		this.mvc.perform(post("/authentication/login/process").with(csrf()))
+				.andExpect(redirectedUrl("/authentication/login?failed"));
+	}
+
+	@Test
+	public void openidLoginWithCustomHandlersThenBehaviorMatchesNamespace() throws Exception {
+		OpenIDAuthenticationToken token = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS,
+				"identityUrl", "message", Arrays.asList(new OpenIDAttribute("name", "type")));
+
+		OpenIDLoginCustomRefsConfig.AUDS = mock(AuthenticationUserDetailsService.class);
+		when(OpenIDLoginCustomRefsConfig.AUDS.loadUserDetails(any(Authentication.class)))
+				.thenReturn(new User("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER")));
+		OpenIDLoginCustomRefsConfig.ADS = spy(new WebAuthenticationDetailsSource());
+		OpenIDLoginCustomRefsConfig.CONSUMER = mock(OpenIDConsumer.class);
+
+		this.spring.register(OpenIDLoginCustomRefsConfig.class, UserDetailsServiceConfig.class).autowire();
+
+		when(OpenIDLoginCustomRefsConfig.CONSUMER.endConsumption(any(HttpServletRequest.class)))
+				.thenThrow(new AuthenticationServiceException("boom"));
+		this.mvc.perform(post("/login/openid").with(csrf()).param("openid.identity", "identity"))
+				.andExpect(redirectedUrl("/custom/failure"));
+		reset(OpenIDLoginCustomRefsConfig.CONSUMER);
+
+		when(OpenIDLoginCustomRefsConfig.CONSUMER.endConsumption(any(HttpServletRequest.class))).thenReturn(token);
+		this.mvc.perform(post("/login/openid").with(csrf()).param("openid.identity", "identity"))
+				.andExpect(redirectedUrl("/custom/targetUrl"));
+
+		verify(OpenIDLoginCustomRefsConfig.AUDS).loadUserDetails(any(Authentication.class));
+		verify(OpenIDLoginCustomRefsConfig.ADS).buildDetails(any(Object.class));
+	}
+
+	@Configuration
+	@EnableWebSecurity
+	static class OpenIDLoginConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.openidLogin()
+					.permitAll();
+			// @formatter:on
+		}
+
+	}
+
 	@Configuration
 	@EnableWebSecurity
 	static class OpenIDLoginAttributeExchangeConfig extends WebSecurityConfigurerAdapter {
@@ -194,14 +229,6 @@ public class NamespaceHttpOpenIDLoginTests {
 
 	}
 
-	@Test
-	public void openidLoginWhenUsingCustomEndpointsThenMatchesNamespace() throws Exception {
-		this.spring.register(OpenIDLoginCustomConfig.class).autowire();
-		this.mvc.perform(get("/")).andExpect(redirectedUrl("http://localhost/authentication/login"));
-		this.mvc.perform(post("/authentication/login/process").with(csrf()))
-				.andExpect(redirectedUrl("/authentication/login?failed"));
-	}
-
 	@Configuration
 	@EnableWebSecurity
 	static class OpenIDLoginCustomConfig extends WebSecurityConfigurerAdapter {
@@ -225,33 +252,6 @@ public class NamespaceHttpOpenIDLoginTests {
 
 	}
 
-	@Test
-	public void openidLoginWithCustomHandlersThenBehaviorMatchesNamespace() throws Exception {
-		OpenIDAuthenticationToken token = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS,
-				"identityUrl", "message", Arrays.asList(new OpenIDAttribute("name", "type")));
-
-		OpenIDLoginCustomRefsConfig.AUDS = mock(AuthenticationUserDetailsService.class);
-		when(OpenIDLoginCustomRefsConfig.AUDS.loadUserDetails(any(Authentication.class)))
-				.thenReturn(new User("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER")));
-		OpenIDLoginCustomRefsConfig.ADS = spy(new WebAuthenticationDetailsSource());
-		OpenIDLoginCustomRefsConfig.CONSUMER = mock(OpenIDConsumer.class);
-
-		this.spring.register(OpenIDLoginCustomRefsConfig.class, UserDetailsServiceConfig.class).autowire();
-
-		when(OpenIDLoginCustomRefsConfig.CONSUMER.endConsumption(any(HttpServletRequest.class)))
-				.thenThrow(new AuthenticationServiceException("boom"));
-		this.mvc.perform(post("/login/openid").with(csrf()).param("openid.identity", "identity"))
-				.andExpect(redirectedUrl("/custom/failure"));
-		reset(OpenIDLoginCustomRefsConfig.CONSUMER);
-
-		when(OpenIDLoginCustomRefsConfig.CONSUMER.endConsumption(any(HttpServletRequest.class))).thenReturn(token);
-		this.mvc.perform(post("/login/openid").with(csrf()).param("openid.identity", "identity"))
-				.andExpect(redirectedUrl("/custom/targetUrl"));
-
-		verify(OpenIDLoginCustomRefsConfig.AUDS).loadUserDetails(any(Authentication.class));
-		verify(OpenIDLoginCustomRefsConfig.ADS).buildDetails(any(Object.class));
-	}
-
 	@Configuration
 	@EnableWebSecurity
 	static class OpenIDLoginCustomRefsConfig extends WebSecurityConfigurerAdapter {
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpRequestCacheTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpRequestCacheTests.java
index dd6f0a250a..6969c377e1 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpRequestCacheTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpRequestCacheTests.java
@@ -64,6 +64,21 @@ public class NamespaceHttpRequestCacheTests {
 		verifyBean(RequestCache.class).saveRequest(any(HttpServletRequest.class), any(HttpServletResponse.class));
 	}
 
+	@Test
+	public void requestWhenDefaultConfigurationThenUsesHttpSessionRequestCache() throws Exception {
+		this.spring.register(DefaultRequestCacheRefConfig.class).autowire();
+
+		MvcResult result = this.mvc.perform(get("/")).andExpect(status().isForbidden()).andReturn();
+
+		HttpSession session = result.getRequest().getSession(false);
+		assertThat(session).isNotNull();
+		assertThat(session.getAttribute("SPRING_SECURITY_SAVED_REQUEST")).isNotNull();
+	}
+
+	private  T verifyBean(Class beanClass) {
+		return verify(this.spring.getContext().getBean(beanClass));
+	}
+
 	@EnableWebSecurity
 	static class RequestCacheRefConfig extends WebSecurityConfigurerAdapter {
 
@@ -96,17 +111,6 @@ public class NamespaceHttpRequestCacheTests {
 
 	}
 
-	@Test
-	public void requestWhenDefaultConfigurationThenUsesHttpSessionRequestCache() throws Exception {
-		this.spring.register(DefaultRequestCacheRefConfig.class).autowire();
-
-		MvcResult result = this.mvc.perform(get("/")).andExpect(status().isForbidden()).andReturn();
-
-		HttpSession session = result.getRequest().getSession(false);
-		assertThat(session).isNotNull();
-		assertThat(session.getAttribute("SPRING_SECURITY_SAVED_REQUEST")).isNotNull();
-	}
-
 	@EnableWebSecurity
 	static class DefaultRequestCacheRefConfig extends WebSecurityConfigurerAdapter {
 
@@ -131,8 +135,4 @@ public class NamespaceHttpRequestCacheTests {
 
 	}
 
-	private  T verifyBean(Class beanClass) {
-		return verify(this.spring.getContext().getBean(beanClass));
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpServerAccessDeniedHandlerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpServerAccessDeniedHandlerTests.java
index d5729357b6..76e422ac91 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpServerAccessDeniedHandlerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpServerAccessDeniedHandlerTests.java
@@ -65,6 +65,40 @@ public class NamespaceHttpServerAccessDeniedHandlerTests {
 				.andExpect(forwardedUrl("/AccessDeniedPageConfig"));
 	}
 
+	@Test
+	public void requestWhenCustomAccessDeniedPageInLambdaThenForwardedToCustomPage() throws Exception {
+		this.spring.register(AccessDeniedPageInLambdaConfig.class).autowire();
+
+		this.mvc.perform(get("/").with(authentication(user()))).andExpect(status().isForbidden())
+				.andExpect(forwardedUrl("/AccessDeniedPageConfig"));
+	}
+
+	@Test
+	public void requestWhenCustomAccessDeniedHandlerThenBehaviorMatchesNamespace() throws Exception {
+		this.spring.register(AccessDeniedHandlerRefConfig.class).autowire();
+		this.mvc.perform(get("/").with(authentication(user())));
+		verifyBean(AccessDeniedHandler.class).handle(any(HttpServletRequest.class), any(HttpServletResponse.class),
+				any(AccessDeniedException.class));
+	}
+
+	@Test
+	public void requestWhenCustomAccessDeniedHandlerInLambdaThenBehaviorMatchesNamespace() throws Exception {
+		this.spring.register(AccessDeniedHandlerRefInLambdaConfig.class).autowire();
+
+		this.mvc.perform(get("/").with(authentication(user())));
+
+		verify(AccessDeniedHandlerRefInLambdaConfig.accessDeniedHandler).handle(any(HttpServletRequest.class),
+				any(HttpServletResponse.class), any(AccessDeniedException.class));
+	}
+
+	private static Authentication user() {
+		return new UsernamePasswordAuthenticationToken("user", null, AuthorityUtils.NO_AUTHORITIES);
+	}
+
+	private  T verifyBean(Class beanClass) {
+		return verify(this.spring.getContext().getBean(beanClass));
+	}
+
 	@EnableWebSecurity
 	static class AccessDeniedPageConfig extends WebSecurityConfigurerAdapter {
 
@@ -82,18 +116,6 @@ public class NamespaceHttpServerAccessDeniedHandlerTests {
 
 	}
 
-	private static Authentication user() {
-		return new UsernamePasswordAuthenticationToken("user", null, AuthorityUtils.NO_AUTHORITIES);
-	}
-
-	@Test
-	public void requestWhenCustomAccessDeniedPageInLambdaThenForwardedToCustomPage() throws Exception {
-		this.spring.register(AccessDeniedPageInLambdaConfig.class).autowire();
-
-		this.mvc.perform(get("/").with(authentication(user()))).andExpect(status().isForbidden())
-				.andExpect(forwardedUrl("/AccessDeniedPageConfig"));
-	}
-
 	@EnableWebSecurity
 	static class AccessDeniedPageInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -113,14 +135,6 @@ public class NamespaceHttpServerAccessDeniedHandlerTests {
 
 	}
 
-	@Test
-	public void requestWhenCustomAccessDeniedHandlerThenBehaviorMatchesNamespace() throws Exception {
-		this.spring.register(AccessDeniedHandlerRefConfig.class).autowire();
-		this.mvc.perform(get("/").with(authentication(user())));
-		verifyBean(AccessDeniedHandler.class).handle(any(HttpServletRequest.class), any(HttpServletResponse.class),
-				any(AccessDeniedException.class));
-	}
-
 	@EnableWebSecurity
 	static class AccessDeniedHandlerRefConfig extends WebSecurityConfigurerAdapter {
 
@@ -143,16 +157,6 @@ public class NamespaceHttpServerAccessDeniedHandlerTests {
 
 	}
 
-	@Test
-	public void requestWhenCustomAccessDeniedHandlerInLambdaThenBehaviorMatchesNamespace() throws Exception {
-		this.spring.register(AccessDeniedHandlerRefInLambdaConfig.class).autowire();
-
-		this.mvc.perform(get("/").with(authentication(user())));
-
-		verify(AccessDeniedHandlerRefInLambdaConfig.accessDeniedHandler).handle(any(HttpServletRequest.class),
-				any(HttpServletResponse.class), any(AccessDeniedException.class));
-	}
-
 	@EnableWebSecurity
 	static class AccessDeniedHandlerRefInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -179,8 +183,4 @@ public class NamespaceHttpServerAccessDeniedHandlerTests {
 
 	}
 
-	private  T verifyBean(Class beanClass) {
-		return verify(this.spring.getContext().getBean(beanClass));
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.java
index b6a997ba33..74cc76cd4d 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.java
@@ -77,6 +77,58 @@ public class NamespaceHttpX509Tests {
 		this.mvc.perform(get("/whoami").with(x509(certificate))).andExpect(content().string("rod"));
 	}
 
+	@Test
+	public void x509AuthenticationWhenHasCustomAuthenticationDetailsSourceThenMatchesNamespace() throws Exception {
+		this.spring.register(AuthenticationDetailsSourceRefConfig.class, X509Controller.class).autowire();
+
+		X509Certificate certificate = loadCert("rod.cer");
+		this.mvc.perform(get("/whoami").with(x509(certificate))).andExpect(content().string("rod"));
+
+		verifyBean(AuthenticationDetailsSource.class).buildDetails(any());
+	}
+
+	@Test
+	public void x509AuthenticationWhenHasSubjectPrincipalRegexThenMatchesNamespace() throws Exception {
+		this.spring.register(SubjectPrincipalRegexConfig.class, X509Controller.class).autowire();
+		X509Certificate certificate = loadCert("rodatexampledotcom.cer");
+		this.mvc.perform(get("/whoami").with(x509(certificate))).andExpect(content().string("rod"));
+	}
+
+	@Test
+	public void x509AuthenticationWhenHasCustomPrincipalExtractorThenMatchesNamespace() throws Exception {
+		this.spring.register(CustomPrincipalExtractorConfig.class, X509Controller.class).autowire();
+		X509Certificate certificate = loadCert("rodatexampledotcom.cer");
+		this.mvc.perform(get("/whoami").with(x509(certificate))).andExpect(content().string("rod@example.com"));
+	}
+
+	@Test
+	public void x509AuthenticationWhenHasCustomUserDetailsServiceThenMatchesNamespace() throws Exception {
+		this.spring.register(UserDetailsServiceRefConfig.class, X509Controller.class).autowire();
+		X509Certificate certificate = loadCert("rodatexampledotcom.cer");
+		this.mvc.perform(get("/whoami").with(x509(certificate))).andExpect(content().string("customuser"));
+	}
+
+	@Test
+	public void x509AuthenticationWhenHasCustomAuthenticationUserDetailsServiceThenMatchesNamespace() throws Exception {
+		this.spring.register(AuthenticationUserDetailsServiceConfig.class, X509Controller.class).autowire();
+		X509Certificate certificate = loadCert("rodatexampledotcom.cer");
+		this.mvc.perform(get("/whoami").with(x509(certificate))).andExpect(content().string("customuser"));
+	}
+
+	 T loadCert(String location) {
+		try (InputStream is = new ClassPathResource(location).getInputStream()) {
+			CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+			return (T) certFactory.generateCertificate(is);
+		}
+		catch (Exception e) {
+			throw new IllegalArgumentException(e);
+		}
+	}
+
+	 T verifyBean(Class beanClass) {
+		return verify(this.spring.getContext().getBean(beanClass));
+	}
+
 	@EnableWebSecurity
 	@EnableWebMvc
 	public static class X509Config extends WebSecurityConfigurerAdapter {
@@ -103,16 +155,6 @@ public class NamespaceHttpX509Tests {
 
 	}
 
-	@Test
-	public void x509AuthenticationWhenHasCustomAuthenticationDetailsSourceThenMatchesNamespace() throws Exception {
-		this.spring.register(AuthenticationDetailsSourceRefConfig.class, X509Controller.class).autowire();
-
-		X509Certificate certificate = loadCert("rod.cer");
-		this.mvc.perform(get("/whoami").with(x509(certificate))).andExpect(content().string("rod"));
-
-		verifyBean(AuthenticationDetailsSource.class).buildDetails(any());
-	}
-
 	@EnableWebSecurity
 	@EnableWebMvc
 	static class AuthenticationDetailsSourceRefConfig extends WebSecurityConfigurerAdapter {
@@ -146,13 +188,6 @@ public class NamespaceHttpX509Tests {
 
 	}
 
-	@Test
-	public void x509AuthenticationWhenHasSubjectPrincipalRegexThenMatchesNamespace() throws Exception {
-		this.spring.register(SubjectPrincipalRegexConfig.class, X509Controller.class).autowire();
-		X509Certificate certificate = loadCert("rodatexampledotcom.cer");
-		this.mvc.perform(get("/whoami").with(x509(certificate))).andExpect(content().string("rod"));
-	}
-
 	@EnableWebMvc
 	@EnableWebSecurity
 	public static class SubjectPrincipalRegexConfig extends WebSecurityConfigurerAdapter {
@@ -180,13 +215,6 @@ public class NamespaceHttpX509Tests {
 
 	}
 
-	@Test
-	public void x509AuthenticationWhenHasCustomPrincipalExtractorThenMatchesNamespace() throws Exception {
-		this.spring.register(CustomPrincipalExtractorConfig.class, X509Controller.class).autowire();
-		X509Certificate certificate = loadCert("rodatexampledotcom.cer");
-		this.mvc.perform(get("/whoami").with(x509(certificate))).andExpect(content().string("rod@example.com"));
-	}
-
 	@EnableWebMvc
 	@EnableWebSecurity
 	public static class CustomPrincipalExtractorConfig extends WebSecurityConfigurerAdapter {
@@ -223,13 +251,6 @@ public class NamespaceHttpX509Tests {
 
 	}
 
-	@Test
-	public void x509AuthenticationWhenHasCustomUserDetailsServiceThenMatchesNamespace() throws Exception {
-		this.spring.register(UserDetailsServiceRefConfig.class, X509Controller.class).autowire();
-		X509Certificate certificate = loadCert("rodatexampledotcom.cer");
-		this.mvc.perform(get("/whoami").with(x509(certificate))).andExpect(content().string("customuser"));
-	}
-
 	@EnableWebMvc
 	@EnableWebSecurity
 	public static class UserDetailsServiceRefConfig extends WebSecurityConfigurerAdapter {
@@ -257,13 +278,6 @@ public class NamespaceHttpX509Tests {
 
 	}
 
-	@Test
-	public void x509AuthenticationWhenHasCustomAuthenticationUserDetailsServiceThenMatchesNamespace() throws Exception {
-		this.spring.register(AuthenticationUserDetailsServiceConfig.class, X509Controller.class).autowire();
-		X509Certificate certificate = loadCert("rodatexampledotcom.cer");
-		this.mvc.perform(get("/whoami").with(x509(certificate))).andExpect(content().string("customuser"));
-	}
-
 	@EnableWebMvc
 	@EnableWebSecurity
 	public static class AuthenticationUserDetailsServiceConfig extends WebSecurityConfigurerAdapter {
@@ -297,18 +311,4 @@ public class NamespaceHttpX509Tests {
 
 	}
 
-	 T loadCert(String location) {
-		try (InputStream is = new ClassPathResource(location).getInputStream()) {
-			CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
-			return (T) certFactory.generateCertificate(is);
-		}
-		catch (Exception e) {
-			throw new IllegalArgumentException(e);
-		}
-	}
-
-	 T verifyBean(Class beanClass) {
-		return verify(this.spring.getContext().getBean(beanClass));
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.java
index aeac564a92..548c700491 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.java
@@ -98,6 +98,160 @@ public class NamespaceRememberMeTests {
 				.andExpect(redirectedUrl("http://localhost/login")).andReturn();
 	}
 
+	// SEC-3170 - RememberMeService implementations should not have to also implement
+	// LogoutHandler
+	@Test
+	public void logoutWhenCustomRememberMeServicesDeclaredThenUses() throws Exception {
+		RememberMeServicesRefConfig.REMEMBER_ME_SERVICES = mock(RememberMeServicesWithoutLogoutHandler.class);
+		this.spring.register(RememberMeServicesRefConfig.class).autowire();
+
+		this.mvc.perform(get("/"));
+		verify(RememberMeServicesRefConfig.REMEMBER_ME_SERVICES).autoLogin(any(HttpServletRequest.class),
+				any(HttpServletResponse.class));
+
+		this.mvc.perform(post("/login").with(csrf()));
+		verify(RememberMeServicesRefConfig.REMEMBER_ME_SERVICES).loginFail(any(HttpServletRequest.class),
+				any(HttpServletResponse.class));
+	}
+
+	@Test
+	public void rememberMeLoginWhenAuthenticationSuccessHandlerDeclaredThenUses() throws Exception {
+		AuthSuccessConfig.SUCCESS_HANDLER = mock(AuthenticationSuccessHandler.class);
+		this.spring.register(AuthSuccessConfig.class).autowire();
+
+		MvcResult result = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn();
+
+		verifyZeroInteractions(AuthSuccessConfig.SUCCESS_HANDLER);
+
+		Cookie rememberMe = result.getResponse().getCookie("remember-me");
+		assertThat(rememberMe).isNotNull();
+		this.mvc.perform(get("/somewhere").cookie(rememberMe));
+
+		verify(AuthSuccessConfig.SUCCESS_HANDLER).onAuthenticationSuccess(any(HttpServletRequest.class),
+				any(HttpServletResponse.class), any(Authentication.class));
+	}
+
+	@Test
+	public void rememberMeLoginWhenKeyDeclaredThenMatchesNamespace() throws Exception {
+		this.spring.register(WithoutKeyConfig.class, KeyConfig.class, SecurityController.class).autowire();
+		Cookie withoutKey = this.mvc.perform(post("/without-key/login").with(rememberMeLogin()))
+				.andExpect(redirectedUrl("/")).andReturn().getResponse().getCookie("remember-me");
+
+		this.mvc.perform(get("/somewhere").cookie(withoutKey)).andExpect(status().isFound())
+				.andExpect(redirectedUrl("http://localhost/login"));
+
+		Cookie withKey = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn().getResponse()
+				.getCookie("remember-me");
+		this.mvc.perform(get("/somewhere").cookie(withKey)).andExpect(status().isNotFound());
+	}
+
+	// http/remember-me@services-alias is not supported use standard aliasing instead
+	// (i.e. @Bean("alias"))
+
+	// http/remember-me@data-source-ref is not supported directly. Instead use
+	// http/remember-me@token-repository-ref example
+	@Test
+	public void rememberMeLoginWhenDeclaredTokenRepositoryThenMatchesNamespace() throws Exception {
+		TokenRepositoryRefConfig.TOKEN_REPOSITORY = mock(PersistentTokenRepository.class);
+		this.spring.register(TokenRepositoryRefConfig.class).autowire();
+
+		this.mvc.perform(post("/login").with(rememberMeLogin()));
+
+		verify(TokenRepositoryRefConfig.TOKEN_REPOSITORY).createNewToken(any(PersistentRememberMeToken.class));
+	}
+
+	@Test
+	public void rememberMeLoginWhenTokenValidityDeclaredThenMatchesNamespace() throws Exception {
+		this.spring.register(TokenValiditySecondsConfig.class).autowire();
+		Cookie expiredRememberMe = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn().getResponse()
+				.getCookie("remember-me");
+
+		assertThat(expiredRememberMe).extracting(Cookie::getMaxAge).isEqualTo(314);
+	}
+
+	@Test
+	public void rememberMeLoginWhenUsingDefaultsThenCookieMaxAgeMatchesNamespace() throws Exception {
+		this.spring.register(RememberMeConfig.class).autowire();
+		Cookie expiredRememberMe = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn().getResponse()
+				.getCookie("remember-me");
+
+		assertThat(expiredRememberMe).extracting(Cookie::getMaxAge).isEqualTo(AbstractRememberMeServices.TWO_WEEKS_S);
+	}
+
+	@Test
+	public void rememberMeLoginWhenUsingSecureCookieThenMatchesNamespace() throws Exception {
+		this.spring.register(UseSecureCookieConfig.class).autowire();
+		Cookie secureCookie = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn().getResponse()
+				.getCookie("remember-me");
+
+		assertThat(secureCookie).extracting(Cookie::getSecure).isEqualTo(true);
+	}
+
+	@Test
+	public void rememberMeLoginWhenUsingDefaultsThenCookieSecurityMatchesNamespace() throws Exception {
+		this.spring.register(RememberMeConfig.class).autowire();
+		Cookie secureCookie = this.mvc.perform(post("/login").with(rememberMeLogin()).secure(true)).andReturn()
+				.getResponse().getCookie("remember-me");
+
+		assertThat(secureCookie).extracting(Cookie::getSecure).isEqualTo(true);
+	}
+
+	@Test
+	public void rememberMeLoginWhenParameterSpecifiedThenMatchesNamespace() throws Exception {
+		this.spring.register(RememberMeParameterConfig.class).autowire();
+		Cookie rememberMe = this.mvc.perform(post("/login").with(rememberMeLogin("rememberMe", true))).andReturn()
+				.getResponse().getCookie("remember-me");
+
+		assertThat(rememberMe).isNotNull();
+	}
+
+	// SEC-2880
+	@Test
+	public void rememberMeLoginWhenCookieNameDeclaredThenMatchesNamespace() throws Exception {
+		this.spring.register(RememberMeCookieNameConfig.class).autowire();
+		Cookie rememberMe = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn().getResponse()
+				.getCookie("rememberMe");
+
+		assertThat(rememberMe).isNotNull();
+	}
+
+	@Test
+	public void rememberMeLoginWhenGlobalUserDetailsServiceDeclaredThenMatchesNamespace() throws Exception {
+		DefaultsUserDetailsServiceWithDaoConfig.USERDETAILS_SERVICE = mock(UserDetailsService.class);
+		this.spring.register(DefaultsUserDetailsServiceWithDaoConfig.class).autowire();
+
+		this.mvc.perform(post("/login").with(rememberMeLogin()));
+
+		verify(DefaultsUserDetailsServiceWithDaoConfig.USERDETAILS_SERVICE).loadUserByUsername("user");
+	}
+
+	@Test
+	public void rememberMeLoginWhenUserDetailsServiceDeclaredThenMatchesNamespace() throws Exception {
+		UserServiceRefConfig.USERDETAILS_SERVICE = mock(UserDetailsService.class);
+		this.spring.register(UserServiceRefConfig.class).autowire();
+
+		when(UserServiceRefConfig.USERDETAILS_SERVICE.loadUserByUsername("user"))
+				.thenReturn(new User("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER")));
+
+		this.mvc.perform(post("/login").with(rememberMeLogin()));
+
+		verify(UserServiceRefConfig.USERDETAILS_SERVICE).loadUserByUsername("user");
+	}
+
+	static RequestPostProcessor rememberMeLogin() {
+		return rememberMeLogin("remember-me", true);
+	}
+
+	static RequestPostProcessor rememberMeLogin(String parameterName, boolean parameterValue) {
+		return request -> {
+			csrf().postProcessRequest(request);
+			request.setParameter("username", "user");
+			request.setParameter("password", "password");
+			request.setParameter(parameterName, String.valueOf(parameterValue));
+			return request;
+		};
+	}
+
 	@Configuration
 	@EnableWebSecurity
 	static class RememberMeConfig extends UsersConfig {
@@ -117,22 +271,6 @@ public class NamespaceRememberMeTests {
 
 	}
 
-	// SEC-3170 - RememberMeService implementations should not have to also implement
-	// LogoutHandler
-	@Test
-	public void logoutWhenCustomRememberMeServicesDeclaredThenUses() throws Exception {
-		RememberMeServicesRefConfig.REMEMBER_ME_SERVICES = mock(RememberMeServicesWithoutLogoutHandler.class);
-		this.spring.register(RememberMeServicesRefConfig.class).autowire();
-
-		this.mvc.perform(get("/"));
-		verify(RememberMeServicesRefConfig.REMEMBER_ME_SERVICES).autoLogin(any(HttpServletRequest.class),
-				any(HttpServletResponse.class));
-
-		this.mvc.perform(post("/login").with(csrf()));
-		verify(RememberMeServicesRefConfig.REMEMBER_ME_SERVICES).loginFail(any(HttpServletRequest.class),
-				any(HttpServletResponse.class));
-	}
-
 	interface RememberMeServicesWithoutLogoutHandler extends RememberMeServices {
 
 	}
@@ -156,23 +294,6 @@ public class NamespaceRememberMeTests {
 
 	}
 
-	@Test
-	public void rememberMeLoginWhenAuthenticationSuccessHandlerDeclaredThenUses() throws Exception {
-		AuthSuccessConfig.SUCCESS_HANDLER = mock(AuthenticationSuccessHandler.class);
-		this.spring.register(AuthSuccessConfig.class).autowire();
-
-		MvcResult result = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn();
-
-		verifyZeroInteractions(AuthSuccessConfig.SUCCESS_HANDLER);
-
-		Cookie rememberMe = result.getResponse().getCookie("remember-me");
-		assertThat(rememberMe).isNotNull();
-		this.mvc.perform(get("/somewhere").cookie(rememberMe));
-
-		verify(AuthSuccessConfig.SUCCESS_HANDLER).onAuthenticationSuccess(any(HttpServletRequest.class),
-				any(HttpServletResponse.class), any(Authentication.class));
-	}
-
 	@Configuration
 	@EnableWebSecurity
 	static class AuthSuccessConfig extends UsersConfig {
@@ -192,20 +313,6 @@ public class NamespaceRememberMeTests {
 
 	}
 
-	@Test
-	public void rememberMeLoginWhenKeyDeclaredThenMatchesNamespace() throws Exception {
-		this.spring.register(WithoutKeyConfig.class, KeyConfig.class, SecurityController.class).autowire();
-		Cookie withoutKey = this.mvc.perform(post("/without-key/login").with(rememberMeLogin()))
-				.andExpect(redirectedUrl("/")).andReturn().getResponse().getCookie("remember-me");
-
-		this.mvc.perform(get("/somewhere").cookie(withoutKey)).andExpect(status().isFound())
-				.andExpect(redirectedUrl("http://localhost/login"));
-
-		Cookie withKey = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn().getResponse()
-				.getCookie("remember-me");
-		this.mvc.perform(get("/somewhere").cookie(withKey)).andExpect(status().isNotFound());
-	}
-
 	@Configuration
 	@EnableWebSecurity
 	@Order(0)
@@ -245,21 +352,6 @@ public class NamespaceRememberMeTests {
 
 	}
 
-	// http/remember-me@services-alias is not supported use standard aliasing instead
-	// (i.e. @Bean("alias"))
-
-	// http/remember-me@data-source-ref is not supported directly. Instead use
-	// http/remember-me@token-repository-ref example
-	@Test
-	public void rememberMeLoginWhenDeclaredTokenRepositoryThenMatchesNamespace() throws Exception {
-		TokenRepositoryRefConfig.TOKEN_REPOSITORY = mock(PersistentTokenRepository.class);
-		this.spring.register(TokenRepositoryRefConfig.class).autowire();
-
-		this.mvc.perform(post("/login").with(rememberMeLogin()));
-
-		verify(TokenRepositoryRefConfig.TOKEN_REPOSITORY).createNewToken(any(PersistentRememberMeToken.class));
-	}
-
 	@Configuration
 	@EnableWebSecurity
 	static class TokenRepositoryRefConfig extends UsersConfig {
@@ -282,15 +374,6 @@ public class NamespaceRememberMeTests {
 
 	}
 
-	@Test
-	public void rememberMeLoginWhenTokenValidityDeclaredThenMatchesNamespace() throws Exception {
-		this.spring.register(TokenValiditySecondsConfig.class).autowire();
-		Cookie expiredRememberMe = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn().getResponse()
-				.getCookie("remember-me");
-
-		assertThat(expiredRememberMe).extracting(Cookie::getMaxAge).isEqualTo(314);
-	}
-
 	@Configuration
 	@EnableWebSecurity
 	static class TokenValiditySecondsConfig extends UsersConfig {
@@ -311,24 +394,6 @@ public class NamespaceRememberMeTests {
 
 	}
 
-	@Test
-	public void rememberMeLoginWhenUsingDefaultsThenCookieMaxAgeMatchesNamespace() throws Exception {
-		this.spring.register(RememberMeConfig.class).autowire();
-		Cookie expiredRememberMe = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn().getResponse()
-				.getCookie("remember-me");
-
-		assertThat(expiredRememberMe).extracting(Cookie::getMaxAge).isEqualTo(AbstractRememberMeServices.TWO_WEEKS_S);
-	}
-
-	@Test
-	public void rememberMeLoginWhenUsingSecureCookieThenMatchesNamespace() throws Exception {
-		this.spring.register(UseSecureCookieConfig.class).autowire();
-		Cookie secureCookie = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn().getResponse()
-				.getCookie("remember-me");
-
-		assertThat(secureCookie).extracting(Cookie::getSecure).isEqualTo(true);
-	}
-
 	@Configuration
 	@EnableWebSecurity
 	static class UseSecureCookieConfig extends UsersConfig {
@@ -346,24 +411,6 @@ public class NamespaceRememberMeTests {
 
 	}
 
-	@Test
-	public void rememberMeLoginWhenUsingDefaultsThenCookieSecurityMatchesNamespace() throws Exception {
-		this.spring.register(RememberMeConfig.class).autowire();
-		Cookie secureCookie = this.mvc.perform(post("/login").with(rememberMeLogin()).secure(true)).andReturn()
-				.getResponse().getCookie("remember-me");
-
-		assertThat(secureCookie).extracting(Cookie::getSecure).isEqualTo(true);
-	}
-
-	@Test
-	public void rememberMeLoginWhenParameterSpecifiedThenMatchesNamespace() throws Exception {
-		this.spring.register(RememberMeParameterConfig.class).autowire();
-		Cookie rememberMe = this.mvc.perform(post("/login").with(rememberMeLogin("rememberMe", true))).andReturn()
-				.getResponse().getCookie("remember-me");
-
-		assertThat(rememberMe).isNotNull();
-	}
-
 	@Configuration
 	@EnableWebSecurity
 	static class RememberMeParameterConfig extends UsersConfig {
@@ -381,17 +428,6 @@ public class NamespaceRememberMeTests {
 
 	}
 
-	// SEC-2880
-
-	@Test
-	public void rememberMeLoginWhenCookieNameDeclaredThenMatchesNamespace() throws Exception {
-		this.spring.register(RememberMeCookieNameConfig.class).autowire();
-		Cookie rememberMe = this.mvc.perform(post("/login").with(rememberMeLogin())).andReturn().getResponse()
-				.getCookie("rememberMe");
-
-		assertThat(rememberMe).isNotNull();
-	}
-
 	@Configuration
 	@EnableWebSecurity
 	static class RememberMeCookieNameConfig extends UsersConfig {
@@ -409,16 +445,6 @@ public class NamespaceRememberMeTests {
 
 	}
 
-	@Test
-	public void rememberMeLoginWhenGlobalUserDetailsServiceDeclaredThenMatchesNamespace() throws Exception {
-		DefaultsUserDetailsServiceWithDaoConfig.USERDETAILS_SERVICE = mock(UserDetailsService.class);
-		this.spring.register(DefaultsUserDetailsServiceWithDaoConfig.class).autowire();
-
-		this.mvc.perform(post("/login").with(rememberMeLogin()));
-
-		verify(DefaultsUserDetailsServiceWithDaoConfig.USERDETAILS_SERVICE).loadUserByUsername("user");
-	}
-
 	@EnableWebSecurity
 	@Configuration
 	static class DefaultsUserDetailsServiceWithDaoConfig extends WebSecurityConfigurerAdapter {
@@ -445,19 +471,6 @@ public class NamespaceRememberMeTests {
 
 	}
 
-	@Test
-	public void rememberMeLoginWhenUserDetailsServiceDeclaredThenMatchesNamespace() throws Exception {
-		UserServiceRefConfig.USERDETAILS_SERVICE = mock(UserDetailsService.class);
-		this.spring.register(UserServiceRefConfig.class).autowire();
-
-		when(UserServiceRefConfig.USERDETAILS_SERVICE.loadUserByUsername("user"))
-				.thenReturn(new User("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER")));
-
-		this.mvc.perform(post("/login").with(rememberMeLogin()));
-
-		verify(UserServiceRefConfig.USERDETAILS_SERVICE).loadUserByUsername("user");
-	}
-
 	@Configuration
 	@EnableWebSecurity
 	static class UserServiceRefConfig extends UsersConfig {
@@ -477,20 +490,6 @@ public class NamespaceRememberMeTests {
 
 	}
 
-	static RequestPostProcessor rememberMeLogin() {
-		return rememberMeLogin("remember-me", true);
-	}
-
-	static RequestPostProcessor rememberMeLogin(String parameterName, boolean parameterValue) {
-		return request -> {
-			csrf().postProcessRequest(request);
-			request.setParameter("username", "user");
-			request.setParameter("password", "password");
-			request.setParameter(parameterName, String.valueOf(parameterValue));
-			return request;
-		};
-	}
-
 	static class UsersConfig extends WebSecurityConfigurerAdapter {
 
 		@Override
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.java
index ee6dad15e1..4cea822c91 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.java
@@ -91,11 +91,6 @@ public class NamespaceSessionManagementTests {
 		assertThat(result.getRequest().getSession(false).getId()).isNotEqualTo(sessionId);
 	}
 
-	@EnableWebSecurity
-	static class SessionManagementConfig extends WebSecurityConfigurerAdapter {
-
-	}
-
 	@Test
 	public void authenticateWhenUsingInvalidSessionUrlThenMatchesNamespace() throws Exception {
 		this.spring.register(CustomSessionManagementConfig.class).autowire();
@@ -157,6 +152,104 @@ public class NamespaceSessionManagementTests {
 		verify(sessionRegistry).registerNewSession(any(String.class), any(Object.class));
 	}
 
+	// gh-3371
+	@Test
+	public void authenticateWhenUsingCustomInvalidSessionStrategyThenMatchesNamespace() throws Exception {
+		this.spring.register(InvalidSessionStrategyConfig.class).autowire();
+
+		this.mvc.perform(get("/auth").with(request -> {
+			request.setRequestedSessionIdValid(false);
+			request.setRequestedSessionId("id");
+			return request;
+		})).andExpect(status().isOk());
+
+		verifyBean(InvalidSessionStrategy.class).onInvalidSessionDetected(any(HttpServletRequest.class),
+				any(HttpServletResponse.class));
+	}
+
+	@Test
+	public void authenticateWhenUsingCustomSessionAuthenticationStrategyThenMatchesNamespace() throws Exception {
+		this.spring.register(RefsSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class)
+				.autowire();
+
+		this.mvc.perform(get("/auth").with(httpBasic("user", "password"))).andExpect(status().isOk());
+
+		verifyBean(SessionAuthenticationStrategy.class).onAuthentication(any(Authentication.class),
+				any(HttpServletRequest.class), any(HttpServletResponse.class));
+	}
+
+	@Test
+	public void authenticateWhenNoSessionFixationProtectionThenMatchesNamespace() throws Exception {
+		this.spring
+				.register(SFPNoneSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class)
+				.autowire();
+
+		MockHttpSession givenSession = new MockHttpSession();
+		String givenSessionId = givenSession.getId();
+		MockHttpSession resultingSession = (MockHttpSession) this.mvc
+				.perform(get("/auth").session(givenSession).with(httpBasic("user", "password")))
+				.andExpect(status().isOk()).andReturn().getRequest().getSession(false);
+
+		assertThat(givenSessionId).isEqualTo(resultingSession.getId());
+	}
+
+	@Test
+	public void authenticateWhenMigrateSessionFixationProtectionThenMatchesNamespace() throws Exception {
+		this.spring.register(SFPMigrateSessionManagementConfig.class, BasicController.class,
+				UserDetailsServiceConfig.class).autowire();
+
+		MockHttpSession givenSession = new MockHttpSession();
+		String givenSessionId = givenSession.getId();
+		givenSession.setAttribute("name", "value");
+
+		MockHttpSession resultingSession = (MockHttpSession) this.mvc
+				.perform(get("/auth").session(givenSession).with(httpBasic("user", "password")))
+				.andExpect(status().isOk()).andReturn().getRequest().getSession(false);
+
+		assertThat(givenSessionId).isNotEqualTo(resultingSession.getId());
+		assertThat(resultingSession.getAttribute("name")).isEqualTo("value");
+	}
+
+	// SEC-2913
+	@Test
+	public void authenticateWhenUsingSessionFixationProtectionThenUsesNonNullEventPublisher() throws Exception {
+		this.spring.register(SFPPostProcessedConfig.class, UserDetailsServiceConfig.class).autowire();
+
+		this.mvc.perform(get("/auth").session(new MockHttpSession()).with(httpBasic("user", "password")))
+				.andExpect(status().isNotFound());
+
+		verifyBean(MockEventListener.class).onApplicationEvent(any(SessionFixationProtectionEvent.class));
+	}
+
+	@Test
+	public void authenticateWhenNewSessionFixationProtectionThenMatchesNamespace() throws Exception {
+		this.spring.register(SFPNewSessionSessionManagementConfig.class, UserDetailsServiceConfig.class).autowire();
+
+		MockHttpSession givenSession = new MockHttpSession();
+		String givenSessionId = givenSession.getId();
+		givenSession.setAttribute("name", "value");
+
+		MockHttpSession resultingSession = (MockHttpSession) this.mvc
+				.perform(get("/auth").session(givenSession).with(httpBasic("user", "password")))
+				.andExpect(status().isNotFound()).andReturn().getRequest().getSession(false);
+
+		assertThat(givenSessionId).isNotEqualTo(resultingSession.getId());
+		assertThat(resultingSession.getAttribute("name")).isNull();
+	}
+
+	private  T verifyBean(Class clazz) {
+		return verify(this.spring.getContext().getBean(clazz));
+	}
+
+	private static SessionResultMatcher session() {
+		return new SessionResultMatcher();
+	}
+
+	@EnableWebSecurity
+	static class SessionManagementConfig extends WebSecurityConfigurerAdapter {
+
+	}
+
 	@EnableWebSecurity
 	static class CustomSessionManagementConfig extends WebSecurityConfigurerAdapter {
 
@@ -188,21 +281,6 @@ public class NamespaceSessionManagementTests {
 
 	}
 
-	// gh-3371
-	@Test
-	public void authenticateWhenUsingCustomInvalidSessionStrategyThenMatchesNamespace() throws Exception {
-		this.spring.register(InvalidSessionStrategyConfig.class).autowire();
-
-		this.mvc.perform(get("/auth").with(request -> {
-			request.setRequestedSessionIdValid(false);
-			request.setRequestedSessionId("id");
-			return request;
-		})).andExpect(status().isOk());
-
-		verifyBean(InvalidSessionStrategy.class).onInvalidSessionDetected(any(HttpServletRequest.class),
-				any(HttpServletResponse.class));
-	}
-
 	@EnableWebSecurity
 	static class InvalidSessionStrategyConfig extends WebSecurityConfigurerAdapter {
 
@@ -224,17 +302,6 @@ public class NamespaceSessionManagementTests {
 
 	}
 
-	@Test
-	public void authenticateWhenUsingCustomSessionAuthenticationStrategyThenMatchesNamespace() throws Exception {
-		this.spring.register(RefsSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class)
-				.autowire();
-
-		this.mvc.perform(get("/auth").with(httpBasic("user", "password"))).andExpect(status().isOk());
-
-		verifyBean(SessionAuthenticationStrategy.class).onAuthentication(any(Authentication.class),
-				any(HttpServletRequest.class), any(HttpServletResponse.class));
-	}
-
 	@EnableWebSecurity
 	static class RefsSessionManagementConfig extends WebSecurityConfigurerAdapter {
 
@@ -258,21 +325,6 @@ public class NamespaceSessionManagementTests {
 
 	}
 
-	@Test
-	public void authenticateWhenNoSessionFixationProtectionThenMatchesNamespace() throws Exception {
-		this.spring
-				.register(SFPNoneSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class)
-				.autowire();
-
-		MockHttpSession givenSession = new MockHttpSession();
-		String givenSessionId = givenSession.getId();
-		MockHttpSession resultingSession = (MockHttpSession) this.mvc
-				.perform(get("/auth").session(givenSession).with(httpBasic("user", "password")))
-				.andExpect(status().isOk()).andReturn().getRequest().getSession(false);
-
-		assertThat(givenSessionId).isEqualTo(resultingSession.getId());
-	}
-
 	@EnableWebSecurity
 	static class SFPNoneSessionManagementConfig extends WebSecurityConfigurerAdapter {
 
@@ -289,23 +341,6 @@ public class NamespaceSessionManagementTests {
 
 	}
 
-	@Test
-	public void authenticateWhenMigrateSessionFixationProtectionThenMatchesNamespace() throws Exception {
-		this.spring.register(SFPMigrateSessionManagementConfig.class, BasicController.class,
-				UserDetailsServiceConfig.class).autowire();
-
-		MockHttpSession givenSession = new MockHttpSession();
-		String givenSessionId = givenSession.getId();
-		givenSession.setAttribute("name", "value");
-
-		MockHttpSession resultingSession = (MockHttpSession) this.mvc
-				.perform(get("/auth").session(givenSession).with(httpBasic("user", "password")))
-				.andExpect(status().isOk()).andReturn().getRequest().getSession(false);
-
-		assertThat(givenSessionId).isNotEqualTo(resultingSession.getId());
-		assertThat(resultingSession.getAttribute("name")).isEqualTo("value");
-	}
-
 	@EnableWebSecurity
 	static class SFPMigrateSessionManagementConfig extends WebSecurityConfigurerAdapter {
 
@@ -321,17 +356,6 @@ public class NamespaceSessionManagementTests {
 
 	}
 
-	// SEC-2913
-	@Test
-	public void authenticateWhenUsingSessionFixationProtectionThenUsesNonNullEventPublisher() throws Exception {
-		this.spring.register(SFPPostProcessedConfig.class, UserDetailsServiceConfig.class).autowire();
-
-		this.mvc.perform(get("/auth").session(new MockHttpSession()).with(httpBasic("user", "password")))
-				.andExpect(status().isNotFound());
-
-		verifyBean(MockEventListener.class).onApplicationEvent(any(SessionFixationProtectionEvent.class));
-	}
-
 	@EnableWebSecurity
 	static class SFPPostProcessedConfig extends WebSecurityConfigurerAdapter {
 
@@ -352,22 +376,6 @@ public class NamespaceSessionManagementTests {
 
 	}
 
-	@Test
-	public void authenticateWhenNewSessionFixationProtectionThenMatchesNamespace() throws Exception {
-		this.spring.register(SFPNewSessionSessionManagementConfig.class, UserDetailsServiceConfig.class).autowire();
-
-		MockHttpSession givenSession = new MockHttpSession();
-		String givenSessionId = givenSession.getId();
-		givenSession.setAttribute("name", "value");
-
-		MockHttpSession resultingSession = (MockHttpSession) this.mvc
-				.perform(get("/auth").session(givenSession).with(httpBasic("user", "password")))
-				.andExpect(status().isNotFound()).andReturn().getRequest().getSession(false);
-
-		assertThat(givenSessionId).isNotEqualTo(resultingSession.getId());
-		assertThat(resultingSession.getAttribute("name")).isNull();
-	}
-
 	@EnableWebSecurity
 	static class SFPNewSessionSessionManagementConfig extends WebSecurityConfigurerAdapter {
 
@@ -384,10 +392,6 @@ public class NamespaceSessionManagementTests {
 
 	}
 
-	private  T verifyBean(Class clazz) {
-		return verify(this.spring.getContext().getBean(clazz));
-	}
-
 	static class MockEventListener implements ApplicationListener {
 
 		List events = new ArrayList<>();
@@ -431,10 +435,6 @@ public class NamespaceSessionManagementTests {
 
 	}
 
-	private static SessionResultMatcher session() {
-		return new SessionResultMatcher();
-	}
-
 	private static class SessionResultMatcher implements ResultMatcher {
 
 		private String id;
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupportTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupportTests.java
index 0af8e42362..8d8fd76f3a 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupportTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupportTests.java
@@ -55,6 +55,13 @@ public class PermitAllSupportTests {
 		this.mvc.perform(get("/app/abc").with(csrf()).contextPath("/app")).andExpect(status().isFound());
 	}
 
+	@Test
+	public void configureWhenNotAuthorizeRequestsThenException() {
+		assertThatCode(() -> this.spring.register(NoAuthorizedUrlsConfig.class).autowire())
+				.isInstanceOf(BeanCreationException.class)
+				.hasMessageContaining("permitAll only works with HttpSecurity.authorizeRequests");
+	}
+
 	@EnableWebSecurity
 	static class PermitAllConfig extends WebSecurityConfigurerAdapter {
 
@@ -73,13 +80,6 @@ public class PermitAllSupportTests {
 
 	}
 
-	@Test
-	public void configureWhenNotAuthorizeRequestsThenException() {
-		assertThatCode(() -> this.spring.register(NoAuthorizedUrlsConfig.class).autowire())
-				.isInstanceOf(BeanCreationException.class)
-				.hasMessageContaining("permitAll only works with HttpSecurity.authorizeRequests");
-	}
-
 	@EnableWebSecurity
 	static class NoAuthorizedUrlsConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurerTests.java
index fadb69cbbe..8fd6a64f0b 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurerTests.java
@@ -50,6 +50,20 @@ public class PortMapperConfigurerTests {
 		this.mockMvc.perform(get("http://localhost:543")).andExpect(redirectedUrl("https://localhost:123"));
 	}
 
+	@Test
+	public void requestWhenPortMapperHttpMapsToInLambdaThenRedirectsToHttpsPort() throws Exception {
+		this.spring.register(HttpMapsToInLambdaConfig.class).autowire();
+
+		this.mockMvc.perform(get("http://localhost:543")).andExpect(redirectedUrl("https://localhost:123"));
+	}
+
+	@Test
+	public void requestWhenCustomPortMapperInLambdaThenRedirectsToHttpsPort() throws Exception {
+		this.spring.register(CustomPortMapperInLambdaConfig.class).autowire();
+
+		this.mockMvc.perform(get("http://localhost:543")).andExpect(redirectedUrl("https://localhost:123"));
+	}
+
 	@EnableWebSecurity
 	static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
 
@@ -69,13 +83,6 @@ public class PortMapperConfigurerTests {
 
 	}
 
-	@Test
-	public void requestWhenPortMapperHttpMapsToInLambdaThenRedirectsToHttpsPort() throws Exception {
-		this.spring.register(HttpMapsToInLambdaConfig.class).autowire();
-
-		this.mockMvc.perform(get("http://localhost:543")).andExpect(redirectedUrl("https://localhost:123"));
-	}
-
 	@EnableWebSecurity
 	static class HttpMapsToInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -96,13 +103,6 @@ public class PortMapperConfigurerTests {
 
 	}
 
-	@Test
-	public void requestWhenCustomPortMapperInLambdaThenRedirectsToHttpsPort() throws Exception {
-		this.spring.register(CustomPortMapperInLambdaConfig.class).autowire();
-
-		this.mockMvc.perform(get("http://localhost:543")).andExpect(redirectedUrl("https://localhost:123"));
-	}
-
 	@EnableWebSecurity
 	static class CustomPortMapperInLambdaConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.java
index cb312190c3..9de0c521d8 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.java
@@ -86,35 +86,6 @@ public class RememberMeConfigurerTests {
 				.param("remember-me", "true").with(csrf()))).hasMessageContaining("UserDetailsService is required");
 	}
 
-	@EnableWebSecurity
-	static class NullUserDetailsConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.anyRequest().hasRole("USER")
-					.and()
-				.formLogin()
-					.and()
-				.rememberMe();
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) {
-			User user = (User) PasswordEncodedUser.user();
-			DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
-			provider.setUserDetailsService(new InMemoryUserDetailsManager(Collections.singletonList(user)));
-			// @formatter:off
-			auth
-				.authenticationProvider(provider);
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnRememberMeAuthenticationFilter() {
 		this.spring.register(ObjectPostProcessorConfig.class).autowire();
@@ -122,44 +93,6 @@ public class RememberMeConfigurerTests {
 		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(RememberMeAuthenticationFilter.class));
 	}
 
-	@EnableWebSecurity
-	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
-
-		static ObjectPostProcessor objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.rememberMe()
-					.userDetailsService(new AuthenticationManagerBuilder(objectPostProcessor).getDefaultUserDetailsService());
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-			// @formatter:off
-			auth
-				.inMemoryAuthentication();
-			// @formatter:on
-		}
-
-		@Bean
-		static ObjectPostProcessor objectPostProcessor() {
-			return objectPostProcessor;
-		}
-
-	}
-
-	static class ReflectingObjectPostProcessor implements ObjectPostProcessor {
-
-		@Override
-		public  O postProcess(O object) {
-			return object;
-		}
-
-	}
-
 	@Test
 	public void rememberMeWhenInvokedTwiceThenUsesOriginalUserDetailsService() throws Exception {
 		when(DuplicateDoesNotOverrideConfig.userDetailsService.loadUserByUsername(anyString()))
@@ -171,40 +104,6 @@ public class RememberMeConfigurerTests {
 		verify(DuplicateDoesNotOverrideConfig.userDetailsService).loadUserByUsername("user");
 	}
 
-	@EnableWebSecurity
-	static class DuplicateDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
-
-		static UserDetailsService userDetailsService = mock(UserDetailsService.class);
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.httpBasic()
-					.and()
-				.rememberMe()
-					.userDetailsService(userDetailsService)
-					.and()
-				.rememberMe();
-			// @formatter:on
-		}
-
-		@Override
-		@Bean
-		public UserDetailsService userDetailsService() {
-			return new InMemoryUserDetailsManager(
-			// @formatter:off
-					User.withDefaultPasswordEncoder()
-							.username("user")
-							.password("password")
-							.roles("USER")
-							.build()
-					// @formatter:on
-			);
-		}
-
-	}
-
 	@Test
 	public void loginWhenRememberMeTrueThenRespondsWithRememberMeCookie() throws Exception {
 		this.spring.register(RememberMeConfig.class).autowire();
@@ -255,6 +154,152 @@ public class RememberMeConfigurerTests {
 				.andExpect(redirectedUrl("http://localhost/login"));
 	}
 
+	@Test
+	public void loginWhenRememberMeConfiguredInLambdaThenRespondsWithRememberMeCookie() throws Exception {
+		this.spring.register(RememberMeInLambdaConfig.class).autowire();
+
+		this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password")
+				.param("remember-me", "true")).andExpect(cookie().exists("remember-me"));
+	}
+
+	@Test
+	public void loginWhenRememberMeTrueAndCookieDomainThenRememberMeCookieHasDomain() throws Exception {
+		this.spring.register(RememberMeCookieDomainConfig.class).autowire();
+
+		this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password")
+				.param("remember-me", "true")).andExpect(cookie().exists("remember-me"))
+				.andExpect(cookie().domain("remember-me", "spring.io"));
+	}
+
+	@Test
+	public void loginWhenRememberMeTrueAndCookieDomainInLambdaThenRememberMeCookieHasDomain() throws Exception {
+		this.spring.register(RememberMeCookieDomainInLambdaConfig.class).autowire();
+
+		this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password")
+				.param("remember-me", "true")).andExpect(cookie().exists("remember-me"))
+				.andExpect(cookie().domain("remember-me", "spring.io"));
+	}
+
+	@Test
+	public void configureWhenRememberMeCookieNameAndRememberMeServicesThenException() {
+		assertThatThrownBy(() -> this.spring.register(RememberMeCookieNameAndRememberMeServicesConfig.class).autowire())
+				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class)
+				.hasMessageContaining("Can not set rememberMeCookieName and custom rememberMeServices.");
+	}
+
+	@Test
+	public void getWhenRememberMeCookieAndNoKeyConfiguredThenKeyFromRememberMeServicesIsUsed() throws Exception {
+		this.spring.register(FallbackRememberMeKeyConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(post("/login").with(csrf()).param("username", "user")
+				.param("password", "password").param("remember-me", "true")).andReturn();
+		Cookie rememberMeCookie = mvcResult.getResponse().getCookie("remember-me");
+
+		this.mvc.perform(get("/abc").cookie(rememberMeCookie)).andExpect(authenticated()
+				.withAuthentication(auth -> assertThat(auth).isInstanceOf(RememberMeAuthenticationToken.class)));
+	}
+
+	@EnableWebSecurity
+	static class NullUserDetailsConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin()
+					.and()
+				.rememberMe();
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) {
+			User user = (User) PasswordEncodedUser.user();
+			DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
+			provider.setUserDetailsService(new InMemoryUserDetailsManager(Collections.singletonList(user)));
+			// @formatter:off
+			auth
+				.authenticationProvider(provider);
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
+
+		static ObjectPostProcessor objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.rememberMe()
+					.userDetailsService(new AuthenticationManagerBuilder(objectPostProcessor).getDefaultUserDetailsService());
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication();
+			// @formatter:on
+		}
+
+		@Bean
+		static ObjectPostProcessor objectPostProcessor() {
+			return objectPostProcessor;
+		}
+
+	}
+
+	static class ReflectingObjectPostProcessor implements ObjectPostProcessor {
+
+		@Override
+		public  O postProcess(O object) {
+			return object;
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class DuplicateDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
+
+		static UserDetailsService userDetailsService = mock(UserDetailsService.class);
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.httpBasic()
+					.and()
+				.rememberMe()
+					.userDetailsService(userDetailsService)
+					.and()
+				.rememberMe();
+			// @formatter:on
+		}
+
+		@Override
+		@Bean
+		public UserDetailsService userDetailsService() {
+			return new InMemoryUserDetailsManager(
+			// @formatter:off
+					User.withDefaultPasswordEncoder()
+							.username("user")
+							.password("password")
+							.roles("USER")
+							.build()
+					// @formatter:on
+			);
+		}
+
+	}
+
 	@EnableWebSecurity
 	static class RememberMeConfig extends WebSecurityConfigurerAdapter {
 
@@ -282,14 +327,6 @@ public class RememberMeConfigurerTests {
 
 	}
 
-	@Test
-	public void loginWhenRememberMeConfiguredInLambdaThenRespondsWithRememberMeCookie() throws Exception {
-		this.spring.register(RememberMeInLambdaConfig.class).autowire();
-
-		this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password")
-				.param("remember-me", "true")).andExpect(cookie().exists("remember-me"));
-	}
-
 	@EnableWebSecurity
 	static class RememberMeInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -317,15 +354,6 @@ public class RememberMeConfigurerTests {
 
 	}
 
-	@Test
-	public void loginWhenRememberMeTrueAndCookieDomainThenRememberMeCookieHasDomain() throws Exception {
-		this.spring.register(RememberMeCookieDomainConfig.class).autowire();
-
-		this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password")
-				.param("remember-me", "true")).andExpect(cookie().exists("remember-me"))
-				.andExpect(cookie().domain("remember-me", "spring.io"));
-	}
-
 	@EnableWebSecurity
 	static class RememberMeCookieDomainConfig extends WebSecurityConfigurerAdapter {
 
@@ -354,15 +382,6 @@ public class RememberMeConfigurerTests {
 
 	}
 
-	@Test
-	public void loginWhenRememberMeTrueAndCookieDomainInLambdaThenRememberMeCookieHasDomain() throws Exception {
-		this.spring.register(RememberMeCookieDomainInLambdaConfig.class).autowire();
-
-		this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password")
-				.param("remember-me", "true")).andExpect(cookie().exists("remember-me"))
-				.andExpect(cookie().domain("remember-me", "spring.io"));
-	}
-
 	@EnableWebSecurity
 	static class RememberMeCookieDomainInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -393,13 +412,6 @@ public class RememberMeConfigurerTests {
 
 	}
 
-	@Test
-	public void configureWhenRememberMeCookieNameAndRememberMeServicesThenException() {
-		assertThatThrownBy(() -> this.spring.register(RememberMeCookieNameAndRememberMeServicesConfig.class).autowire())
-				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class)
-				.hasMessageContaining("Can not set rememberMeCookieName and custom rememberMeServices.");
-	}
-
 	@EnableWebSecurity
 	static class RememberMeCookieNameAndRememberMeServicesConfig extends WebSecurityConfigurerAdapter {
 
@@ -432,18 +444,6 @@ public class RememberMeConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenRememberMeCookieAndNoKeyConfiguredThenKeyFromRememberMeServicesIsUsed() throws Exception {
-		this.spring.register(FallbackRememberMeKeyConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(post("/login").with(csrf()).param("username", "user")
-				.param("password", "password").param("remember-me", "true")).andReturn();
-		Cookie rememberMeCookie = mvcResult.getResponse().getCookie("remember-me");
-
-		this.mvc.perform(get("/abc").cookie(rememberMeCookie)).andExpect(authenticated()
-				.withAuthentication(auth -> assertThat(auth).isInstanceOf(RememberMeAuthenticationToken.class)));
-	}
-
 	@EnableWebSecurity
 	static class FallbackRememberMeKeyConfig extends RememberMeConfig {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java
index 9bb76f55b1..f1c2e15727 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java
@@ -72,35 +72,6 @@ public class RequestCacheConfigurerTests {
 		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(RequestCacheAwareFilter.class));
 	}
 
-	@EnableWebSecurity
-	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
-
-		static ObjectPostProcessor objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.requestCache();
-			// @formatter:on
-		}
-
-		@Bean
-		static ObjectPostProcessor objectPostProcessor() {
-			return objectPostProcessor;
-		}
-
-	}
-
-	static class ReflectingObjectPostProcessor implements ObjectPostProcessor {
-
-		@Override
-		public  O postProcess(O object) {
-			return object;
-		}
-
-	}
-
 	@Test
 	public void getWhenInvokingExceptionHandlingTwiceThenOriginalEntryPointUsed() throws Exception {
 		this.spring.register(InvokeTwiceDoesNotOverrideConfig.class).autowire();
@@ -111,24 +82,6 @@ public class RequestCacheConfigurerTests {
 				any(HttpServletResponse.class));
 	}
 
-	@EnableWebSecurity
-	static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
-
-		static RequestCache requestCache = mock(RequestCache.class);
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.requestCache()
-					.requestCache(requestCache)
-					.and()
-				.requestCache();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void getWhenBookmarkedUrlIsFaviconIcoThenPostAuthenticationRedirectsToRoot() throws Exception {
 		this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire();
@@ -242,22 +195,6 @@ public class RequestCacheConfigurerTests {
 		this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("http://localhost/messages"));
 	}
 
-	@EnableWebSecurity
-	static class RequestCacheDefaultsConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.anyRequest().authenticated()
-					.and()
-				.formLogin();
-			// @formatter:on
-		}
-
-	}
-
 	// gh-6102
 	@Test
 	public void getWhenRequestCacheIsDisabledThenExceptionTranslationFilterDoesNotStoreRequest() throws Exception {
@@ -282,6 +219,101 @@ public class RequestCacheConfigurerTests {
 		this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/"));
 	}
 
+	@Test
+	public void getWhenRequestCacheIsDisabledInLambdaThenExceptionTranslationFilterDoesNotStoreRequest()
+			throws Exception {
+		this.spring.register(RequestCacheDisabledInLambdaConfig.class, DefaultSecurityConfig.class).autowire();
+
+		MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/bob")).andReturn().getRequest().getSession();
+
+		this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/"));
+	}
+
+	@Test
+	public void getWhenRequestCacheInLambdaThenRedirectedToCachedPage() throws Exception {
+		this.spring.register(RequestCacheInLambdaConfig.class, DefaultSecurityConfig.class).autowire();
+
+		MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/bob")).andReturn().getRequest().getSession();
+
+		this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("http://localhost/bob"));
+	}
+
+	@Test
+	public void getWhenCustomRequestCacheInLambdaThenCustomRequestCacheUsed() throws Exception {
+		this.spring.register(CustomRequestCacheInLambdaConfig.class, DefaultSecurityConfig.class).autowire();
+
+		MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/bob")).andReturn().getRequest().getSession();
+
+		this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/"));
+	}
+
+	private static RequestBuilder formLogin(MockHttpSession session) {
+		return post("/login").param("username", "user").param("password", "password").session(session).with(csrf());
+	}
+
+	@EnableWebSecurity
+	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
+
+		static ObjectPostProcessor objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.requestCache();
+			// @formatter:on
+		}
+
+		@Bean
+		static ObjectPostProcessor objectPostProcessor() {
+			return objectPostProcessor;
+		}
+
+	}
+
+	static class ReflectingObjectPostProcessor implements ObjectPostProcessor {
+
+		@Override
+		public  O postProcess(O object) {
+			return object;
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
+
+		static RequestCache requestCache = mock(RequestCache.class);
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.requestCache()
+					.requestCache(requestCache)
+					.and()
+				.requestCache();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class RequestCacheDefaultsConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().authenticated()
+					.and()
+				.formLogin();
+			// @formatter:on
+		}
+
+	}
+
 	@EnableWebSecurity
 	static class RequestCacheDisabledConfig extends WebSecurityConfigurerAdapter {
 
@@ -293,16 +325,6 @@ public class RequestCacheConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenRequestCacheIsDisabledInLambdaThenExceptionTranslationFilterDoesNotStoreRequest()
-			throws Exception {
-		this.spring.register(RequestCacheDisabledInLambdaConfig.class, DefaultSecurityConfig.class).autowire();
-
-		MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/bob")).andReturn().getRequest().getSession();
-
-		this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/"));
-	}
-
 	@EnableWebSecurity
 	static class RequestCacheDisabledInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -321,15 +343,6 @@ public class RequestCacheConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenRequestCacheInLambdaThenRedirectedToCachedPage() throws Exception {
-		this.spring.register(RequestCacheInLambdaConfig.class, DefaultSecurityConfig.class).autowire();
-
-		MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/bob")).andReturn().getRequest().getSession();
-
-		this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("http://localhost/bob"));
-	}
-
 	@EnableWebSecurity
 	static class RequestCacheInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -348,15 +361,6 @@ public class RequestCacheConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenCustomRequestCacheInLambdaThenCustomRequestCacheUsed() throws Exception {
-		this.spring.register(CustomRequestCacheInLambdaConfig.class, DefaultSecurityConfig.class).autowire();
-
-		MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/bob")).andReturn().getRequest().getSession();
-
-		this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/"));
-	}
-
 	@EnableWebSecurity
 	static class CustomRequestCacheInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -395,8 +399,4 @@ public class RequestCacheConfigurerTests {
 
 	}
 
-	private static RequestBuilder formLogin(MockHttpSession session) {
-		return post("/login").param("username", "user").param("password", "password").session(session).with(csrf());
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestMatcherConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestMatcherConfigurerTests.java
index ae744a06f5..9abd316d03 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestMatcherConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestMatcherConfigurerTests.java
@@ -52,6 +52,14 @@ public class RequestMatcherConfigurerTests {
 		this.mvc.perform(get("/api/abc")).andExpect(status().isForbidden());
 	}
 
+	@Test
+	public void authorizeRequestsWhenInvokedMultipleTimesInLambdaThenChainsPaths() throws Exception {
+		this.spring.register(AuthorizeRequestInLambdaConfig.class).autowire();
+
+		this.mvc.perform(get("/oauth/abc")).andExpect(status().isForbidden());
+		this.mvc.perform(get("/api/abc")).andExpect(status().isForbidden());
+	}
+
 	@EnableWebSecurity
 	static class Sec2908Config extends WebSecurityConfigurerAdapter {
 
@@ -72,14 +80,6 @@ public class RequestMatcherConfigurerTests {
 
 	}
 
-	@Test
-	public void authorizeRequestsWhenInvokedMultipleTimesInLambdaThenChainsPaths() throws Exception {
-		this.spring.register(AuthorizeRequestInLambdaConfig.class).autowire();
-
-		this.mvc.perform(get("/oauth/abc")).andExpect(status().isForbidden());
-		this.mvc.perform(get("/api/abc")).andExpect(status().isForbidden());
-	}
-
 	@EnableWebSecurity
 	static class AuthorizeRequestInLambdaConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurerTests.java
index 2bfd5fda47..4d7b7e052d 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurerTests.java
@@ -71,6 +71,51 @@ public class SecurityContextConfigurerTests {
 		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(SecurityContextPersistenceFilter.class));
 	}
 
+	@Test
+	public void securityContextWhenInvokedTwiceThenUsesOriginalSecurityContextRepository() throws Exception {
+		this.spring.register(DuplicateDoesNotOverrideConfig.class).autowire();
+		when(DuplicateDoesNotOverrideConfig.SCR.loadContext(any())).thenReturn(mock(SecurityContext.class));
+
+		this.mvc.perform(get("/"));
+
+		verify(DuplicateDoesNotOverrideConfig.SCR).loadContext(any(HttpRequestResponseHolder.class));
+	}
+
+	// SEC-2932
+	@Test
+	public void securityContextWhenSecurityContextRepositoryNotConfiguredThenDoesNotThrowException() throws Exception {
+		this.spring.register(SecurityContextRepositoryDefaultsSecurityContextRepositoryConfig.class).autowire();
+
+		this.mvc.perform(get("/"));
+	}
+
+	@Test
+	public void requestWhenSecurityContextWithDefaultsInLambdaThenSessionIsCreated() throws Exception {
+		this.spring.register(SecurityContextWithDefaultsInLambdaConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(formLogin()).andReturn();
+		HttpSession session = mvcResult.getRequest().getSession(false);
+		assertThat(session).isNotNull();
+	}
+
+	@Test
+	public void requestWhenSecurityContextDisabledInLambdaThenContextNotSavedInSession() throws Exception {
+		this.spring.register(SecurityContextDisabledInLambdaConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(formLogin()).andReturn();
+		HttpSession session = mvcResult.getRequest().getSession(false);
+		assertThat(session).isNull();
+	}
+
+	@Test
+	public void requestWhenNullSecurityContextRepositoryInLambdaThenContextNotSavedInSession() throws Exception {
+		this.spring.register(NullSecurityContextRepositoryInLambdaConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(formLogin()).andReturn();
+		HttpSession session = mvcResult.getRequest().getSession(false);
+		assertThat(session).isNull();
+	}
+
 	@EnableWebSecurity
 	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
 
@@ -100,16 +145,6 @@ public class SecurityContextConfigurerTests {
 
 	}
 
-	@Test
-	public void securityContextWhenInvokedTwiceThenUsesOriginalSecurityContextRepository() throws Exception {
-		this.spring.register(DuplicateDoesNotOverrideConfig.class).autowire();
-		when(DuplicateDoesNotOverrideConfig.SCR.loadContext(any())).thenReturn(mock(SecurityContext.class));
-
-		this.mvc.perform(get("/"));
-
-		verify(DuplicateDoesNotOverrideConfig.SCR).loadContext(any(HttpRequestResponseHolder.class));
-	}
-
 	@EnableWebSecurity
 	static class DuplicateDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
 
@@ -128,14 +163,6 @@ public class SecurityContextConfigurerTests {
 
 	}
 
-	// SEC-2932
-	@Test
-	public void securityContextWhenSecurityContextRepositoryNotConfiguredThenDoesNotThrowException() throws Exception {
-		this.spring.register(SecurityContextRepositoryDefaultsSecurityContextRepositoryConfig.class).autowire();
-
-		this.mvc.perform(get("/"));
-	}
-
 	@Configuration
 	@EnableWebSecurity
 	static class SecurityContextRepositoryDefaultsSecurityContextRepositoryConfig extends WebSecurityConfigurerAdapter {
@@ -171,15 +198,6 @@ public class SecurityContextConfigurerTests {
 
 	}
 
-	@Test
-	public void requestWhenSecurityContextWithDefaultsInLambdaThenSessionIsCreated() throws Exception {
-		this.spring.register(SecurityContextWithDefaultsInLambdaConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(formLogin()).andReturn();
-		HttpSession session = mvcResult.getRequest().getSession(false);
-		assertThat(session).isNotNull();
-	}
-
 	@EnableWebSecurity
 	static class SecurityContextWithDefaultsInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -203,15 +221,6 @@ public class SecurityContextConfigurerTests {
 
 	}
 
-	@Test
-	public void requestWhenSecurityContextDisabledInLambdaThenContextNotSavedInSession() throws Exception {
-		this.spring.register(SecurityContextDisabledInLambdaConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(formLogin()).andReturn();
-		HttpSession session = mvcResult.getRequest().getSession(false);
-		assertThat(session).isNull();
-	}
-
 	@EnableWebSecurity
 	static class SecurityContextDisabledInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -235,15 +244,6 @@ public class SecurityContextConfigurerTests {
 
 	}
 
-	@Test
-	public void requestWhenNullSecurityContextRepositoryInLambdaThenContextNotSavedInSession() throws Exception {
-		this.spring.register(NullSecurityContextRepositoryInLambdaConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(formLogin()).andReturn();
-		HttpSession session = mvcResult.getRequest().getSession(false);
-		assertThat(session).isNull();
-	}
-
 	@EnableWebSecurity
 	static class NullSecurityContextRepositoryInLambdaConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurerTests.java
index b94cbdf0eb..0850eb24ca 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurerTests.java
@@ -93,6 +93,127 @@ public class ServletApiConfigurerTests {
 				.postProcess(any(SecurityContextHolderAwareRequestFilter.class));
 	}
 
+	// SEC-2215
+	@Test
+	public void configureWhenUsingDefaultsThenAuthenticationManagerIsNotNull() {
+		this.spring.register(ServletApiConfig.class).autowire();
+
+		assertThat(this.spring.getContext().getBean("customAuthenticationManager")).isNotNull();
+	}
+
+	@Test
+	public void configureWhenUsingDefaultsThenAuthenticationEntryPointIsLogin() throws Exception {
+		this.spring.register(ServletApiConfig.class).autowire();
+
+		this.mvc.perform(formLogin()).andExpect(status().isFound());
+	}
+
+	// SEC-2926
+	@Test
+	public void configureWhenUsingDefaultsThenRolePrefixIsSet() throws Exception {
+		this.spring.register(ServletApiConfig.class, AdminController.class).autowire();
+
+		this.mvc.perform(
+				get("/admin").with(authentication(new TestingAuthenticationToken("user", "pass", "ROLE_ADMIN"))))
+				.andExpect(status().isOk());
+	}
+
+	@Test
+	public void requestWhenCustomAuthenticationEntryPointThenEntryPointUsed() throws Exception {
+		this.spring.register(CustomEntryPointConfig.class).autowire();
+
+		this.mvc.perform(get("/"));
+
+		verify(CustomEntryPointConfig.ENTRYPOINT).commence(any(HttpServletRequest.class),
+				any(HttpServletResponse.class), any(AuthenticationException.class));
+	}
+
+	@Test
+	public void servletApiWhenInvokedTwiceThenUsesOriginalRole() throws Exception {
+		this.spring.register(DuplicateInvocationsDoesNotOverrideConfig.class, AdminController.class).autowire();
+
+		this.mvc.perform(
+				get("/admin").with(user("user").authorities(AuthorityUtils.createAuthorityList("PERMISSION_ADMIN"))))
+				.andExpect(status().isOk());
+
+		this.mvc.perform(get("/admin").with(user("user").authorities(AuthorityUtils.createAuthorityList("ROLE_ADMIN"))))
+				.andExpect(status().isForbidden());
+	}
+
+	@Test
+	public void configureWhenSharedObjectTrustResolverThenTrustResolverUsed() throws Exception {
+		this.spring.register(SharedTrustResolverConfig.class).autowire();
+
+		this.mvc.perform(get("/"));
+
+		verify(SharedTrustResolverConfig.TR, atLeastOnce()).isAnonymous(any());
+	}
+
+	@Test
+	public void requestWhenServletApiWithDefaultsInLambdaThenUsesDefaultRolePrefix() throws Exception {
+		this.spring.register(ServletApiWithDefaultsInLambdaConfig.class, AdminController.class).autowire();
+
+		this.mvc.perform(get("/admin").with(user("user").authorities(AuthorityUtils.createAuthorityList("ROLE_ADMIN"))))
+				.andExpect(status().isOk());
+	}
+
+	@Test
+	public void requestWhenRolePrefixInLambdaThenUsesCustomRolePrefix() throws Exception {
+		this.spring.register(RolePrefixInLambdaConfig.class, AdminController.class).autowire();
+
+		this.mvc.perform(
+				get("/admin").with(user("user").authorities(AuthorityUtils.createAuthorityList("PERMISSION_ADMIN"))))
+				.andExpect(status().isOk());
+
+		this.mvc.perform(get("/admin").with(user("user").authorities(AuthorityUtils.createAuthorityList("ROLE_ADMIN"))))
+				.andExpect(status().isForbidden());
+	}
+
+	@Test
+	public void checkSecurityContextAwareAndLogoutFilterHasSameSizeAndHasLogoutSuccessEventPublishingLogoutHandler() {
+		this.spring.register(ServletApiWithLogoutConfig.class);
+
+		SecurityContextHolderAwareRequestFilter scaFilter = getFilter(SecurityContextHolderAwareRequestFilter.class);
+		LogoutFilter logoutFilter = getFilter(LogoutFilter.class);
+
+		LogoutHandler lfLogoutHandler = getFieldValue(logoutFilter, "handler");
+		assertThat(lfLogoutHandler).isInstanceOf(CompositeLogoutHandler.class);
+
+		List scaLogoutHandlers = getFieldValue(scaFilter, "logoutHandlers");
+		List lfLogoutHandlers = getFieldValue(lfLogoutHandler, "logoutHandlers");
+
+		assertThat(scaLogoutHandlers).hasSameSizeAs(lfLogoutHandlers);
+
+		assertThat(scaLogoutHandlers).hasAtLeastOneElementOfType(LogoutSuccessEventPublishingLogoutHandler.class);
+		assertThat(lfLogoutHandlers).hasAtLeastOneElementOfType(LogoutSuccessEventPublishingLogoutHandler.class);
+	}
+
+	@Test
+	public void logoutServletApiWhenCsrfDisabled() throws Exception {
+		ConfigurableWebApplicationContext context = this.spring.register(CsrfDisabledConfig.class).getContext();
+		MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()).build();
+		MvcResult mvcResult = mockMvc.perform(get("/")).andReturn();
+		assertThat(mvcResult.getRequest().getSession(false)).isNull();
+	}
+
+	private  T getFilter(Class filterClass) {
+		return (T) getFilters().stream().filter(filterClass::isInstance).findFirst().orElse(null);
+	}
+
+	private List getFilters() {
+		FilterChainProxy proxy = this.spring.getContext().getBean(FilterChainProxy.class);
+		return proxy.getFilters("/");
+	}
+
+	private  T getFieldValue(Object target, String fieldName) {
+		try {
+			return (T) FieldUtils.getFieldValue(target, fieldName);
+		}
+		catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+
 	@EnableWebSecurity
 	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
 
@@ -122,31 +243,6 @@ public class ServletApiConfigurerTests {
 
 	}
 
-	// SEC-2215
-	@Test
-	public void configureWhenUsingDefaultsThenAuthenticationManagerIsNotNull() {
-		this.spring.register(ServletApiConfig.class).autowire();
-
-		assertThat(this.spring.getContext().getBean("customAuthenticationManager")).isNotNull();
-	}
-
-	@Test
-	public void configureWhenUsingDefaultsThenAuthenticationEntryPointIsLogin() throws Exception {
-		this.spring.register(ServletApiConfig.class).autowire();
-
-		this.mvc.perform(formLogin()).andExpect(status().isFound());
-	}
-
-	// SEC-2926
-	@Test
-	public void configureWhenUsingDefaultsThenRolePrefixIsSet() throws Exception {
-		this.spring.register(ServletApiConfig.class, AdminController.class).autowire();
-
-		this.mvc.perform(
-				get("/admin").with(authentication(new TestingAuthenticationToken("user", "pass", "ROLE_ADMIN"))))
-				.andExpect(status().isOk());
-	}
-
 	@EnableWebSecurity
 	static class ServletApiConfig extends WebSecurityConfigurerAdapter {
 
@@ -166,16 +262,6 @@ public class ServletApiConfigurerTests {
 
 	}
 
-	@Test
-	public void requestWhenCustomAuthenticationEntryPointThenEntryPointUsed() throws Exception {
-		this.spring.register(CustomEntryPointConfig.class).autowire();
-
-		this.mvc.perform(get("/"));
-
-		verify(CustomEntryPointConfig.ENTRYPOINT).commence(any(HttpServletRequest.class),
-				any(HttpServletResponse.class), any(AuthenticationException.class));
-	}
-
 	@EnableWebSecurity
 	static class CustomEntryPointConfig extends WebSecurityConfigurerAdapter {
 
@@ -206,18 +292,6 @@ public class ServletApiConfigurerTests {
 
 	}
 
-	@Test
-	public void servletApiWhenInvokedTwiceThenUsesOriginalRole() throws Exception {
-		this.spring.register(DuplicateInvocationsDoesNotOverrideConfig.class, AdminController.class).autowire();
-
-		this.mvc.perform(
-				get("/admin").with(user("user").authorities(AuthorityUtils.createAuthorityList("PERMISSION_ADMIN"))))
-				.andExpect(status().isOk());
-
-		this.mvc.perform(get("/admin").with(user("user").authorities(AuthorityUtils.createAuthorityList("ROLE_ADMIN"))))
-				.andExpect(status().isForbidden());
-	}
-
 	@EnableWebSecurity
 	static class DuplicateInvocationsDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
 
@@ -234,15 +308,6 @@ public class ServletApiConfigurerTests {
 
 	}
 
-	@Test
-	public void configureWhenSharedObjectTrustResolverThenTrustResolverUsed() throws Exception {
-		this.spring.register(SharedTrustResolverConfig.class).autowire();
-
-		this.mvc.perform(get("/"));
-
-		verify(SharedTrustResolverConfig.TR, atLeastOnce()).isAnonymous(any());
-	}
-
 	@EnableWebSecurity
 	static class SharedTrustResolverConfig extends WebSecurityConfigurerAdapter {
 
@@ -258,14 +323,6 @@ public class ServletApiConfigurerTests {
 
 	}
 
-	@Test
-	public void requestWhenServletApiWithDefaultsInLambdaThenUsesDefaultRolePrefix() throws Exception {
-		this.spring.register(ServletApiWithDefaultsInLambdaConfig.class, AdminController.class).autowire();
-
-		this.mvc.perform(get("/admin").with(user("user").authorities(AuthorityUtils.createAuthorityList("ROLE_ADMIN"))))
-				.andExpect(status().isOk());
-	}
-
 	@EnableWebSecurity
 	static class ServletApiWithDefaultsInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -279,18 +336,6 @@ public class ServletApiConfigurerTests {
 
 	}
 
-	@Test
-	public void requestWhenRolePrefixInLambdaThenUsesCustomRolePrefix() throws Exception {
-		this.spring.register(RolePrefixInLambdaConfig.class, AdminController.class).autowire();
-
-		this.mvc.perform(
-				get("/admin").with(user("user").authorities(AuthorityUtils.createAuthorityList("PERMISSION_ADMIN"))))
-				.andExpect(status().isOk());
-
-		this.mvc.perform(get("/admin").with(user("user").authorities(AuthorityUtils.createAuthorityList("ROLE_ADMIN"))))
-				.andExpect(status().isForbidden());
-	}
-
 	@EnableWebSecurity
 	static class RolePrefixInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -319,25 +364,6 @@ public class ServletApiConfigurerTests {
 
 	}
 
-	@Test
-	public void checkSecurityContextAwareAndLogoutFilterHasSameSizeAndHasLogoutSuccessEventPublishingLogoutHandler() {
-		this.spring.register(ServletApiWithLogoutConfig.class);
-
-		SecurityContextHolderAwareRequestFilter scaFilter = getFilter(SecurityContextHolderAwareRequestFilter.class);
-		LogoutFilter logoutFilter = getFilter(LogoutFilter.class);
-
-		LogoutHandler lfLogoutHandler = getFieldValue(logoutFilter, "handler");
-		assertThat(lfLogoutHandler).isInstanceOf(CompositeLogoutHandler.class);
-
-		List scaLogoutHandlers = getFieldValue(scaFilter, "logoutHandlers");
-		List lfLogoutHandlers = getFieldValue(lfLogoutHandler, "logoutHandlers");
-
-		assertThat(scaLogoutHandlers).hasSameSizeAs(lfLogoutHandlers);
-
-		assertThat(scaLogoutHandlers).hasAtLeastOneElementOfType(LogoutSuccessEventPublishingLogoutHandler.class);
-		assertThat(lfLogoutHandlers).hasAtLeastOneElementOfType(LogoutSuccessEventPublishingLogoutHandler.class);
-	}
-
 	@EnableWebSecurity
 	static class ServletApiWithLogoutConfig extends WebSecurityConfigurerAdapter {
 
@@ -352,14 +378,6 @@ public class ServletApiConfigurerTests {
 
 	}
 
-	@Test
-	public void logoutServletApiWhenCsrfDisabled() throws Exception {
-		ConfigurableWebApplicationContext context = this.spring.register(CsrfDisabledConfig.class).getContext();
-		MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()).build();
-		MvcResult mvcResult = mockMvc.perform(get("/")).andReturn();
-		assertThat(mvcResult.getRequest().getSession(false)).isNull();
-	}
-
 	@Configuration
 	@EnableWebSecurity
 	static class CsrfDisabledConfig extends WebSecurityConfigurerAdapter {
@@ -386,22 +404,4 @@ public class ServletApiConfigurerTests {
 
 	}
 
-	private  T getFilter(Class filterClass) {
-		return (T) getFilters().stream().filter(filterClass::isInstance).findFirst().orElse(null);
-	}
-
-	private List getFilters() {
-		FilterChainProxy proxy = this.spring.getContext().getBean(FilterChainProxy.class);
-		return proxy.getFilters("/");
-	}
-
-	private  T getFieldValue(Object target, String fieldName) {
-		try {
-			return (T) FieldUtils.getFieldValue(target, fieldName);
-		}
-		catch (Exception e) {
-			throw new RuntimeException(e);
-		}
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java
index a200d42087..d2e84b594b 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java
@@ -103,6 +103,24 @@ public class SessionManagementConfigurerServlet31Tests {
 		assertThat(request.getSession().getAttribute("attribute1")).isEqualTo("value1");
 	}
 
+	private void loadConfig(Class... classes) {
+		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
+		context.register(classes);
+		context.refresh();
+		this.context = context;
+		this.springSecurityFilterChain = this.context.getBean("springSecurityFilterChain", Filter.class);
+	}
+
+	private void login(Authentication auth) {
+		HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
+		HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(this.request, this.response);
+		repo.loadContext(requestResponseHolder);
+
+		SecurityContextImpl securityContextImpl = new SecurityContextImpl();
+		securityContextImpl.setAuthentication(auth);
+		repo.saveContext(securityContextImpl, requestResponseHolder.getRequest(), requestResponseHolder.getResponse());
+	}
+
 	@EnableWebSecurity
 	static class SessionManagementDefaultSessionFixationServlet31Config extends WebSecurityConfigurerAdapter {
 
@@ -127,22 +145,4 @@ public class SessionManagementConfigurerServlet31Tests {
 
 	}
 
-	private void loadConfig(Class... classes) {
-		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
-		context.register(classes);
-		context.refresh();
-		this.context = context;
-		this.springSecurityFilterChain = this.context.getBean("springSecurityFilterChain", Filter.class);
-	}
-
-	private void login(Authentication auth) {
-		HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
-		HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(this.request, this.response);
-		repo.loadContext(requestResponseHolder);
-
-		SecurityContextImpl securityContextImpl = new SecurityContextImpl();
-		securityContextImpl.setAuthentication(auth);
-		repo.saveContext(securityContextImpl, requestResponseHolder.getRequest(), requestResponseHolder.getResponse());
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionCreationPolicyTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionCreationPolicyTests.java
index 6cf6576b1b..ff7d81bae3 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionCreationPolicyTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionCreationPolicyTests.java
@@ -55,6 +55,26 @@ public class SessionManagementConfigurerSessionCreationPolicyTests {
 		assertThat(result.getRequest().getSession(false)).isNull();
 	}
 
+	@Test
+	public void getWhenUserSessionCreationPolicyConfigurationThenOverrides() throws Exception {
+
+		this.spring.register(StatelessCreateSessionUserConfig.class).autowire();
+
+		MvcResult result = this.mvc.perform(get("/")).andReturn();
+
+		assertThat(result.getRequest().getSession(false)).isNull();
+	}
+
+	@Test
+	public void getWhenDefaultsThenLoginChallengeCreatesSession() throws Exception {
+
+		this.spring.register(DefaultConfig.class, BasicController.class).autowire();
+
+		MvcResult result = this.mvc.perform(get("/")).andExpect(status().isUnauthorized()).andReturn();
+
+		assertThat(result.getRequest().getSession(false)).isNotNull();
+	}
+
 	@EnableWebSecurity
 	static class StatelessCreateSessionSharedObjectConfig extends WebSecurityConfigurerAdapter {
 
@@ -66,16 +86,6 @@ public class SessionManagementConfigurerSessionCreationPolicyTests {
 
 	}
 
-	@Test
-	public void getWhenUserSessionCreationPolicyConfigurationThenOverrides() throws Exception {
-
-		this.spring.register(StatelessCreateSessionUserConfig.class).autowire();
-
-		MvcResult result = this.mvc.perform(get("/")).andReturn();
-
-		assertThat(result.getRequest().getSession(false)).isNull();
-	}
-
 	@EnableWebSecurity
 	static class StatelessCreateSessionUserConfig extends WebSecurityConfigurerAdapter {
 
@@ -92,16 +102,6 @@ public class SessionManagementConfigurerSessionCreationPolicyTests {
 
 	}
 
-	@Test
-	public void getWhenDefaultsThenLoginChallengeCreatesSession() throws Exception {
-
-		this.spring.register(DefaultConfig.class, BasicController.class).autowire();
-
-		MvcResult result = this.mvc.perform(get("/")).andExpect(status().isUnauthorized()).andReturn();
-
-		assertThat(result.getRequest().getSession(false)).isNotNull();
-	}
-
 	@EnableWebSecurity
 	static class DefaultConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTests.java
index 8ce913f6b3..267135d6cf 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTests.java
@@ -90,25 +90,6 @@ public class SessionManagementConfigurerTests {
 				any(HttpServletResponse.class));
 	}
 
-	@EnableWebSecurity
-	static class SessionManagementRequestCacheConfig extends WebSecurityConfigurerAdapter {
-
-		static RequestCache REQUEST_CACHE;
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.requestCache()
-					.requestCache(REQUEST_CACHE)
-					.and()
-				.sessionManagement()
-					.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void sessionManagementWhenConfiguredThenDoesNotOverrideSecurityContextRepository() throws Exception {
 		SessionManagementSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO = mock(SecurityContextRepository.class);
@@ -122,25 +103,6 @@ public class SessionManagementConfigurerTests {
 				.saveContext(any(SecurityContext.class), any(HttpServletRequest.class), any(HttpServletResponse.class));
 	}
 
-	@EnableWebSecurity
-	static class SessionManagementSecurityContextRepositoryConfig extends WebSecurityConfigurerAdapter {
-
-		static SecurityContextRepository SECURITY_CONTEXT_REPO;
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.securityContext()
-					.securityContextRepository(SECURITY_CONTEXT_REPO)
-					.and()
-				.sessionManagement()
-					.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void sessionManagementWhenInvokedTwiceThenUsesOriginalSessionCreationPolicy() throws Exception {
 		this.spring.register(InvokeTwiceDoesNotOverride.class).autowire();
@@ -151,22 +113,6 @@ public class SessionManagementConfigurerTests {
 		assertThat(session).isNull();
 	}
 
-	@EnableWebSecurity
-	static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.sessionManagement()
-					.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
-					.and()
-				.sessionManagement();
-			// @formatter:on
-		}
-
-	}
-
 	// SEC-2137
 	@Test
 	public void getWhenSessionFixationDisabledAndConcurrencyControlEnabledThenSessionIsNotInvalidated()
@@ -181,32 +127,6 @@ public class SessionManagementConfigurerTests {
 		assertThat(mvcResult.getRequest().getSession().getId()).isEqualTo(sessionId);
 	}
 
-	@EnableWebSecurity
-	static class DisableSessionFixationEnableConcurrencyControlConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		public void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.httpBasic()
-					.and()
-				.sessionManagement()
-					.sessionFixation().none()
-					.maximumSessions(1);
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-			// @formatter:off
-			auth
-				.inMemoryAuthentication()
-					.withUser(PasswordEncodedUser.user());
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void authenticateWhenNewSessionFixationProtectionInLambdaThenCreatesNewSession() throws Exception {
 		this.spring.register(SFPNewSessionInLambdaConfig.class).autowire();
@@ -223,34 +143,6 @@ public class SessionManagementConfigurerTests {
 		assertThat(resultingSession.getAttribute("name")).isNull();
 	}
 
-	@EnableWebSecurity
-	static class SFPNewSessionInLambdaConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.sessionManagement(sessionManagement ->
-					sessionManagement
-						.sessionFixation(sessionFixation ->
-							sessionFixation.newSession()
-						)
-				)
-				.httpBasic(withDefaults());
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-			// @formatter:off
-			auth
-				.inMemoryAuthentication()
-					.withUser(PasswordEncodedUser.user());
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void loginWhenUserLoggedInAndMaxSessionsIsOneThenLoginPrevented() throws Exception {
 		this.spring.register(ConcurrencyControlConfig.class).autowire();
@@ -275,32 +167,6 @@ public class SessionManagementConfigurerTests {
 				.andExpect(status().isFound()).andExpect(redirectedUrl("/"));
 	}
 
-	@EnableWebSecurity
-	static class ConcurrencyControlConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		public void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.formLogin()
-					.and()
-				.sessionManagement()
-					.maximumSessions(1)
-					.maxSessionsPreventsLogin(true);
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-			// @formatter:off
-			auth
-				.inMemoryAuthentication()
-					.withUser(PasswordEncodedUser.user());
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void loginWhenUserLoggedInAndMaxSessionsOneInLambdaThenLoginPrevented() throws Exception {
 		this.spring.register(ConcurrencyControlInLambdaConfig.class).autowire();
@@ -311,36 +177,6 @@ public class SessionManagementConfigurerTests {
 				.andExpect(status().isFound()).andExpect(redirectedUrl("/login?error"));
 	}
 
-	@EnableWebSecurity
-	static class ConcurrencyControlInLambdaConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		public void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.formLogin(withDefaults())
-				.sessionManagement(sessionManagement ->
-					sessionManagement
-						.sessionConcurrency(sessionConcurrency ->
-							sessionConcurrency
-								.maximumSessions(1)
-								.maxSessionsPreventsLogin(true)
-						)
-				);
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-			// @formatter:off
-			auth
-				.inMemoryAuthentication()
-					.withUser(PasswordEncodedUser.user());
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void requestWhenSessionCreationPolicyStateLessInLambdaThenNoSessionCreated() throws Exception {
 		this.spring.register(SessionCreationPolicyStateLessInLambdaConfig.class).autowire();
@@ -351,22 +187,6 @@ public class SessionManagementConfigurerTests {
 		assertThat(session).isNull();
 	}
 
-	@EnableWebSecurity
-	static class SessionCreationPolicyStateLessInLambdaConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.sessionManagement(sessionManagement ->
-					sessionManagement
-						.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
-				);
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnSessionManagementFilter() {
 		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
@@ -419,6 +239,222 @@ public class SessionManagementConfigurerTests {
 				.postProcess(any(ChangeSessionIdAuthenticationStrategy.class));
 	}
 
+	@Test
+	public void getWhenAnonymousRequestAndTrustResolverSharedObjectReturnsAnonymousFalseThenSessionIsSaved()
+			throws Exception {
+		SharedTrustResolverConfig.TR = mock(AuthenticationTrustResolver.class);
+		when(SharedTrustResolverConfig.TR.isAnonymous(any())).thenReturn(false);
+		this.spring.register(SharedTrustResolverConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/")).andReturn();
+
+		assertThat(mvcResult.getRequest().getSession(false)).isNotNull();
+	}
+
+	@Test
+	public void whenOneSessionRegistryBeanThenUseIt() throws Exception {
+		SessionRegistryOneBeanConfig.SESSION_REGISTRY = mock(SessionRegistry.class);
+		this.spring.register(SessionRegistryOneBeanConfig.class).autowire();
+
+		MockHttpSession session = new MockHttpSession(this.spring.getContext().getServletContext());
+		this.mvc.perform(get("/").session(session));
+
+		verify(SessionRegistryOneBeanConfig.SESSION_REGISTRY).getSessionInformation(session.getId());
+	}
+
+	@Test
+	public void whenTwoSessionRegistryBeansThenUseNeither() throws Exception {
+		SessionRegistryTwoBeansConfig.SESSION_REGISTRY_ONE = mock(SessionRegistry.class);
+		SessionRegistryTwoBeansConfig.SESSION_REGISTRY_TWO = mock(SessionRegistry.class);
+		this.spring.register(SessionRegistryTwoBeansConfig.class).autowire();
+
+		MockHttpSession session = new MockHttpSession(this.spring.getContext().getServletContext());
+		this.mvc.perform(get("/").session(session));
+
+		verifyNoInteractions(SessionRegistryTwoBeansConfig.SESSION_REGISTRY_ONE);
+		verifyNoInteractions(SessionRegistryTwoBeansConfig.SESSION_REGISTRY_TWO);
+	}
+
+	@EnableWebSecurity
+	static class SessionManagementRequestCacheConfig extends WebSecurityConfigurerAdapter {
+
+		static RequestCache REQUEST_CACHE;
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.requestCache()
+					.requestCache(REQUEST_CACHE)
+					.and()
+				.sessionManagement()
+					.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class SessionManagementSecurityContextRepositoryConfig extends WebSecurityConfigurerAdapter {
+
+		static SecurityContextRepository SECURITY_CONTEXT_REPO;
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.securityContext()
+					.securityContextRepository(SECURITY_CONTEXT_REPO)
+					.and()
+				.sessionManagement()
+					.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.sessionManagement()
+					.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+					.and()
+				.sessionManagement();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class DisableSessionFixationEnableConcurrencyControlConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		public void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.httpBasic()
+					.and()
+				.sessionManagement()
+					.sessionFixation().none()
+					.maximumSessions(1);
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication()
+					.withUser(PasswordEncodedUser.user());
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class SFPNewSessionInLambdaConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.sessionManagement(sessionManagement ->
+					sessionManagement
+						.sessionFixation(sessionFixation ->
+							sessionFixation.newSession()
+						)
+				)
+				.httpBasic(withDefaults());
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication()
+					.withUser(PasswordEncodedUser.user());
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class ConcurrencyControlConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		public void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.formLogin()
+					.and()
+				.sessionManagement()
+					.maximumSessions(1)
+					.maxSessionsPreventsLogin(true);
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication()
+					.withUser(PasswordEncodedUser.user());
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class ConcurrencyControlInLambdaConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		public void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.formLogin(withDefaults())
+				.sessionManagement(sessionManagement ->
+					sessionManagement
+						.sessionConcurrency(sessionConcurrency ->
+							sessionConcurrency
+								.maximumSessions(1)
+								.maxSessionsPreventsLogin(true)
+						)
+				);
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication()
+					.withUser(PasswordEncodedUser.user());
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class SessionCreationPolicyStateLessInLambdaConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.sessionManagement(sessionManagement ->
+					sessionManagement
+						.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+				);
+			// @formatter:on
+		}
+
+	}
+
 	@EnableWebSecurity
 	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
 
@@ -449,18 +485,6 @@ public class SessionManagementConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenAnonymousRequestAndTrustResolverSharedObjectReturnsAnonymousFalseThenSessionIsSaved()
-			throws Exception {
-		SharedTrustResolverConfig.TR = mock(AuthenticationTrustResolver.class);
-		when(SharedTrustResolverConfig.TR.isAnonymous(any())).thenReturn(false);
-		this.spring.register(SharedTrustResolverConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/")).andReturn();
-
-		assertThat(mvcResult.getRequest().getSession(false)).isNotNull();
-	}
-
 	@EnableWebSecurity
 	static class SharedTrustResolverConfig extends WebSecurityConfigurerAdapter {
 
@@ -476,30 +500,6 @@ public class SessionManagementConfigurerTests {
 
 	}
 
-	@Test
-	public void whenOneSessionRegistryBeanThenUseIt() throws Exception {
-		SessionRegistryOneBeanConfig.SESSION_REGISTRY = mock(SessionRegistry.class);
-		this.spring.register(SessionRegistryOneBeanConfig.class).autowire();
-
-		MockHttpSession session = new MockHttpSession(this.spring.getContext().getServletContext());
-		this.mvc.perform(get("/").session(session));
-
-		verify(SessionRegistryOneBeanConfig.SESSION_REGISTRY).getSessionInformation(session.getId());
-	}
-
-	@Test
-	public void whenTwoSessionRegistryBeansThenUseNeither() throws Exception {
-		SessionRegistryTwoBeansConfig.SESSION_REGISTRY_ONE = mock(SessionRegistry.class);
-		SessionRegistryTwoBeansConfig.SESSION_REGISTRY_TWO = mock(SessionRegistry.class);
-		this.spring.register(SessionRegistryTwoBeansConfig.class).autowire();
-
-		MockHttpSession session = new MockHttpSession(this.spring.getContext().getServletContext());
-		this.mvc.perform(get("/").session(session));
-
-		verifyNoInteractions(SessionRegistryTwoBeansConfig.SESSION_REGISTRY_ONE);
-		verifyNoInteractions(SessionRegistryTwoBeansConfig.SESSION_REGISTRY_TWO);
-	}
-
 	@EnableWebSecurity
 	static class SessionRegistryOneBeanConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurerTests.java
index e0ba32d1aa..1604b8e616 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurerTests.java
@@ -98,41 +98,6 @@ public class UrlAuthorizationConfigurerTests {
 		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
 	}
 
-	@EnableWebSecurity
-	@Configuration
-	@EnableWebMvc
-	static class MvcMatcherConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.httpBasic().and()
-				.apply(new UrlAuthorizationConfigurer(getApplicationContext())).getRegistry()
-					.mvcMatchers("/path").hasRole("ADMIN");
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-			// @formatter:off
-			auth
-				.inMemoryAuthentication();
-			// @formatter:on
-		}
-
-		@RestController
-		static class PathController {
-
-			@RequestMapping("/path")
-			public String path() {
-				return "path";
-			}
-
-		}
-
-	}
-
 	@Test
 	public void mvcMatcherServletPath() throws Exception {
 		loadConfig(MvcMatcherServletPathConfig.class, LegacyMvcMatchingConfig.class);
@@ -176,6 +141,55 @@ public class UrlAuthorizationConfigurerTests {
 		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
 	}
 
+	@Test
+	public void anonymousUrlAuthorization() {
+		loadConfig(AnonymousUrlAuthorizationConfig.class);
+	}
+
+	public void loadConfig(Class... configs) {
+		this.context = new AnnotationConfigWebApplicationContext();
+		this.context.register(configs);
+		this.context.setServletContext(new MockServletContext());
+		this.context.refresh();
+
+		this.context.getAutowireCapableBeanFactory().autowireBean(this);
+	}
+
+	@EnableWebSecurity
+	@Configuration
+	@EnableWebMvc
+	static class MvcMatcherConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.httpBasic().and()
+				.apply(new UrlAuthorizationConfigurer(getApplicationContext())).getRegistry()
+					.mvcMatchers("/path").hasRole("ADMIN");
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication();
+			// @formatter:on
+		}
+
+		@RestController
+		static class PathController {
+
+			@RequestMapping("/path")
+			public String path() {
+				return "path";
+			}
+
+		}
+
+	}
+
 	@EnableWebSecurity
 	@Configuration
 	@EnableWebMvc
@@ -211,11 +225,6 @@ public class UrlAuthorizationConfigurerTests {
 
 	}
 
-	@Test
-	public void anonymousUrlAuthorization() {
-		loadConfig(AnonymousUrlAuthorizationConfig.class);
-	}
-
 	@EnableWebSecurity
 	@Configuration
 	static class AnonymousUrlAuthorizationConfig extends WebSecurityConfigurerAdapter {
@@ -241,13 +250,4 @@ public class UrlAuthorizationConfigurerTests {
 
 	}
 
-	public void loadConfig(Class... configs) {
-		this.context = new AnnotationConfigWebApplicationContext();
-		this.context.register(configs);
-		this.context.setServletContext(new MockServletContext());
-		this.context.refresh();
-
-		this.context.getAutowireCapableBeanFactory().autowireBean(this);
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationsTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationsTests.java
index f0b8d56e78..8497fee4fd 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationsTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationsTests.java
@@ -103,25 +103,6 @@ public class UrlAuthorizationsTests {
 		this.mvc.perform(get("/role-admin")).andExpect(status().isForbidden());
 	}
 
-	@EnableWebSecurity
-	static class RoleConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.antMatchers("/role-user-authority").hasAnyAuthority("ROLE_USER")
-					.antMatchers("/role-admin-authority").hasAnyAuthority("ROLE_ADMIN")
-					.antMatchers("/role-user-admin-authority").hasAnyAuthority("ROLE_USER", "ROLE_ADMIN")
-					.antMatchers("/role-user").hasAnyRole("USER")
-					.antMatchers("/role-admin").hasAnyRole("ADMIN")
-					.antMatchers("/role-user-admin").hasAnyRole("USER", "ADMIN");
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void configureWhenNoAccessDecisionManagerThenDefaultsToAffirmativeBased() {
 		this.spring.register(NoSpecificAccessDecisionManagerConfig.class).autowire();
@@ -142,6 +123,25 @@ public class UrlAuthorizationsTests {
 		return null;
 	}
 
+	@EnableWebSecurity
+	static class RoleConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.antMatchers("/role-user-authority").hasAnyAuthority("ROLE_USER")
+					.antMatchers("/role-admin-authority").hasAnyAuthority("ROLE_ADMIN")
+					.antMatchers("/role-user-admin-authority").hasAnyAuthority("ROLE_USER", "ROLE_ADMIN")
+					.antMatchers("/role-user").hasAnyRole("USER")
+					.antMatchers("/role-admin").hasAnyRole("ADMIN")
+					.antMatchers("/role-user-admin").hasAnyRole("USER", "ADMIN");
+			// @formatter:on
+		}
+
+	}
+
 	@EnableWebSecurity
 	static class NoSpecificAccessDecisionManagerConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/X509ConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/X509ConfigurerTests.java
index 20d4245cd8..e497365b44 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/X509ConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/X509ConfigurerTests.java
@@ -65,6 +65,40 @@ public class X509ConfigurerTests {
 		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(X509AuthenticationFilter.class));
 	}
 
+	@Test
+	public void x509WhenInvokedTwiceThenUsesOriginalSubjectPrincipalRegex() throws Exception {
+		this.spring.register(DuplicateDoesNotOverrideConfig.class).autowire();
+		X509Certificate certificate = loadCert("rodatexampledotcom.cer");
+
+		this.mvc.perform(get("/").with(x509(certificate))).andExpect(authenticated().withUsername("rod"));
+	}
+
+	@Test
+	public void x509WhenConfiguredInLambdaThenUsesDefaults() throws Exception {
+		this.spring.register(DefaultsInLambdaConfig.class).autowire();
+		X509Certificate certificate = loadCert("rod.cer");
+
+		this.mvc.perform(get("/").with(x509(certificate))).andExpect(authenticated().withUsername("rod"));
+	}
+
+	@Test
+	public void x509WhenSubjectPrincipalRegexInLambdaThenUsesRegexToExtractPrincipal() throws Exception {
+		this.spring.register(SubjectPrincipalRegexInLambdaConfig.class).autowire();
+		X509Certificate certificate = loadCert("rodatexampledotcom.cer");
+
+		this.mvc.perform(get("/").with(x509(certificate))).andExpect(authenticated().withUsername("rod"));
+	}
+
+	private  T loadCert(String location) {
+		try (InputStream is = new ClassPathResource(location).getInputStream()) {
+			CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+			return (T) certFactory.generateCertificate(is);
+		}
+		catch (Exception e) {
+			throw new IllegalArgumentException(e);
+		}
+	}
+
 	@EnableWebSecurity
 	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
 
@@ -94,14 +128,6 @@ public class X509ConfigurerTests {
 
 	}
 
-	@Test
-	public void x509WhenInvokedTwiceThenUsesOriginalSubjectPrincipalRegex() throws Exception {
-		this.spring.register(DuplicateDoesNotOverrideConfig.class).autowire();
-		X509Certificate certificate = loadCert("rodatexampledotcom.cer");
-
-		this.mvc.perform(get("/").with(x509(certificate))).andExpect(authenticated().withUsername("rod"));
-	}
-
 	@EnableWebSecurity
 	static class DuplicateDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
 
@@ -127,14 +153,6 @@ public class X509ConfigurerTests {
 
 	}
 
-	@Test
-	public void x509WhenConfiguredInLambdaThenUsesDefaults() throws Exception {
-		this.spring.register(DefaultsInLambdaConfig.class).autowire();
-		X509Certificate certificate = loadCert("rod.cer");
-
-		this.mvc.perform(get("/").with(x509(certificate))).andExpect(authenticated().withUsername("rod"));
-	}
-
 	@EnableWebSecurity
 	static class DefaultsInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -157,14 +175,6 @@ public class X509ConfigurerTests {
 
 	}
 
-	@Test
-	public void x509WhenSubjectPrincipalRegexInLambdaThenUsesRegexToExtractPrincipal() throws Exception {
-		this.spring.register(SubjectPrincipalRegexInLambdaConfig.class).autowire();
-		X509Certificate certificate = loadCert("rodatexampledotcom.cer");
-
-		this.mvc.perform(get("/").with(x509(certificate))).andExpect(authenticated().withUsername("rod"));
-	}
-
 	@EnableWebSecurity
 	static class SubjectPrincipalRegexInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -190,14 +200,4 @@ public class X509ConfigurerTests {
 
 	}
 
-	private  T loadCert(String location) {
-		try (InputStream is = new ClassPathResource(location).getInputStream()) {
-			CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
-			return (T) certFactory.generateCertificate(is);
-		}
-		catch (Exception e) {
-			throw new IllegalArgumentException(e);
-		}
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java
index 130fa378bb..edcc2600a5 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java
@@ -584,6 +584,37 @@ public class OAuth2LoginConfigurerTests {
 				.scope(scopes).build();
 	}
 
+	private static OAuth2AccessTokenResponseClient createOauth2AccessTokenResponseClient() {
+		return request -> {
+			Map additionalParameters = new HashMap<>();
+			if (request.getAuthorizationExchange().getAuthorizationRequest().getScopes().contains("openid")) {
+				additionalParameters.put(OidcParameterNames.ID_TOKEN, "token123");
+			}
+			return OAuth2AccessTokenResponse.withToken("accessToken123").tokenType(OAuth2AccessToken.TokenType.BEARER)
+					.additionalParameters(additionalParameters).build();
+		};
+	}
+
+	private static OAuth2UserService createOauth2UserService() {
+		Map userAttributes = Collections.singletonMap("name", "spring");
+		return request -> new DefaultOAuth2User(Collections.singleton(new OAuth2UserAuthority(userAttributes)),
+				userAttributes, "name");
+	}
+
+	private static OAuth2UserService createOidcUserService() {
+		OidcIdToken idToken = idToken().build();
+		return request -> new DefaultOidcUser(Collections.singleton(new OidcUserAuthority(idToken)), idToken);
+	}
+
+	private static GrantedAuthoritiesMapper createGrantedAuthoritiesMapper() {
+		return authorities -> {
+			boolean isOidc = OidcUserAuthority.class.isInstance(authorities.iterator().next());
+			List mappedAuthorities = new ArrayList<>(authorities);
+			mappedAuthorities.add(new SimpleGrantedAuthority(isOidc ? "ROLE_OIDC_USER" : "ROLE_OAUTH2_USER"));
+			return mappedAuthorities;
+		};
+	}
+
 	@EnableWebSecurity
 	static class OAuth2LoginConfig extends CommonWebSecurityConfigurerAdapter
 			implements ApplicationListener {
@@ -985,35 +1016,4 @@ public class OAuth2LoginConfigurerTests {
 
 	}
 
-	private static OAuth2AccessTokenResponseClient createOauth2AccessTokenResponseClient() {
-		return request -> {
-			Map additionalParameters = new HashMap<>();
-			if (request.getAuthorizationExchange().getAuthorizationRequest().getScopes().contains("openid")) {
-				additionalParameters.put(OidcParameterNames.ID_TOKEN, "token123");
-			}
-			return OAuth2AccessTokenResponse.withToken("accessToken123").tokenType(OAuth2AccessToken.TokenType.BEARER)
-					.additionalParameters(additionalParameters).build();
-		};
-	}
-
-	private static OAuth2UserService createOauth2UserService() {
-		Map userAttributes = Collections.singletonMap("name", "spring");
-		return request -> new DefaultOAuth2User(Collections.singleton(new OAuth2UserAuthority(userAttributes)),
-				userAttributes, "name");
-	}
-
-	private static OAuth2UserService createOidcUserService() {
-		OidcIdToken idToken = idToken().build();
-		return request -> new DefaultOidcUser(Collections.singleton(new OidcUserAuthority(idToken)), idToken);
-	}
-
-	private static GrantedAuthoritiesMapper createGrantedAuthoritiesMapper() {
-		return authorities -> {
-			boolean isOidc = OidcUserAuthority.class.isInstance(authorities.iterator().next());
-			List mappedAuthorities = new ArrayList<>(authorities);
-			mappedAuthorities.add(new SimpleGrantedAuthority(isOidc ? "ROLE_OIDC_USER" : "ROLE_OAUTH2_USER"));
-			return mappedAuthorities;
-		};
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java
index 4338f5a43c..04c077fd60 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java
@@ -1327,7 +1327,89 @@ public class OAuth2ResourceServerConfigurerTests {
 				.isInstanceOf(NoUniqueBeanDefinitionException.class);
 	}
 
-	// -- support
+	private static  void registerMockBean(GenericApplicationContext context, String name, Class clazz) {
+		context.registerBean(name, clazz, () -> mock(clazz));
+	}
+
+	private static BearerTokenRequestPostProcessor bearerToken(String token) {
+		return new BearerTokenRequestPostProcessor(token);
+	}
+
+	private static ResultMatcher invalidRequestHeader(String message) {
+		return header().string(HttpHeaders.WWW_AUTHENTICATE,
+				AllOf.allOf(new StringStartsWith("Bearer " + "error=\"invalid_request\", " + "error_description=\""),
+						new StringContains(message),
+						new StringEndsWith(", " + "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\"")));
+	}
+
+	private static ResultMatcher invalidTokenHeader(String message) {
+		return header().string(HttpHeaders.WWW_AUTHENTICATE,
+				AllOf.allOf(new StringStartsWith("Bearer " + "error=\"invalid_token\", " + "error_description=\""),
+						new StringContains(message),
+						new StringEndsWith(", " + "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\"")));
+	}
+
+	private static ResultMatcher insufficientScopeHeader() {
+		return header().string(HttpHeaders.WWW_AUTHENTICATE, "Bearer " + "error=\"insufficient_scope\""
+				+ ", error_description=\"The request requires higher privileges than provided by the access token.\""
+				+ ", error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\"");
+	}
+
+	private String jwkSet() {
+		return new JWKSet(new RSAKey.Builder(TestKeys.DEFAULT_PUBLIC_KEY).keyID("1").build()).toString();
+	}
+
+	private String jwtFromIssuer(String issuer) throws Exception {
+		Map claims = new HashMap<>();
+		claims.put(ISS, issuer);
+		claims.put(SUB, "test-subject");
+		claims.put("scope", "message:read");
+		JWSObject jws = new JWSObject(new JWSHeader.Builder(JWSAlgorithm.RS256).keyID("1").build(),
+				new Payload(new JSONObject(claims)));
+		jws.sign(new RSASSASigner(TestKeys.DEFAULT_PRIVATE_KEY));
+		return jws.serialize();
+	}
+
+	private void mockWebServer(String response) {
+		this.web.enqueue(new MockResponse().setResponseCode(200)
+				.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(response));
+	}
+
+	private void mockRestOperations(String response) {
+		RestOperations rest = this.spring.getContext().getBean(RestOperations.class);
+		HttpHeaders headers = new HttpHeaders();
+		headers.setContentType(MediaType.APPLICATION_JSON);
+		ResponseEntity entity = new ResponseEntity<>(response, headers, HttpStatus.OK);
+		when(rest.exchange(any(RequestEntity.class), eq(String.class))).thenReturn(entity);
+	}
+
+	private  T bean(Class beanClass) {
+		return this.spring.getContext().getBean(beanClass);
+	}
+
+	private  T verifyBean(Class beanClass) {
+		return verify(this.spring.getContext().getBean(beanClass));
+	}
+
+	private String json(String name) throws IOException {
+		return resource(name + ".json");
+	}
+
+	private String jwks(String name) throws IOException {
+		return resource(name + ".jwks");
+	}
+
+	private String token(String name) throws IOException {
+		return resource(name + ".token");
+	}
+
+	private String resource(String suffix) throws IOException {
+		String name = this.getClass().getSimpleName() + "-" + suffix;
+		ClassPathResource resource = new ClassPathResource(name, this.getClass());
+		try (BufferedReader reader = new BufferedReader(new FileReader(resource.getFile()))) {
+			return reader.lines().collect(Collectors.joining());
+		}
+	}
 
 	@EnableWebSecurity
 	static class DefaultConfig extends WebSecurityConfigurerAdapter {
@@ -2293,10 +2375,6 @@ public class OAuth2ResourceServerConfigurerTests {
 
 	}
 
-	private static  void registerMockBean(GenericApplicationContext context, String name, Class clazz) {
-		context.registerBean(name, clazz, () -> mock(clazz));
-	}
-
 	private static class BearerTokenRequestPostProcessor implements RequestPostProcessor {
 
 		private boolean asRequestParameter;
@@ -2326,84 +2404,4 @@ public class OAuth2ResourceServerConfigurerTests {
 
 	}
 
-	private static BearerTokenRequestPostProcessor bearerToken(String token) {
-		return new BearerTokenRequestPostProcessor(token);
-	}
-
-	private static ResultMatcher invalidRequestHeader(String message) {
-		return header().string(HttpHeaders.WWW_AUTHENTICATE,
-				AllOf.allOf(new StringStartsWith("Bearer " + "error=\"invalid_request\", " + "error_description=\""),
-						new StringContains(message),
-						new StringEndsWith(", " + "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\"")));
-	}
-
-	private static ResultMatcher invalidTokenHeader(String message) {
-		return header().string(HttpHeaders.WWW_AUTHENTICATE,
-				AllOf.allOf(new StringStartsWith("Bearer " + "error=\"invalid_token\", " + "error_description=\""),
-						new StringContains(message),
-						new StringEndsWith(", " + "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\"")));
-	}
-
-	private static ResultMatcher insufficientScopeHeader() {
-		return header().string(HttpHeaders.WWW_AUTHENTICATE, "Bearer " + "error=\"insufficient_scope\""
-				+ ", error_description=\"The request requires higher privileges than provided by the access token.\""
-				+ ", error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\"");
-	}
-
-	private String jwkSet() {
-		return new JWKSet(new RSAKey.Builder(TestKeys.DEFAULT_PUBLIC_KEY).keyID("1").build()).toString();
-	}
-
-	private String jwtFromIssuer(String issuer) throws Exception {
-		Map claims = new HashMap<>();
-		claims.put(ISS, issuer);
-		claims.put(SUB, "test-subject");
-		claims.put("scope", "message:read");
-		JWSObject jws = new JWSObject(new JWSHeader.Builder(JWSAlgorithm.RS256).keyID("1").build(),
-				new Payload(new JSONObject(claims)));
-		jws.sign(new RSASSASigner(TestKeys.DEFAULT_PRIVATE_KEY));
-		return jws.serialize();
-	}
-
-	private void mockWebServer(String response) {
-		this.web.enqueue(new MockResponse().setResponseCode(200)
-				.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(response));
-	}
-
-	private void mockRestOperations(String response) {
-		RestOperations rest = this.spring.getContext().getBean(RestOperations.class);
-		HttpHeaders headers = new HttpHeaders();
-		headers.setContentType(MediaType.APPLICATION_JSON);
-		ResponseEntity entity = new ResponseEntity<>(response, headers, HttpStatus.OK);
-		when(rest.exchange(any(RequestEntity.class), eq(String.class))).thenReturn(entity);
-	}
-
-	private  T bean(Class beanClass) {
-		return this.spring.getContext().getBean(beanClass);
-	}
-
-	private  T verifyBean(Class beanClass) {
-		return verify(this.spring.getContext().getBean(beanClass));
-	}
-
-	private String json(String name) throws IOException {
-		return resource(name + ".json");
-	}
-
-	private String jwks(String name) throws IOException {
-		return resource(name + ".jwks");
-	}
-
-	private String token(String name) throws IOException {
-		return resource(name + ".token");
-	}
-
-	private String resource(String suffix) throws IOException {
-		String name = this.getClass().getSimpleName() + "-" + suffix;
-		ClassPathResource resource = new ClassPathResource(name, this.getClass());
-		try (BufferedReader reader = new BufferedReader(new FileReader(resource.getFile()))) {
-			return reader.lines().collect(Collectors.joining());
-		}
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/openid/OpenIDLoginConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/openid/OpenIDLoginConfigurerTests.java
index ab6ff70dd8..f2882e78f0 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/openid/OpenIDLoginConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/openid/OpenIDLoginConfigurerTests.java
@@ -83,35 +83,6 @@ public class OpenIDLoginConfigurerTests {
 		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(OpenIDAuthenticationProvider.class));
 	}
 
-	@EnableWebSecurity
-	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
-
-		static ObjectPostProcessor objectPostProcessor;
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.openidLogin();
-			// @formatter:on
-		}
-
-		@Bean
-		static ObjectPostProcessor objectPostProcessor() {
-			return objectPostProcessor;
-		}
-
-	}
-
-	static class ReflectingObjectPostProcessor implements ObjectPostProcessor {
-
-		@Override
-		public  O postProcess(O object) {
-			return object;
-		}
-
-	}
-
 	@Test
 	public void openidLoginWhenInvokedTwiceThenUsesOriginalLoginPage() throws Exception {
 		this.spring.register(InvokeTwiceDoesNotOverrideConfig.class).autowire();
@@ -120,33 +91,6 @@ public class OpenIDLoginConfigurerTests {
 				.andExpect(redirectedUrl("http://localhost/login/custom"));
 	}
 
-	@EnableWebSecurity
-	static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-			// @formatter:off
-			auth
-				.inMemoryAuthentication();
-			// @formatter:on
-		}
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.anyRequest().authenticated()
-					.and()
-				.openidLogin()
-					.loginPage("/login/custom")
-					.and()
-				.openidLogin();
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void requestWhenOpenIdLoginPageInLambdaThenRedirectsToLoginPAge() throws Exception {
 		this.spring.register(OpenIdLoginPageInLambdaConfig.class).autowire();
@@ -155,26 +99,6 @@ public class OpenIDLoginConfigurerTests {
 				.andExpect(redirectedUrl("http://localhost/login/custom"));
 	}
 
-	@EnableWebSecurity
-	static class OpenIdLoginPageInLambdaConfig extends WebSecurityConfigurerAdapter {
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests(authorizeRequests ->
-					authorizeRequests
-						.anyRequest().authenticated()
-				)
-				.openidLogin(openIdLogin ->
-					openIdLogin
-						.loginPage("/login/custom")
-				);
-			// @formatter:on
-		}
-
-	}
-
 	@Test
 	public void requestWhenAttributeExchangeConfiguredThenFetchAttributesMatchAttributeList() throws Exception {
 		OpenIdAttributesInLambdaConfig.CONSUMER_MANAGER = mock(ConsumerManager.class);
@@ -213,6 +137,113 @@ public class OpenIDLoginConfigurerTests {
 		}
 	}
 
+	@Test
+	public void requestWhenAttributeNameNotSpecifiedThenAttributeNameDefaulted() throws Exception {
+		OpenIdAttributesNullNameConfig.CONSUMER_MANAGER = mock(ConsumerManager.class);
+		AuthRequest mockAuthRequest = mock(AuthRequest.class);
+		DiscoveryInformation mockDiscoveryInformation = mock(DiscoveryInformation.class);
+		when(mockAuthRequest.getDestinationUrl(anyBoolean())).thenReturn("mockUrl");
+		when(OpenIdAttributesNullNameConfig.CONSUMER_MANAGER.associate(any())).thenReturn(mockDiscoveryInformation);
+		when(OpenIdAttributesNullNameConfig.CONSUMER_MANAGER.authenticate(any(DiscoveryInformation.class), any(),
+				any())).thenReturn(mockAuthRequest);
+		this.spring.register(OpenIdAttributesNullNameConfig.class).autowire();
+
+		try (MockWebServer server = new MockWebServer()) {
+			String endpoint = server.url("/").toString();
+
+			server.enqueue(new MockResponse().addHeader(YADIS_XRDS_LOCATION, endpoint));
+			server.enqueue(new MockResponse()
+					.setBody(String.format("%s", endpoint)));
+
+			MvcResult mvcResult = this.mvc.perform(
+					get("/login/openid").param(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, endpoint))
+					.andExpect(status().isFound()).andReturn();
+
+			Object attributeObject = mvcResult.getRequest().getSession()
+					.getAttribute("SPRING_SECURITY_OPEN_ID_ATTRIBUTES_FETCH_LIST");
+			assertThat(attributeObject).isInstanceOf(List.class);
+			List attributeList = (List) attributeObject;
+			assertThat(attributeList).hasSize(1);
+			assertThat(attributeList.get(0).getName()).isEqualTo("default-attribute");
+		}
+	}
+
+	@EnableWebSecurity
+	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
+
+		static ObjectPostProcessor objectPostProcessor;
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.openidLogin();
+			// @formatter:on
+		}
+
+		@Bean
+		static ObjectPostProcessor objectPostProcessor() {
+			return objectPostProcessor;
+		}
+
+	}
+
+	static class ReflectingObjectPostProcessor implements ObjectPostProcessor {
+
+		@Override
+		public  O postProcess(O object) {
+			return object;
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication();
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().authenticated()
+					.and()
+				.openidLogin()
+					.loginPage("/login/custom")
+					.and()
+				.openidLogin();
+			// @formatter:on
+		}
+
+	}
+
+	@EnableWebSecurity
+	static class OpenIdLoginPageInLambdaConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests(authorizeRequests ->
+					authorizeRequests
+						.anyRequest().authenticated()
+				)
+				.openidLogin(openIdLogin ->
+					openIdLogin
+						.loginPage("/login/custom")
+				);
+			// @formatter:on
+		}
+
+	}
+
 	@EnableWebSecurity
 	static class OpenIdAttributesInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -251,37 +282,6 @@ public class OpenIDLoginConfigurerTests {
 
 	}
 
-	@Test
-	public void requestWhenAttributeNameNotSpecifiedThenAttributeNameDefaulted() throws Exception {
-		OpenIdAttributesNullNameConfig.CONSUMER_MANAGER = mock(ConsumerManager.class);
-		AuthRequest mockAuthRequest = mock(AuthRequest.class);
-		DiscoveryInformation mockDiscoveryInformation = mock(DiscoveryInformation.class);
-		when(mockAuthRequest.getDestinationUrl(anyBoolean())).thenReturn("mockUrl");
-		when(OpenIdAttributesNullNameConfig.CONSUMER_MANAGER.associate(any())).thenReturn(mockDiscoveryInformation);
-		when(OpenIdAttributesNullNameConfig.CONSUMER_MANAGER.authenticate(any(DiscoveryInformation.class), any(),
-				any())).thenReturn(mockAuthRequest);
-		this.spring.register(OpenIdAttributesNullNameConfig.class).autowire();
-
-		try (MockWebServer server = new MockWebServer()) {
-			String endpoint = server.url("/").toString();
-
-			server.enqueue(new MockResponse().addHeader(YADIS_XRDS_LOCATION, endpoint));
-			server.enqueue(new MockResponse()
-					.setBody(String.format("%s", endpoint)));
-
-			MvcResult mvcResult = this.mvc.perform(
-					get("/login/openid").param(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, endpoint))
-					.andExpect(status().isFound()).andReturn();
-
-			Object attributeObject = mvcResult.getRequest().getSession()
-					.getAttribute("SPRING_SECURITY_OPEN_ID_ATTRIBUTES_FETCH_LIST");
-			assertThat(attributeObject).isInstanceOf(List.class);
-			List attributeList = (List) attributeObject;
-			assertThat(attributeList).hasSize(1);
-			assertThat(attributeList.get(0).getName()).isEqualTo("default-attribute");
-		}
-	}
-
 	@EnableWebSecurity
 	static class OpenIdAttributesNullNameConfig extends WebSecurityConfigurerAdapter {
 
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurerTests.java
index de8bd7924c..d387b12037 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurerTests.java
@@ -241,6 +241,44 @@ public class Saml2LoginConfigurerTests {
 				.hasToString(expected);
 	}
 
+	private static org.apache.commons.codec.binary.Base64 BASE64 = new org.apache.commons.codec.binary.Base64(0,
+			new byte[] { '\n' });
+
+	private static byte[] samlDecode(String s) {
+		return BASE64.decode(s);
+	}
+
+	private static String samlInflate(byte[] b) {
+		try {
+			ByteArrayOutputStream out = new ByteArrayOutputStream();
+			InflaterOutputStream iout = new InflaterOutputStream(out, new Inflater(true));
+			iout.write(b);
+			iout.finish();
+			return new String(out.toByteArray(), UTF_8);
+		}
+		catch (IOException e) {
+			throw new Saml2Exception("Unable to inflate string", e);
+		}
+	}
+
+	private static AuthenticationManager getAuthenticationManagerMock(String role) {
+		return new AuthenticationManager() {
+
+			@Override
+			public Authentication authenticate(Authentication authentication) throws AuthenticationException {
+				if (!supports(authentication.getClass())) {
+					throw new AuthenticationServiceException("not supported");
+				}
+				return new Saml2Authentication(() -> "auth principal", "saml2 response",
+						Collections.singletonList(new SimpleGrantedAuthority(role)));
+			}
+
+			public boolean supports(Class authentication) {
+				return authentication.isAssignableFrom(Saml2AuthenticationToken.class);
+			}
+		};
+	}
+
 	@EnableWebSecurity
 	@Import(Saml2LoginConfigBeans.class)
 	static class Saml2LoginConfigWithCustomAuthenticationManager extends WebSecurityConfigurerAdapter {
@@ -339,24 +377,6 @@ public class Saml2LoginConfigurerTests {
 
 	}
 
-	private static AuthenticationManager getAuthenticationManagerMock(String role) {
-		return new AuthenticationManager() {
-
-			@Override
-			public Authentication authenticate(Authentication authentication) throws AuthenticationException {
-				if (!supports(authentication.getClass())) {
-					throw new AuthenticationServiceException("not supported");
-				}
-				return new Saml2Authentication(() -> "auth principal", "saml2 response",
-						Collections.singletonList(new SimpleGrantedAuthority(role)));
-			}
-
-			public boolean supports(Class authentication) {
-				return authentication.isAssignableFrom(Saml2AuthenticationToken.class);
-			}
-		};
-	}
-
 	static class Saml2LoginConfigBeans {
 
 		@Bean
@@ -373,24 +393,4 @@ public class Saml2LoginConfigurerTests {
 
 	}
 
-	private static org.apache.commons.codec.binary.Base64 BASE64 = new org.apache.commons.codec.binary.Base64(0,
-			new byte[] { '\n' });
-
-	private static byte[] samlDecode(String s) {
-		return BASE64.decode(s);
-	}
-
-	private static String samlInflate(byte[] b) {
-		try {
-			ByteArrayOutputStream out = new ByteArrayOutputStream();
-			InflaterOutputStream iout = new InflaterOutputStream(out, new Inflater(true));
-			iout.write(b);
-			iout.finish();
-			return new String(out.toByteArray(), UTF_8);
-		}
-		catch (IOException e) {
-			throw new Saml2Exception("Unable to inflate string", e);
-		}
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/reactive/EnableWebFluxSecurityTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/reactive/EnableWebFluxSecurityTests.java
index 5f01efd285..fdd1461eeb 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/reactive/EnableWebFluxSecurityTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/reactive/EnableWebFluxSecurityTests.java
@@ -164,12 +164,6 @@ public class EnableWebFluxSecurityTests {
 		assertThat(rdvp).isNotNull();
 	}
 
-	@EnableWebFluxSecurity
-	@Import(ReactiveAuthenticationTestConfiguration.class)
-	static class Config {
-
-	}
-
 	@Test
 	public void passwordEncoderBeanIsUsed() {
 		this.spring.register(CustomPasswordEncoderConfig.class).autowire();
@@ -186,22 +180,6 @@ public class EnableWebFluxSecurityTests {
 				.consumeWith(result -> assertThat(result.getResponseBody()).isEqualTo("user"));
 	}
 
-	@EnableWebFluxSecurity
-	static class CustomPasswordEncoderConfig {
-
-		@Bean
-		public ReactiveUserDetailsService userDetailsService(PasswordEncoder encoder) {
-			return new MapReactiveUserDetailsService(
-					User.withUsername("user").password(encoder.encode("password")).roles("USER").build());
-		}
-
-		@Bean
-		public static PasswordEncoder passwordEncoder() {
-			return new BCryptPasswordEncoder();
-		}
-
-	}
-
 	@Test
 	public void passwordUpdateManagerUsed() {
 		this.spring.register(MapReactiveUserDetailsServiceConfig.class).autowire();
@@ -213,22 +191,6 @@ public class EnableWebFluxSecurityTests {
 		assertThat(users.findByUsername("user").block().getPassword()).startsWith("{bcrypt}");
 	}
 
-	@EnableWebFluxSecurity
-	static class MapReactiveUserDetailsServiceConfig {
-
-		@Bean
-		public MapReactiveUserDetailsService userDetailsService() {
-			// @formatter:off
-			return new MapReactiveUserDetailsService(User.withUsername("user")
-					.password("{noop}password")
-					.roles("USER")
-					.build()
-			// @formatter:on
-			);
-		}
-
-	}
-
 	@Test
 	public void formLoginWorks() {
 		this.spring.register(Config.class).autowire();
@@ -254,6 +216,87 @@ public class EnableWebFluxSecurityTests {
 		client.get().uri("/test").exchange().expectStatus().isOk();
 	}
 
+	@Test
+	@WithMockUser
+	public void authenticationPrincipalArgumentResolverWhenSpelThenWorks() {
+		this.spring.register(AuthenticationPrincipalConfig.class).autowire();
+
+		WebTestClient client = WebTestClient.bindToApplicationContext(this.spring.getContext()).build();
+
+		client.get().uri("/spel").exchange().expectStatus().isOk().expectBody(String.class).isEqualTo("user");
+	}
+
+	private static DataBuffer toDataBuffer(String body) {
+		DataBuffer buffer = new DefaultDataBufferFactory().allocateBuffer();
+		buffer.write(body.getBytes(StandardCharsets.UTF_8));
+		return buffer;
+	}
+
+	@Test
+	public void enableWebFluxSecurityWhenNoConfigurationAnnotationThenBeanProxyingEnabled() {
+		this.spring.register(BeanProxyEnabledByDefaultConfig.class).autowire();
+
+		Child childBean = this.spring.getContext().getBean(Child.class);
+		Parent parentBean = this.spring.getContext().getBean(Parent.class);
+
+		assertThat(parentBean.getChild()).isSameAs(childBean);
+	}
+
+	@Test
+	public void enableWebFluxSecurityWhenProxyBeanMethodsFalseThenBeanProxyingDisabled() {
+		this.spring.register(BeanProxyDisabledConfig.class).autowire();
+
+		Child childBean = this.spring.getContext().getBean(Child.class);
+		Parent parentBean = this.spring.getContext().getBean(Parent.class);
+
+		assertThat(parentBean.getChild()).isNotSameAs(childBean);
+	}
+
+	@Test
+	// gh-8596
+	public void resolveAuthenticationPrincipalArgumentResolverFirstDoesNotCauseBeanCurrentlyInCreationException() {
+		this.spring.register(EnableWebFluxSecurityConfiguration.class, ReactiveAuthenticationTestConfiguration.class,
+				DelegatingWebFluxConfiguration.class).autowire();
+	}
+
+	@EnableWebFluxSecurity
+	@Import(ReactiveAuthenticationTestConfiguration.class)
+	static class Config {
+
+	}
+
+	@EnableWebFluxSecurity
+	static class CustomPasswordEncoderConfig {
+
+		@Bean
+		public ReactiveUserDetailsService userDetailsService(PasswordEncoder encoder) {
+			return new MapReactiveUserDetailsService(
+					User.withUsername("user").password(encoder.encode("password")).roles("USER").build());
+		}
+
+		@Bean
+		public static PasswordEncoder passwordEncoder() {
+			return new BCryptPasswordEncoder();
+		}
+
+	}
+
+	@EnableWebFluxSecurity
+	static class MapReactiveUserDetailsServiceConfig {
+
+		@Bean
+		public MapReactiveUserDetailsService userDetailsService() {
+			// @formatter:off
+			return new MapReactiveUserDetailsService(User.withUsername("user")
+					.password("{noop}password")
+					.roles("USER")
+					.build()
+			// @formatter:on
+			);
+		}
+
+	}
+
 	@EnableWebFluxSecurity
 	@Import(ReactiveAuthenticationTestConfiguration.class)
 	static class MultiSecurityHttpConfig {
@@ -273,16 +316,6 @@ public class EnableWebFluxSecurityTests {
 
 	}
 
-	@Test
-	@WithMockUser
-	public void authenticationPrincipalArgumentResolverWhenSpelThenWorks() {
-		this.spring.register(AuthenticationPrincipalConfig.class).autowire();
-
-		WebTestClient client = WebTestClient.bindToApplicationContext(this.spring.getContext()).build();
-
-		client.get().uri("/spel").exchange().expectStatus().isOk().expectBody(String.class).isEqualTo("user");
-	}
-
 	@EnableWebFluxSecurity
 	@EnableWebFlux
 	@Import(ReactiveAuthenticationTestConfiguration.class)
@@ -313,22 +346,6 @@ public class EnableWebFluxSecurityTests {
 
 	}
 
-	private static DataBuffer toDataBuffer(String body) {
-		DataBuffer buffer = new DefaultDataBufferFactory().allocateBuffer();
-		buffer.write(body.getBytes(StandardCharsets.UTF_8));
-		return buffer;
-	}
-
-	@Test
-	public void enableWebFluxSecurityWhenNoConfigurationAnnotationThenBeanProxyingEnabled() {
-		this.spring.register(BeanProxyEnabledByDefaultConfig.class).autowire();
-
-		Child childBean = this.spring.getContext().getBean(Child.class);
-		Parent parentBean = this.spring.getContext().getBean(Parent.class);
-
-		assertThat(parentBean.getChild()).isSameAs(childBean);
-	}
-
 	@EnableWebFluxSecurity
 	@Import(ReactiveAuthenticationTestConfiguration.class)
 	static class BeanProxyEnabledByDefaultConfig {
@@ -345,16 +362,6 @@ public class EnableWebFluxSecurityTests {
 
 	}
 
-	@Test
-	public void enableWebFluxSecurityWhenProxyBeanMethodsFalseThenBeanProxyingDisabled() {
-		this.spring.register(BeanProxyDisabledConfig.class).autowire();
-
-		Child childBean = this.spring.getContext().getBean(Child.class);
-		Parent parentBean = this.spring.getContext().getBean(Parent.class);
-
-		assertThat(parentBean.getChild()).isNotSameAs(childBean);
-	}
-
 	@Configuration(proxyBeanMethods = false)
 	@EnableWebFluxSecurity
 	@Import(ReactiveAuthenticationTestConfiguration.class)
@@ -393,13 +400,6 @@ public class EnableWebFluxSecurityTests {
 
 	}
 
-	@Test
-	// gh-8596
-	public void resolveAuthenticationPrincipalArgumentResolverFirstDoesNotCauseBeanCurrentlyInCreationException() {
-		this.spring.register(EnableWebFluxSecurityConfiguration.class, ReactiveAuthenticationTestConfiguration.class,
-				DelegatingWebFluxConfiguration.class).autowire();
-	}
-
 	@EnableWebFluxSecurity
 	@Configuration(proxyBeanMethods = false)
 	static class EnableWebFluxSecurityConfiguration {
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurerTests.java
index 9d73774461..8511a04d73 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurerTests.java
@@ -272,43 +272,6 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests {
 		}
 	}
 
-	@Configuration
-	@EnableWebSocketMessageBroker
-	@Import(SyncExecutorConfig.class)
-	static class MsmsRegistryCustomPatternMatcherConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
-
-		// @formatter:off
-		@Override
-		public void registerStompEndpoints(StompEndpointRegistry registry) {
-			registry
-				.addEndpoint("/other")
-				.setHandshakeHandler(testHandshakeHandler());
-		}
-		// @formatter:on
-
-		// @formatter:off
-		@Override
-		protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
-			messages
-				.simpDestMatchers("/app/a.*").permitAll()
-				.anyMessage().denyAll();
-		}
-		// @formatter:on
-
-		@Override
-		public void configureMessageBroker(MessageBrokerRegistry registry) {
-			registry.setPathMatcher(new AntPathMatcher("."));
-			registry.enableSimpleBroker("/queue/", "/topic/");
-			registry.setApplicationDestinationPrefixes("/app");
-		}
-
-		@Bean
-		public TestHandshakeHandler testHandshakeHandler() {
-			return new TestHandshakeHandler();
-		}
-
-	}
-
 	@Test
 	public void overrideMsmsRegistryCustomPatternMatcher() {
 		loadConfig(OverrideMsmsRegistryCustomPatternMatcherConfig.class);
@@ -324,45 +287,6 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests {
 		}
 	}
 
-	@Configuration
-	@EnableWebSocketMessageBroker
-	@Import(SyncExecutorConfig.class)
-	static class OverrideMsmsRegistryCustomPatternMatcherConfig
-			extends AbstractSecurityWebSocketMessageBrokerConfigurer {
-
-		// @formatter:off
-		@Override
-		public void registerStompEndpoints(StompEndpointRegistry registry) {
-			registry
-				.addEndpoint("/other")
-				.setHandshakeHandler(testHandshakeHandler());
-		}
-		// @formatter:on
-
-		// @formatter:off
-		@Override
-		protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
-			messages
-				.simpDestPathMatcher(new AntPathMatcher())
-				.simpDestMatchers("/app/a/*").permitAll()
-				.anyMessage().denyAll();
-		}
-		// @formatter:on
-
-		@Override
-		public void configureMessageBroker(MessageBrokerRegistry registry) {
-			registry.setPathMatcher(new AntPathMatcher("."));
-			registry.enableSimpleBroker("/queue/", "/topic/");
-			registry.setApplicationDestinationPrefixes("/app");
-		}
-
-		@Bean
-		public TestHandshakeHandler testHandshakeHandler() {
-			return new TestHandshakeHandler();
-		}
-
-	}
-
 	@Test
 	public void defaultPatternMatcher() {
 		loadConfig(DefaultPatternMatcherConfig.class);
@@ -378,42 +302,6 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests {
 		}
 	}
 
-	@Configuration
-	@EnableWebSocketMessageBroker
-	@Import(SyncExecutorConfig.class)
-	static class DefaultPatternMatcherConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
-
-		// @formatter:off
-		@Override
-		public void registerStompEndpoints(StompEndpointRegistry registry) {
-			registry
-				.addEndpoint("/other")
-				.setHandshakeHandler(testHandshakeHandler());
-		}
-		// @formatter:on
-
-		// @formatter:off
-		@Override
-		protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
-			messages
-				.simpDestMatchers("/app/a/*").permitAll()
-				.anyMessage().denyAll();
-		}
-		// @formatter:on
-
-		@Override
-		public void configureMessageBroker(MessageBrokerRegistry registry) {
-			registry.enableSimpleBroker("/queue/", "/topic/");
-			registry.setApplicationDestinationPrefixes("/app");
-		}
-
-		@Bean
-		public TestHandshakeHandler testHandshakeHandler() {
-			return new TestHandshakeHandler();
-		}
-
-	}
-
 	@Test
 	public void customExpression() {
 		loadConfig(CustomExpressionConfig.class);
@@ -464,57 +352,6 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests {
 		assertThat(((AbstractMessageChannel) messageChannel).getInterceptors()).contains(inboundChannelSecurity);
 	}
 
-	@Configuration
-	@EnableWebSocketMessageBroker
-	@Import(SyncExecutorConfig.class)
-	static class CustomExpressionConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
-
-		// @formatter:off
-		@Override
-		public void registerStompEndpoints(StompEndpointRegistry registry) {
-			registry
-				.addEndpoint("/other")
-				.setHandshakeHandler(testHandshakeHandler());
-		}
-		// @formatter:on
-
-		// @formatter:off
-		@Override
-		protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
-			messages
-				.anyMessage().access("denyRob()");
-		}
-		// @formatter:on
-
-		@Bean
-		public static SecurityExpressionHandler> messageSecurityExpressionHandler() {
-			return new DefaultMessageSecurityExpressionHandler() {
-				@Override
-				protected SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication,
-						Message invocation) {
-					return new MessageSecurityExpressionRoot(authentication, invocation) {
-						public boolean denyRob() {
-							Authentication auth = getAuthentication();
-							return auth != null && !"rob".equals(auth.getName());
-						}
-					};
-				}
-			};
-		}
-
-		@Override
-		public void configureMessageBroker(MessageBrokerRegistry registry) {
-			registry.enableSimpleBroker("/queue/", "/topic/");
-			registry.setApplicationDestinationPrefixes("/app");
-		}
-
-		@Bean
-		public TestHandshakeHandler testHandshakeHandler() {
-			return new TestHandshakeHandler();
-		}
-
-	}
-
 	private void assertHandshake(HttpServletRequest request) {
 		TestHandshakeHandler handshakeHandler = this.context.getBean(TestHandshakeHandler.class);
 		assertThat(handshakeHandler.attributes.get(CsrfToken.class.getName())).isSameAs(this.token);
@@ -572,6 +409,169 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests {
 		this.context.refresh();
 	}
 
+	@Configuration
+	@EnableWebSocketMessageBroker
+	@Import(SyncExecutorConfig.class)
+	static class MsmsRegistryCustomPatternMatcherConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
+
+		// @formatter:off
+		@Override
+		public void registerStompEndpoints(StompEndpointRegistry registry) {
+			registry
+				.addEndpoint("/other")
+				.setHandshakeHandler(testHandshakeHandler());
+		}
+		// @formatter:on
+
+		// @formatter:off
+		@Override
+		protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
+			messages
+				.simpDestMatchers("/app/a.*").permitAll()
+				.anyMessage().denyAll();
+		}
+		// @formatter:on
+
+		@Override
+		public void configureMessageBroker(MessageBrokerRegistry registry) {
+			registry.setPathMatcher(new AntPathMatcher("."));
+			registry.enableSimpleBroker("/queue/", "/topic/");
+			registry.setApplicationDestinationPrefixes("/app");
+		}
+
+		@Bean
+		public TestHandshakeHandler testHandshakeHandler() {
+			return new TestHandshakeHandler();
+		}
+
+	}
+
+	@Configuration
+	@EnableWebSocketMessageBroker
+	@Import(SyncExecutorConfig.class)
+	static class OverrideMsmsRegistryCustomPatternMatcherConfig
+			extends AbstractSecurityWebSocketMessageBrokerConfigurer {
+
+		// @formatter:off
+		@Override
+		public void registerStompEndpoints(StompEndpointRegistry registry) {
+			registry
+				.addEndpoint("/other")
+				.setHandshakeHandler(testHandshakeHandler());
+		}
+		// @formatter:on
+
+		// @formatter:off
+		@Override
+		protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
+			messages
+				.simpDestPathMatcher(new AntPathMatcher())
+				.simpDestMatchers("/app/a/*").permitAll()
+				.anyMessage().denyAll();
+		}
+		// @formatter:on
+
+		@Override
+		public void configureMessageBroker(MessageBrokerRegistry registry) {
+			registry.setPathMatcher(new AntPathMatcher("."));
+			registry.enableSimpleBroker("/queue/", "/topic/");
+			registry.setApplicationDestinationPrefixes("/app");
+		}
+
+		@Bean
+		public TestHandshakeHandler testHandshakeHandler() {
+			return new TestHandshakeHandler();
+		}
+
+	}
+
+	@Configuration
+	@EnableWebSocketMessageBroker
+	@Import(SyncExecutorConfig.class)
+	static class DefaultPatternMatcherConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
+
+		// @formatter:off
+		@Override
+		public void registerStompEndpoints(StompEndpointRegistry registry) {
+			registry
+				.addEndpoint("/other")
+				.setHandshakeHandler(testHandshakeHandler());
+		}
+		// @formatter:on
+
+		// @formatter:off
+		@Override
+		protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
+			messages
+				.simpDestMatchers("/app/a/*").permitAll()
+				.anyMessage().denyAll();
+		}
+		// @formatter:on
+
+		@Override
+		public void configureMessageBroker(MessageBrokerRegistry registry) {
+			registry.enableSimpleBroker("/queue/", "/topic/");
+			registry.setApplicationDestinationPrefixes("/app");
+		}
+
+		@Bean
+		public TestHandshakeHandler testHandshakeHandler() {
+			return new TestHandshakeHandler();
+		}
+
+	}
+
+	@Configuration
+	@EnableWebSocketMessageBroker
+	@Import(SyncExecutorConfig.class)
+	static class CustomExpressionConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
+
+		// @formatter:off
+		@Override
+		public void registerStompEndpoints(StompEndpointRegistry registry) {
+			registry
+				.addEndpoint("/other")
+				.setHandshakeHandler(testHandshakeHandler());
+		}
+		// @formatter:on
+
+		// @formatter:off
+		@Override
+		protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
+			messages
+				.anyMessage().access("denyRob()");
+		}
+		// @formatter:on
+
+		@Bean
+		public static SecurityExpressionHandler> messageSecurityExpressionHandler() {
+			return new DefaultMessageSecurityExpressionHandler() {
+				@Override
+				protected SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication,
+						Message invocation) {
+					return new MessageSecurityExpressionRoot(authentication, invocation) {
+						public boolean denyRob() {
+							Authentication auth = getAuthentication();
+							return auth != null && !"rob".equals(auth.getName());
+						}
+					};
+				}
+			};
+		}
+
+		@Override
+		public void configureMessageBroker(MessageBrokerRegistry registry) {
+			registry.enableSimpleBroker("/queue/", "/topic/");
+			registry.setApplicationDestinationPrefixes("/app");
+		}
+
+		@Bean
+		public TestHandshakeHandler testHandshakeHandler() {
+			return new TestHandshakeHandler();
+		}
+
+	}
+
 	@Controller
 	static class MyController {
 
diff --git a/config/src/test/java/org/springframework/security/config/http/CsrfConfigTests.java b/config/src/test/java/org/springframework/security/config/http/CsrfConfigTests.java
index bab0a7e840..edff3fe164 100644
--- a/config/src/test/java/org/springframework/security/config/http/CsrfConfigTests.java
+++ b/config/src/test/java/org/springframework/security/config/http/CsrfConfigTests.java
@@ -417,6 +417,27 @@ public class CsrfConfigTests {
 		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
 	}
 
+	ResultMatcher csrfChanged(MvcResult first) {
+		return (second) -> {
+			assertThat(first).isNotNull();
+			assertThat(second).isNotNull();
+			assertThat(first.getResponse().getContentAsString())
+					.isNotEqualTo(second.getResponse().getContentAsString());
+		};
+	}
+
+	ResultMatcher csrfCreated() {
+		return new CsrfCreatedResultMatcher();
+	}
+
+	ResultMatcher csrfInHeader() {
+		return new CsrfReturnedResultMatcher(result -> result.getResponse().getHeader("X-CSRF-TOKEN"));
+	}
+
+	ResultMatcher csrfInBody() {
+		return new CsrfReturnedResultMatcher(result -> result.getResponse().getContentAsString());
+	}
+
 	@Controller
 	public static class RootController {
 
@@ -458,27 +479,6 @@ public class CsrfConfigTests {
 
 	}
 
-	ResultMatcher csrfChanged(MvcResult first) {
-		return (second) -> {
-			assertThat(first).isNotNull();
-			assertThat(second).isNotNull();
-			assertThat(first.getResponse().getContentAsString())
-					.isNotEqualTo(second.getResponse().getContentAsString());
-		};
-	}
-
-	ResultMatcher csrfCreated() {
-		return new CsrfCreatedResultMatcher();
-	}
-
-	ResultMatcher csrfInHeader() {
-		return new CsrfReturnedResultMatcher(result -> result.getResponse().getHeader("X-CSRF-TOKEN"));
-	}
-
-	ResultMatcher csrfInBody() {
-		return new CsrfReturnedResultMatcher(result -> result.getResponse().getContentAsString());
-	}
-
 	@FunctionalInterface
 	interface ExceptionalFunction {
 
diff --git a/config/src/test/java/org/springframework/security/config/http/FormLoginConfigTests.java b/config/src/test/java/org/springframework/security/config/http/FormLoginConfigTests.java
index 190c0d66d7..4adaebc234 100644
--- a/config/src/test/java/org/springframework/security/config/http/FormLoginConfigTests.java
+++ b/config/src/test/java/org/springframework/security/config/http/FormLoginConfigTests.java
@@ -175,6 +175,24 @@ public class FormLoginConfigTests {
 				.andExpect(redirectedUrl("/login?error"));
 	}
 
+	private Filter getFilter(ApplicationContext context, Class filterClass) {
+		FilterChainProxy filterChain = context.getBean(BeanIds.FILTER_CHAIN_PROXY, FilterChainProxy.class);
+
+		List filters = filterChain.getFilters("/any");
+
+		for (Filter filter : filters) {
+			if (filter.getClass() == filterClass) {
+				return filter;
+			}
+		}
+
+		return null;
+	}
+
+	private String xml(String configName) {
+		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
+	}
+
 	@RestController
 	public static class LoginController {
 
@@ -204,22 +222,4 @@ public class FormLoginConfigTests {
 
 	}
 
-	private Filter getFilter(ApplicationContext context, Class filterClass) {
-		FilterChainProxy filterChain = context.getBean(BeanIds.FILTER_CHAIN_PROXY, FilterChainProxy.class);
-
-		List filters = filterChain.getFilters("/any");
-
-		for (Filter filter : filters) {
-			if (filter.getClass() == filterClass) {
-				return filter;
-			}
-		}
-
-		return null;
-	}
-
-	private String xml(String configName) {
-		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/http/HttpConfigTests.java b/config/src/test/java/org/springframework/security/config/http/HttpConfigTests.java
index 2f9fcd22de..3cd2f3be8b 100644
--- a/config/src/test/java/org/springframework/security/config/http/HttpConfigTests.java
+++ b/config/src/test/java/org/springframework/security/config/http/HttpConfigTests.java
@@ -73,6 +73,10 @@ public class HttpConfigTests {
 		assertThat(response.getRedirectedUrl()).isEqualTo("http://localhost/login");
 	}
 
+	private String xml(String configName) {
+		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
+	}
+
 	private static class EncodeUrlDenyingHttpServletResponseWrapper extends HttpServletResponseWrapper {
 
 		EncodeUrlDenyingHttpServletResponseWrapper(HttpServletResponse response) {
@@ -101,8 +105,4 @@ public class HttpConfigTests {
 
 	}
 
-	private String xml(String configName) {
-		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/http/HttpCorsConfigTests.java b/config/src/test/java/org/springframework/security/config/http/HttpCorsConfigTests.java
index 6f0beba0a0..a51ff6d242 100644
--- a/config/src/test/java/org/springframework/security/config/http/HttpCorsConfigTests.java
+++ b/config/src/test/java/org/springframework/security/config/http/HttpCorsConfigTests.java
@@ -99,29 +99,6 @@ public class HttpCorsConfigTests {
 				.andExpect(status().isOk());
 	}
 
-	@RestController
-	@CrossOrigin(methods = { RequestMethod.GET, RequestMethod.POST })
-	static class CorsController {
-
-		@RequestMapping("/")
-		String hello() {
-			return "Hello";
-		}
-
-	}
-
-	static class MyCorsConfigurationSource extends UrlBasedCorsConfigurationSource {
-
-		MyCorsConfigurationSource() {
-			CorsConfiguration configuration = new CorsConfiguration();
-			configuration.setAllowedOrigins(Arrays.asList("*"));
-			configuration.setAllowedMethods(Arrays.asList(RequestMethod.GET.name(), RequestMethod.POST.name()));
-
-			super.registerCorsConfiguration("/**", configuration);
-		}
-
-	}
-
 	private String xml(String configName) {
 		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
 	}
@@ -154,4 +131,27 @@ public class HttpCorsConfigTests {
 		};
 	}
 
+	@RestController
+	@CrossOrigin(methods = { RequestMethod.GET, RequestMethod.POST })
+	static class CorsController {
+
+		@RequestMapping("/")
+		String hello() {
+			return "Hello";
+		}
+
+	}
+
+	static class MyCorsConfigurationSource extends UrlBasedCorsConfigurationSource {
+
+		MyCorsConfigurationSource() {
+			CorsConfiguration configuration = new CorsConfiguration();
+			configuration.setAllowedOrigins(Arrays.asList("*"));
+			configuration.setAllowedMethods(Arrays.asList(RequestMethod.GET.name(), RequestMethod.POST.name()));
+
+			super.registerCorsConfiguration("/**", configuration);
+		}
+
+	}
+
 }
diff --git a/config/src/test/java/org/springframework/security/config/http/HttpHeadersConfigTests.java b/config/src/test/java/org/springframework/security/config/http/HttpHeadersConfigTests.java
index ad543ee1e3..4bc4ae8846 100644
--- a/config/src/test/java/org/springframework/security/config/http/HttpHeadersConfigTests.java
+++ b/config/src/test/java/org/springframework/security/config/http/HttpHeadersConfigTests.java
@@ -659,16 +659,6 @@ public class HttpHeadersConfigTests {
 				.andExpect(header().string("Referrer-Policy", "same-origin"));
 	}
 
-	@RestController
-	public static class SimpleController {
-
-		@GetMapping("/")
-		public String ok() {
-			return "ok";
-		}
-
-	}
-
 	private static ResultMatcher includesDefaults() {
 		return includes(defaultHeaders);
 	}
@@ -711,4 +701,14 @@ public class HttpHeadersConfigTests {
 		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
 	}
 
+	@RestController
+	public static class SimpleController {
+
+		@GetMapping("/")
+		public String ok() {
+			return "ok";
+		}
+
+	}
+
 }
diff --git a/config/src/test/java/org/springframework/security/config/http/InterceptUrlConfigTests.java b/config/src/test/java/org/springframework/security/config/http/InterceptUrlConfigTests.java
index 3c94ae6f00..565bea71d1 100644
--- a/config/src/test/java/org/springframework/security/config/http/InterceptUrlConfigTests.java
+++ b/config/src/test/java/org/springframework/security/config/http/InterceptUrlConfigTests.java
@@ -209,6 +209,20 @@ public class InterceptUrlConfigTests {
 				.isInstanceOf(BeanDefinitionParsingException.class);
 	}
 
+	private MockServletContext mockServletContext(String servletPath) {
+		MockServletContext servletContext = spy(new MockServletContext());
+		final ServletRegistration registration = mock(ServletRegistration.class);
+		when(registration.getMappings()).thenReturn(Collections.singleton(servletPath));
+		Answer> answer = invocation -> Collections.singletonMap("spring",
+				registration);
+		when(servletContext.getServletRegistrations()).thenAnswer(answer);
+		return servletContext;
+	}
+
+	private String xml(String configName) {
+		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
+	}
+
 	@RestController
 	static class PathController {
 
@@ -232,18 +246,4 @@ public class InterceptUrlConfigTests {
 
 	}
 
-	private MockServletContext mockServletContext(String servletPath) {
-		MockServletContext servletContext = spy(new MockServletContext());
-		final ServletRegistration registration = mock(ServletRegistration.class);
-		when(registration.getMappings()).thenReturn(Collections.singleton(servletPath));
-		Answer> answer = invocation -> Collections.singletonMap("spring",
-				registration);
-		when(servletContext.getServletRegistrations()).thenAnswer(answer);
-		return servletContext;
-	}
-
-	private String xml(String configName) {
-		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/http/MiscHttpConfigTests.java b/config/src/test/java/org/springframework/security/config/http/MiscHttpConfigTests.java
index 2c59e39123..604880a82a 100644
--- a/config/src/test/java/org/springframework/security/config/http/MiscHttpConfigTests.java
+++ b/config/src/test/java/org/springframework/security/config/http/MiscHttpConfigTests.java
@@ -694,6 +694,59 @@ public class MiscHttpConfigTests {
 				.andExpect(redirectedUrl("https://localhost:9443/protected"));
 	}
 
+	private void redirectLogsTo(OutputStream os, Class clazz) {
+		Logger logger = (Logger) LoggerFactory.getLogger(clazz);
+		Appender appender = mock(Appender.class);
+		when(appender.isStarted()).thenReturn(true);
+		doAnswer(writeTo(os)).when(appender).doAppend(any(ILoggingEvent.class));
+		logger.addAppender(appender);
+	}
+
+	private Answer writeTo(OutputStream os) {
+		return invocation -> {
+			os.write(invocation.getArgument(0).toString().getBytes());
+			return null;
+		};
+	}
+
+	private void assertThatFiltersMatchExpectedAutoConfigList() {
+		assertThatFiltersMatchExpectedAutoConfigList("/");
+	}
+
+	private void assertThatFiltersMatchExpectedAutoConfigList(String url) {
+		Iterator filters = getFilters(url).iterator();
+
+		assertThat(filters.next()).isInstanceOf(SecurityContextPersistenceFilter.class);
+		assertThat(filters.next()).isInstanceOf(WebAsyncManagerIntegrationFilter.class);
+		assertThat(filters.next()).isInstanceOf(HeaderWriterFilter.class);
+		assertThat(filters.next()).isInstanceOf(CsrfFilter.class);
+		assertThat(filters.next()).isInstanceOf(LogoutFilter.class);
+		assertThat(filters.next()).isInstanceOf(UsernamePasswordAuthenticationFilter.class);
+		assertThat(filters.next()).isInstanceOf(DefaultLoginPageGeneratingFilter.class);
+		assertThat(filters.next()).isInstanceOf(DefaultLogoutPageGeneratingFilter.class);
+		assertThat(filters.next()).isInstanceOf(BasicAuthenticationFilter.class);
+		assertThat(filters.next()).isInstanceOf(RequestCacheAwareFilter.class);
+		assertThat(filters.next()).isInstanceOf(SecurityContextHolderAwareRequestFilter.class);
+		assertThat(filters.next()).isInstanceOf(AnonymousAuthenticationFilter.class);
+		assertThat(filters.next()).isInstanceOf(SessionManagementFilter.class);
+		assertThat(filters.next()).isInstanceOf(ExceptionTranslationFilter.class);
+		assertThat(filters.next()).isInstanceOf(FilterSecurityInterceptor.class)
+				.hasFieldOrPropertyWithValue("observeOncePerRequest", true);
+	}
+
+	private  T getFilter(Class filterClass) {
+		return (T) getFilters("/").stream().filter(filterClass::isInstance).findFirst().orElse(null);
+	}
+
+	private List getFilters(String url) {
+		FilterChainProxy proxy = this.spring.getContext().getBean(FilterChainProxy.class);
+		return proxy.getFilters(url);
+	}
+
+	private static String xml(String configName) {
+		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
+	}
+
 	@RestController
 	static class BasicController {
 
@@ -847,57 +900,4 @@ public class MiscHttpConfigTests {
 
 	}
 
-	private void redirectLogsTo(OutputStream os, Class clazz) {
-		Logger logger = (Logger) LoggerFactory.getLogger(clazz);
-		Appender appender = mock(Appender.class);
-		when(appender.isStarted()).thenReturn(true);
-		doAnswer(writeTo(os)).when(appender).doAppend(any(ILoggingEvent.class));
-		logger.addAppender(appender);
-	}
-
-	private Answer writeTo(OutputStream os) {
-		return invocation -> {
-			os.write(invocation.getArgument(0).toString().getBytes());
-			return null;
-		};
-	}
-
-	private void assertThatFiltersMatchExpectedAutoConfigList() {
-		assertThatFiltersMatchExpectedAutoConfigList("/");
-	}
-
-	private void assertThatFiltersMatchExpectedAutoConfigList(String url) {
-		Iterator filters = getFilters(url).iterator();
-
-		assertThat(filters.next()).isInstanceOf(SecurityContextPersistenceFilter.class);
-		assertThat(filters.next()).isInstanceOf(WebAsyncManagerIntegrationFilter.class);
-		assertThat(filters.next()).isInstanceOf(HeaderWriterFilter.class);
-		assertThat(filters.next()).isInstanceOf(CsrfFilter.class);
-		assertThat(filters.next()).isInstanceOf(LogoutFilter.class);
-		assertThat(filters.next()).isInstanceOf(UsernamePasswordAuthenticationFilter.class);
-		assertThat(filters.next()).isInstanceOf(DefaultLoginPageGeneratingFilter.class);
-		assertThat(filters.next()).isInstanceOf(DefaultLogoutPageGeneratingFilter.class);
-		assertThat(filters.next()).isInstanceOf(BasicAuthenticationFilter.class);
-		assertThat(filters.next()).isInstanceOf(RequestCacheAwareFilter.class);
-		assertThat(filters.next()).isInstanceOf(SecurityContextHolderAwareRequestFilter.class);
-		assertThat(filters.next()).isInstanceOf(AnonymousAuthenticationFilter.class);
-		assertThat(filters.next()).isInstanceOf(SessionManagementFilter.class);
-		assertThat(filters.next()).isInstanceOf(ExceptionTranslationFilter.class);
-		assertThat(filters.next()).isInstanceOf(FilterSecurityInterceptor.class)
-				.hasFieldOrPropertyWithValue("observeOncePerRequest", true);
-	}
-
-	private  T getFilter(Class filterClass) {
-		return (T) getFilters("/").stream().filter(filterClass::isInstance).findFirst().orElse(null);
-	}
-
-	private List getFilters(String url) {
-		FilterChainProxy proxy = this.spring.getContext().getBean(FilterChainProxy.class);
-		return proxy.getFilters(url);
-	}
-
-	private static String xml(String configName) {
-		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/http/MultiHttpBlockConfigTests.java b/config/src/test/java/org/springframework/security/config/http/MultiHttpBlockConfigTests.java
index d3e8929d0d..267c810076 100644
--- a/config/src/test/java/org/springframework/security/config/http/MultiHttpBlockConfigTests.java
+++ b/config/src/test/java/org/springframework/security/config/http/MultiHttpBlockConfigTests.java
@@ -88,6 +88,10 @@ public class MultiHttpBlockConfigTests {
 				.andExpect(redirectedUrl("/"));
 	}
 
+	private String xml(String configName) {
+		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
+	}
+
 	@Controller
 	static class BasicController {
 
@@ -98,8 +102,4 @@ public class MultiHttpBlockConfigTests {
 
 	}
 
-	private String xml(String configName) {
-		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParserTests.java
index 46f04f410f..5d9be3a411 100644
--- a/config/src/test/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParserTests.java
+++ b/config/src/test/java/org/springframework/security/config/http/OAuth2ClientBeanDefinitionParserTests.java
@@ -209,17 +209,6 @@ public class OAuth2ClientBeanDefinitionParserTests {
 		this.mvc.perform(get("/authorized-client")).andExpect(status().isOk()).andExpect(content().string("resolved"));
 	}
 
-	@RestController
-	static class AuthorizedClientController {
-
-		@GetMapping("/authorized-client")
-		String authorizedClient(Model model,
-				@RegisteredOAuth2AuthorizedClient("google") OAuth2AuthorizedClient authorizedClient) {
-			return authorizedClient != null ? "resolved" : "not-resolved";
-		}
-
-	}
-
 	private static OAuth2AuthorizationRequest createAuthorizationRequest(ClientRegistration clientRegistration) {
 		Map attributes = new HashMap<>();
 		attributes.put(OAuth2ParameterNames.REGISTRATION_ID, clientRegistration.getRegistrationId());
@@ -233,4 +222,15 @@ public class OAuth2ClientBeanDefinitionParserTests {
 		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
 	}
 
+	@RestController
+	static class AuthorizedClientController {
+
+		@GetMapping("/authorized-client")
+		String authorizedClient(Model model,
+				@RegisteredOAuth2AuthorizedClient("google") OAuth2AuthorizedClient authorizedClient) {
+			return authorizedClient != null ? "resolved" : "not-resolved";
+		}
+
+	}
+
 }
diff --git a/config/src/test/java/org/springframework/security/config/http/OAuth2LoginBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/http/OAuth2LoginBeanDefinitionParserTests.java
index 5d29fc8360..6f5608d751 100644
--- a/config/src/test/java/org/springframework/security/config/http/OAuth2LoginBeanDefinitionParserTests.java
+++ b/config/src/test/java/org/springframework/security/config/http/OAuth2LoginBeanDefinitionParserTests.java
@@ -512,6 +512,10 @@ public class OAuth2LoginBeanDefinitionParserTests {
 		this.mvc.perform(get("/authorized-client")).andExpect(status().isOk()).andExpect(content().string("resolved"));
 	}
 
+	private String xml(String configName) {
+		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
+	}
+
 	@RestController
 	static class AuthorizedClientController {
 
@@ -523,8 +527,4 @@ public class OAuth2LoginBeanDefinitionParserTests {
 
 	}
 
-	private String xml(String configName) {
-		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests.java
index 2617e5405e..66e957d0a7 100644
--- a/config/src/test/java/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests.java
+++ b/config/src/test/java/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests.java
@@ -892,6 +892,82 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
 		verify(pc.getReaderContext()).error(anyString(), eq(element));
 	}
 
+	private static ResultMatcher invalidRequestHeader(String message) {
+		return header().string(HttpHeaders.WWW_AUTHENTICATE,
+				AllOf.allOf(new StringStartsWith("Bearer " + "error=\"invalid_request\", " + "error_description=\""),
+						new StringContains(message),
+						new StringEndsWith(", " + "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\"")));
+	}
+
+	private static ResultMatcher invalidTokenHeader(String message) {
+		return header().string(HttpHeaders.WWW_AUTHENTICATE,
+				AllOf.allOf(new StringStartsWith("Bearer " + "error=\"invalid_token\", " + "error_description=\""),
+						new StringContains(message),
+						new StringEndsWith(", " + "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\"")));
+	}
+
+	private static ResultMatcher insufficientScopeHeader() {
+		return header().string(HttpHeaders.WWW_AUTHENTICATE, "Bearer " + "error=\"insufficient_scope\""
+				+ ", error_description=\"The request requires higher privileges than provided by the access token.\""
+				+ ", error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\"");
+	}
+
+	private String jwkSet() {
+		return new JWKSet(new RSAKey.Builder(TestKeys.DEFAULT_PUBLIC_KEY).keyID("1").build()).toString();
+	}
+
+	private String jwtFromIssuer(String issuer) throws Exception {
+		Map claims = new HashMap<>();
+		claims.put(ISS, issuer);
+		claims.put(SUB, "test-subject");
+		claims.put("scope", "message:read");
+		JWSObject jws = new JWSObject(new JWSHeader.Builder(JWSAlgorithm.RS256).keyID("1").build(),
+				new Payload(new JSONObject(claims)));
+		jws.sign(new RSASSASigner(TestKeys.DEFAULT_PRIVATE_KEY));
+		return jws.serialize();
+	}
+
+	private void mockWebServer(String response) {
+		this.web.enqueue(new MockResponse().setResponseCode(200)
+				.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(response));
+	}
+
+	private void mockRestOperations(String response) {
+		RestOperations rest = this.spring.getContext().getBean(RestOperations.class);
+		HttpHeaders headers = new HttpHeaders();
+		headers.setContentType(MediaType.APPLICATION_JSON);
+		ResponseEntity entity = new ResponseEntity<>(response, headers, HttpStatus.OK);
+		Mockito.when(rest.exchange(any(RequestEntity.class), eq(String.class))).thenReturn(entity);
+	}
+
+	private String json(String name) throws IOException {
+		return resource(name + ".json");
+	}
+
+	private String jwks(String name) throws IOException {
+		return resource(name + ".jwks");
+	}
+
+	private String token(String name) throws IOException {
+		return resource(name + ".token");
+	}
+
+	private String resource(String suffix) throws IOException {
+		String name = this.getClass().getSimpleName() + "-" + suffix;
+		ClassPathResource resource = new ClassPathResource(name, this.getClass());
+		try (BufferedReader reader = new BufferedReader(new FileReader(resource.getFile()))) {
+			return reader.lines().collect(Collectors.joining());
+		}
+	}
+
+	private  T bean(Class beanClass) {
+		return this.spring.getContext().getBean(beanClass);
+	}
+
+	private String xml(String configName) {
+		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
+	}
+
 	static class JwtDecoderFactoryBean implements FactoryBean {
 
 		private RestOperations rest;
@@ -1025,80 +1101,4 @@ public class OAuth2ResourceServerBeanDefinitionParserTests {
 
 	}
 
-	private static ResultMatcher invalidRequestHeader(String message) {
-		return header().string(HttpHeaders.WWW_AUTHENTICATE,
-				AllOf.allOf(new StringStartsWith("Bearer " + "error=\"invalid_request\", " + "error_description=\""),
-						new StringContains(message),
-						new StringEndsWith(", " + "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\"")));
-	}
-
-	private static ResultMatcher invalidTokenHeader(String message) {
-		return header().string(HttpHeaders.WWW_AUTHENTICATE,
-				AllOf.allOf(new StringStartsWith("Bearer " + "error=\"invalid_token\", " + "error_description=\""),
-						new StringContains(message),
-						new StringEndsWith(", " + "error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\"")));
-	}
-
-	private static ResultMatcher insufficientScopeHeader() {
-		return header().string(HttpHeaders.WWW_AUTHENTICATE, "Bearer " + "error=\"insufficient_scope\""
-				+ ", error_description=\"The request requires higher privileges than provided by the access token.\""
-				+ ", error_uri=\"https://tools.ietf.org/html/rfc6750#section-3.1\"");
-	}
-
-	private String jwkSet() {
-		return new JWKSet(new RSAKey.Builder(TestKeys.DEFAULT_PUBLIC_KEY).keyID("1").build()).toString();
-	}
-
-	private String jwtFromIssuer(String issuer) throws Exception {
-		Map claims = new HashMap<>();
-		claims.put(ISS, issuer);
-		claims.put(SUB, "test-subject");
-		claims.put("scope", "message:read");
-		JWSObject jws = new JWSObject(new JWSHeader.Builder(JWSAlgorithm.RS256).keyID("1").build(),
-				new Payload(new JSONObject(claims)));
-		jws.sign(new RSASSASigner(TestKeys.DEFAULT_PRIVATE_KEY));
-		return jws.serialize();
-	}
-
-	private void mockWebServer(String response) {
-		this.web.enqueue(new MockResponse().setResponseCode(200)
-				.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(response));
-	}
-
-	private void mockRestOperations(String response) {
-		RestOperations rest = this.spring.getContext().getBean(RestOperations.class);
-		HttpHeaders headers = new HttpHeaders();
-		headers.setContentType(MediaType.APPLICATION_JSON);
-		ResponseEntity entity = new ResponseEntity<>(response, headers, HttpStatus.OK);
-		Mockito.when(rest.exchange(any(RequestEntity.class), eq(String.class))).thenReturn(entity);
-	}
-
-	private String json(String name) throws IOException {
-		return resource(name + ".json");
-	}
-
-	private String jwks(String name) throws IOException {
-		return resource(name + ".jwks");
-	}
-
-	private String token(String name) throws IOException {
-		return resource(name + ".token");
-	}
-
-	private String resource(String suffix) throws IOException {
-		String name = this.getClass().getSimpleName() + "-" + suffix;
-		ClassPathResource resource = new ClassPathResource(name, this.getClass());
-		try (BufferedReader reader = new BufferedReader(new FileReader(resource.getFile()))) {
-			return reader.lines().collect(Collectors.joining());
-		}
-	}
-
-	private  T bean(Class beanClass) {
-		return this.spring.getContext().getBean(beanClass);
-	}
-
-	private String xml(String configName) {
-		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/http/OpenIDConfigTests.java b/config/src/test/java/org/springframework/security/config/http/OpenIDConfigTests.java
index f3021d088a..886be53bb5 100644
--- a/config/src/test/java/org/springframework/security/config/http/OpenIDConfigTests.java
+++ b/config/src/test/java/org/springframework/security/config/http/OpenIDConfigTests.java
@@ -176,16 +176,6 @@ public class OpenIDConfigTests {
 		this.mvc.perform(get("/login")).andExpect(status().isOk()).andExpect(content().string("a custom login page"));
 	}
 
-	@RestController
-	static class CustomLoginController {
-
-		@GetMapping("/login")
-		public String custom() {
-			return "a custom login page";
-		}
-
-	}
-
 	private  T getFilter(Class clazz) {
 		FilterChainProxy filterChain = this.spring.getContext().getBean(FilterChainProxy.class);
 		return (T) filterChain.getFilters("/").stream().filter(clazz::isInstance).findFirst().orElse(null);
@@ -199,4 +189,14 @@ public class OpenIDConfigTests {
 		return (T) FieldUtils.getFieldValue(bean, fieldName);
 	}
 
+	@RestController
+	static class CustomLoginController {
+
+		@GetMapping("/login")
+		public String custom() {
+			return "a custom login page";
+		}
+
+	}
+
 }
diff --git a/config/src/test/java/org/springframework/security/config/http/PlaceHolderAndELConfigTests.java b/config/src/test/java/org/springframework/security/config/http/PlaceHolderAndELConfigTests.java
index 075b93570c..e78e90f5a4 100644
--- a/config/src/test/java/org/springframework/security/config/http/PlaceHolderAndELConfigTests.java
+++ b/config/src/test/java/org/springframework/security/config/http/PlaceHolderAndELConfigTests.java
@@ -169,6 +169,10 @@ public class PlaceHolderAndELConfigTests {
 		this.mvc.perform(get("/secured")).andExpect(forwardedUrl("/go-away"));
 	}
 
+	private String xml(String configName) {
+		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
+	}
+
 	@RestController
 	static class SimpleController {
 
@@ -184,8 +188,4 @@ public class PlaceHolderAndELConfigTests {
 
 	}
 
-	private String xml(String configName) {
-		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/http/RememberMeConfigTests.java b/config/src/test/java/org/springframework/security/config/http/RememberMeConfigTests.java
index e8ce6a5904..8f8731f10e 100644
--- a/config/src/test/java/org/springframework/security/config/http/RememberMeConfigTests.java
+++ b/config/src/test/java/org/springframework/security/config/http/RememberMeConfigTests.java
@@ -302,16 +302,6 @@ public class RememberMeConfigTests {
 								+ "remember-me-parameter or remember-me-cookie");
 	}
 
-	@RestController
-	static class BasicController {
-
-		@GetMapping("/authenticated")
-		String ok() {
-			return "ok";
-		}
-
-	}
-
 	private ResultActions rememberAuthentication(String username, String password) throws Exception {
 
 		return this.mvc.perform(login(username, password).param(DEFAULT_PARAMETER, "true").with(csrf()))
@@ -330,4 +320,14 @@ public class RememberMeConfigTests {
 		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
 	}
 
+	@RestController
+	static class BasicController {
+
+		@GetMapping("/authenticated")
+		String ok() {
+			return "ok";
+		}
+
+	}
+
 }
diff --git a/config/src/test/java/org/springframework/security/config/http/SecurityContextHolderAwareRequestConfigTests.java b/config/src/test/java/org/springframework/security/config/http/SecurityContextHolderAwareRequestConfigTests.java
index 98d431415a..d2f89090fc 100644
--- a/config/src/test/java/org/springframework/security/config/http/SecurityContextHolderAwareRequestConfigTests.java
+++ b/config/src/test/java/org/springframework/security/config/http/SecurityContextHolderAwareRequestConfigTests.java
@@ -206,6 +206,10 @@ public class SecurityContextHolderAwareRequestConfigTests {
 		this.mvc.perform(get("/role")).andExpect(content().string("true"));
 	}
 
+	private String xml(String configName) {
+		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
+	}
+
 	@RestController
 	public static class ServletAuthenticatedController {
 
@@ -267,8 +271,4 @@ public class SecurityContextHolderAwareRequestConfigTests {
 
 	}
 
-	private String xml(String configName) {
-		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigTests.java b/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigTests.java
index ded6945508..00445262d6 100644
--- a/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigTests.java
+++ b/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigTests.java
@@ -382,6 +382,49 @@ public class SessionManagementConfigTests {
 		})).andExpect(redirectedUrl("/timeoutUrl"));
 	}
 
+	private void sessionRegistryIsValid() {
+		SessionRegistry sessionRegistry = this.spring.getContext().getBean("sessionRegistry", SessionRegistry.class);
+
+		assertThat(sessionRegistry).isNotNull();
+
+		assertThat(this.getFilter(ConcurrentSessionFilter.class)).returns(sessionRegistry,
+				this::extractSessionRegistry);
+		assertThat(this.getFilter(UsernamePasswordAuthenticationFilter.class)).returns(sessionRegistry,
+				this::extractSessionRegistry);
+		// SEC-1143
+		assertThat(this.getFilter(SessionManagementFilter.class)).returns(sessionRegistry,
+				this::extractSessionRegistry);
+	}
+
+	private SessionRegistry extractSessionRegistry(ConcurrentSessionFilter filter) {
+		return getFieldValue(filter, "sessionRegistry");
+	}
+
+	private SessionRegistry extractSessionRegistry(UsernamePasswordAuthenticationFilter filter) {
+		SessionAuthenticationStrategy strategy = getFieldValue(filter, "sessionStrategy");
+		List strategies = getFieldValue(strategy, "delegateStrategies");
+		return getFieldValue(strategies.get(0), "sessionRegistry");
+	}
+
+	private SessionRegistry extractSessionRegistry(SessionManagementFilter filter) {
+		SessionAuthenticationStrategy strategy = getFieldValue(filter, "sessionAuthenticationStrategy");
+		List strategies = getFieldValue(strategy, "delegateStrategies");
+		return getFieldValue(strategies.get(0), "sessionRegistry");
+	}
+
+	private  T getFieldValue(Object target, String fieldName) {
+		try {
+			return (T) FieldUtils.getFieldValue(target, fieldName);
+		}
+		catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	private static SessionResultMatcher session() {
+		return new SessionResultMatcher();
+	}
+
 	/**
 	 * SEC-2680
 	 */
@@ -408,6 +451,46 @@ public class SessionManagementConfigTests {
 		assertThat(lfLogoutHandlers).hasAtLeastOneElementOfType(LogoutSuccessEventPublishingLogoutHandler.class);
 	}
 
+	private static MockHttpServletResponse request(MockHttpServletRequest request, ApplicationContext context)
+			throws IOException, ServletException {
+
+		MockHttpServletResponse response = new MockHttpServletResponse();
+
+		FilterChainProxy proxy = context.getBean(FilterChainProxy.class);
+
+		proxy.doFilter(request, new EncodeUrlDenyingHttpServletResponseWrapper(response), (req, resp) -> {
+		});
+
+		return response;
+	}
+
+	private MockHttpSession expiredSession() {
+		MockHttpSession session = new MockHttpSession();
+		SessionRegistry sessionRegistry = this.spring.getContext().getBean(SessionRegistry.class);
+		sessionRegistry.registerNewSession(session.getId(), "user");
+		sessionRegistry.getSessionInformation(session.getId()).expireNow();
+		return session;
+	}
+
+	private  T getFilter(Class filterClass) {
+		return (T) getFilters().stream().filter(filterClass::isInstance).findFirst().orElse(null);
+	}
+
+	private List getFilters() {
+		FilterChainProxy proxy = this.spring.getContext().getBean(FilterChainProxy.class);
+
+		return proxy.getFilters("/");
+	}
+
+	private ServletContext servletContext() {
+		WebApplicationContext context = this.spring.getContext();
+		return context.getServletContext();
+	}
+
+	private String xml(String configName) {
+		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
+	}
+
 	static class TeapotSessionAuthenticationStrategy implements SessionAuthenticationStrategy {
 
 		@Override
@@ -459,49 +542,6 @@ public class SessionManagementConfigTests {
 
 	}
 
-	private void sessionRegistryIsValid() {
-		SessionRegistry sessionRegistry = this.spring.getContext().getBean("sessionRegistry", SessionRegistry.class);
-
-		assertThat(sessionRegistry).isNotNull();
-
-		assertThat(this.getFilter(ConcurrentSessionFilter.class)).returns(sessionRegistry,
-				this::extractSessionRegistry);
-		assertThat(this.getFilter(UsernamePasswordAuthenticationFilter.class)).returns(sessionRegistry,
-				this::extractSessionRegistry);
-		// SEC-1143
-		assertThat(this.getFilter(SessionManagementFilter.class)).returns(sessionRegistry,
-				this::extractSessionRegistry);
-	}
-
-	private SessionRegistry extractSessionRegistry(ConcurrentSessionFilter filter) {
-		return getFieldValue(filter, "sessionRegistry");
-	}
-
-	private SessionRegistry extractSessionRegistry(UsernamePasswordAuthenticationFilter filter) {
-		SessionAuthenticationStrategy strategy = getFieldValue(filter, "sessionStrategy");
-		List strategies = getFieldValue(strategy, "delegateStrategies");
-		return getFieldValue(strategies.get(0), "sessionRegistry");
-	}
-
-	private SessionRegistry extractSessionRegistry(SessionManagementFilter filter) {
-		SessionAuthenticationStrategy strategy = getFieldValue(filter, "sessionAuthenticationStrategy");
-		List strategies = getFieldValue(strategy, "delegateStrategies");
-		return getFieldValue(strategies.get(0), "sessionRegistry");
-	}
-
-	private  T getFieldValue(Object target, String fieldName) {
-		try {
-			return (T) FieldUtils.getFieldValue(target, fieldName);
-		}
-		catch (Exception e) {
-			throw new RuntimeException(e);
-		}
-	}
-
-	private static SessionResultMatcher session() {
-		return new SessionResultMatcher();
-	}
-
 	private static class SessionResultMatcher implements ResultMatcher {
 
 		private String id;
@@ -552,19 +592,6 @@ public class SessionManagementConfigTests {
 
 	}
 
-	private static MockHttpServletResponse request(MockHttpServletRequest request, ApplicationContext context)
-			throws IOException, ServletException {
-
-		MockHttpServletResponse response = new MockHttpServletResponse();
-
-		FilterChainProxy proxy = context.getBean(FilterChainProxy.class);
-
-		proxy.doFilter(request, new EncodeUrlDenyingHttpServletResponseWrapper(response), (req, resp) -> {
-		});
-
-		return response;
-	}
-
 	private static class EncodeUrlDenyingHttpServletResponseWrapper extends HttpServletResponseWrapper {
 
 		EncodeUrlDenyingHttpServletResponseWrapper(HttpServletResponse response) {
@@ -593,31 +620,4 @@ public class SessionManagementConfigTests {
 
 	}
 
-	private MockHttpSession expiredSession() {
-		MockHttpSession session = new MockHttpSession();
-		SessionRegistry sessionRegistry = this.spring.getContext().getBean(SessionRegistry.class);
-		sessionRegistry.registerNewSession(session.getId(), "user");
-		sessionRegistry.getSessionInformation(session.getId()).expireNow();
-		return session;
-	}
-
-	private  T getFilter(Class filterClass) {
-		return (T) getFilters().stream().filter(filterClass::isInstance).findFirst().orElse(null);
-	}
-
-	private List getFilters() {
-		FilterChainProxy proxy = this.spring.getContext().getBean(FilterChainProxy.class);
-
-		return proxy.getFilters("/");
-	}
-
-	private ServletContext servletContext() {
-		WebApplicationContext context = this.spring.getContext();
-		return context.getServletContext();
-	}
-
-	private String xml(String configName) {
-		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigTransientAuthenticationTests.java b/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigTransientAuthenticationTests.java
index fe909288bc..8c1c2af17a 100644
--- a/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigTransientAuthenticationTests.java
+++ b/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigTransientAuthenticationTests.java
@@ -60,6 +60,10 @@ public class SessionManagementConfigTransientAuthenticationTests {
 		assertThat(result.getRequest().getSession(false)).isNotNull();
 	}
 
+	private String xml(String configName) {
+		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
+	}
+
 	static class TransientAuthenticationProvider implements AuthenticationProvider {
 
 		@Override
@@ -93,8 +97,4 @@ public class SessionManagementConfigTransientAuthenticationTests {
 
 	}
 
-	private String xml(String configName) {
-		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParserTests.java
index 25ba7efe8d..81a8a3838d 100644
--- a/config/src/test/java/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParserTests.java
+++ b/config/src/test/java/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParserTests.java
@@ -391,6 +391,14 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
 		foo.foo(new SecurityConfig("A"));
 	}
 
+	private void setContext(String context) {
+		this.appContext = new InMemoryXmlApplicationContext(context);
+	}
+
+	private void setContext(String context, ApplicationContext parent) {
+		this.appContext = new InMemoryXmlApplicationContext(context, parent);
+	}
+
 	static class CustomAuthManager implements AuthenticationManager, ApplicationContextAware {
 
 		private String beanName;
@@ -420,14 +428,6 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
 
 	}
 
-	private void setContext(String context) {
-		this.appContext = new InMemoryXmlApplicationContext(context);
-	}
-
-	private void setContext(String context, ApplicationContext parent) {
-		this.appContext = new InMemoryXmlApplicationContext(context, parent);
-	}
-
 	interface Foo {
 
 		void foo(T action);
diff --git a/config/src/test/java/org/springframework/security/config/web/server/FormLoginTests.java b/config/src/test/java/org/springframework/security/config/web/server/FormLoginTests.java
index df1e409ac7..cdda790028 100644
--- a/config/src/test/java/org/springframework/security/config/web/server/FormLoginTests.java
+++ b/config/src/test/java/org/springframework/security/config/web/server/FormLoginTests.java
@@ -256,6 +256,12 @@ public class FormLoginTests {
 		verify(formLoginSecContextRepository).save(any(), any());
 	}
 
+	Mono authentication(Authentication authentication) {
+		SecurityContext context = new SecurityContextImpl();
+		context.setAuthentication(authentication);
+		return Mono.just(context);
+	}
+
 	public static class CustomLoginPage {
 
 		private WebDriver driver;
@@ -491,10 +497,4 @@ public class FormLoginTests {
 
 	}
 
-	Mono authentication(Authentication authentication) {
-		SecurityContext context = new SecurityContextImpl();
-		context.setAuthentication(authentication);
-		return Mono.just(context);
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/web/server/OAuth2ClientSpecTests.java b/config/src/test/java/org/springframework/security/config/web/server/OAuth2ClientSpecTests.java
index 8942fc5b21..ea814e54fc 100644
--- a/config/src/test/java/org/springframework/security/config/web/server/OAuth2ClientSpecTests.java
+++ b/config/src/test/java/org/springframework/security/config/web/server/OAuth2ClientSpecTests.java
@@ -114,41 +114,6 @@ public class OAuth2ClientSpecTests {
 		this.client.get().uri("/").exchange().expectStatus().is3xxRedirection();
 	}
 
-	@EnableWebFlux
-	@EnableWebFluxSecurity
-	static class Config {
-
-		@Bean
-		SecurityWebFilterChain springSecurity(ServerHttpSecurity http) {
-			// @formatter:off
-			http
-				.oauth2Client();
-			// @formatter:on
-			return http.build();
-		}
-
-		@Bean
-		ReactiveClientRegistrationRepository clientRegistrationRepository() {
-			return mock(ReactiveClientRegistrationRepository.class);
-		}
-
-		@Bean
-		ServerOAuth2AuthorizedClientRepository authorizedClientRepository() {
-			return mock(ServerOAuth2AuthorizedClientRepository.class);
-		}
-
-	}
-
-	@RestController
-	static class AuthorizedClientController {
-
-		@GetMapping("/")
-		String home(@RegisteredOAuth2AuthorizedClient("github") OAuth2AuthorizedClient authorizedClient) {
-			return "home";
-		}
-
-	}
-
 	@Test
 	public void oauth2ClientWhenCustomObjectsThenUsed() {
 		this.spring.register(ClientRegistrationConfig.class, OAuth2ClientCustomConfig.class,
@@ -189,47 +154,6 @@ public class OAuth2ClientSpecTests {
 		verify(requestCache).getRedirectUri(any());
 	}
 
-	@EnableWebFlux
-	@EnableWebFluxSecurity
-	static class ClientRegistrationConfig {
-
-		private ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().build();
-
-		@Bean
-		InMemoryReactiveClientRegistrationRepository clientRegistrationRepository() {
-			return new InMemoryReactiveClientRegistrationRepository(this.clientRegistration);
-		}
-
-	}
-
-	@Configuration
-	static class OAuth2ClientCustomConfig {
-
-		ReactiveAuthenticationManager manager = mock(ReactiveAuthenticationManager.class);
-
-		ServerAuthenticationConverter authenticationConverter = mock(ServerAuthenticationConverter.class);
-
-		ServerAuthorizationRequestRepository authorizationRequestRepository = mock(
-				ServerAuthorizationRequestRepository.class);
-
-		ServerRequestCache requestCache = mock(ServerRequestCache.class);
-
-		@Bean
-		public SecurityWebFilterChain springSecurityFilter(ServerHttpSecurity http) {
-			// @formatter:off
-			http
-				.oauth2Client()
-					.authenticationConverter(this.authenticationConverter)
-					.authenticationManager(this.manager)
-					.authorizationRequestRepository(this.authorizationRequestRepository)
-					.and()
-				.requestCache(c -> c.requestCache(this.requestCache));
-			// @formatter:on
-			return http.build();
-		}
-
-	}
-
 	@Test
 	public void oauth2ClientWhenCustomObjectsInLambdaThenUsed() {
 		this.spring.register(ClientRegistrationConfig.class, OAuth2ClientInLambdaCustomConfig.class,
@@ -271,6 +195,82 @@ public class OAuth2ClientSpecTests {
 		verify(requestCache).getRedirectUri(any());
 	}
 
+	@EnableWebFlux
+	@EnableWebFluxSecurity
+	static class Config {
+
+		@Bean
+		SecurityWebFilterChain springSecurity(ServerHttpSecurity http) {
+			// @formatter:off
+			http
+				.oauth2Client();
+			// @formatter:on
+			return http.build();
+		}
+
+		@Bean
+		ReactiveClientRegistrationRepository clientRegistrationRepository() {
+			return mock(ReactiveClientRegistrationRepository.class);
+		}
+
+		@Bean
+		ServerOAuth2AuthorizedClientRepository authorizedClientRepository() {
+			return mock(ServerOAuth2AuthorizedClientRepository.class);
+		}
+
+	}
+
+	@RestController
+	static class AuthorizedClientController {
+
+		@GetMapping("/")
+		String home(@RegisteredOAuth2AuthorizedClient("github") OAuth2AuthorizedClient authorizedClient) {
+			return "home";
+		}
+
+	}
+
+	@EnableWebFlux
+	@EnableWebFluxSecurity
+	static class ClientRegistrationConfig {
+
+		private ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration().build();
+
+		@Bean
+		InMemoryReactiveClientRegistrationRepository clientRegistrationRepository() {
+			return new InMemoryReactiveClientRegistrationRepository(this.clientRegistration);
+		}
+
+	}
+
+	@Configuration
+	static class OAuth2ClientCustomConfig {
+
+		ReactiveAuthenticationManager manager = mock(ReactiveAuthenticationManager.class);
+
+		ServerAuthenticationConverter authenticationConverter = mock(ServerAuthenticationConverter.class);
+
+		ServerAuthorizationRequestRepository authorizationRequestRepository = mock(
+				ServerAuthorizationRequestRepository.class);
+
+		ServerRequestCache requestCache = mock(ServerRequestCache.class);
+
+		@Bean
+		public SecurityWebFilterChain springSecurityFilter(ServerHttpSecurity http) {
+			// @formatter:off
+			http
+				.oauth2Client()
+					.authenticationConverter(this.authenticationConverter)
+					.authenticationManager(this.manager)
+					.authorizationRequestRepository(this.authorizationRequestRepository)
+					.and()
+				.requestCache(c -> c.requestCache(this.requestCache));
+			// @formatter:on
+			return http.build();
+		}
+
+	}
+
 	@Configuration
 	static class OAuth2ClientInLambdaCustomConfig {
 
diff --git a/config/src/test/java/org/springframework/security/config/web/server/OAuth2LoginTests.java b/config/src/test/java/org/springframework/security/config/web/server/OAuth2LoginTests.java
index 50bda99f27..2bb5aaee8c 100644
--- a/config/src/test/java/org/springframework/security/config/web/server/OAuth2LoginTests.java
+++ b/config/src/test/java/org/springframework/security/config/web/server/OAuth2LoginTests.java
@@ -151,16 +151,6 @@ public class OAuth2LoginTests {
 				.assertClientRegistrationByName(OAuth2LoginTests.github.getClientName()).and();
 	}
 
-	@EnableWebFluxSecurity
-	static class OAuth2LoginWithMultipleClientRegistrations {
-
-		@Bean
-		InMemoryReactiveClientRegistrationRepository clientRegistrationRepository() {
-			return new InMemoryReactiveClientRegistrationRepository(github, google);
-		}
-
-	}
-
 	@Test
 	public void defaultLoginPageWithSingleClientRegistrationThenRedirect() {
 		this.spring.register(OAuth2LoginWithSingleClientRegistrations.class).autowire();
@@ -184,21 +174,6 @@ public class OAuth2LoginTests {
 				.is3xxRedirection().expectHeader().valueEquals(HttpHeaders.LOCATION, "/login");
 	}
 
-	@EnableWebFlux
-	static class WebFluxConfig {
-
-	}
-
-	@EnableWebFluxSecurity
-	static class OAuth2LoginWithSingleClientRegistrations {
-
-		@Bean
-		InMemoryReactiveClientRegistrationRepository clientRegistrationRepository() {
-			return new InMemoryReactiveClientRegistrationRepository(github);
-		}
-
-	}
-
 	@Test
 	public void oauth2AuthorizeWhenCustomObjectsThenUsed() {
 		this.spring.register(OAuth2LoginWithSingleClientRegistrations.class, OAuth2AuthorizeWithMockObjectsConfig.class,
@@ -223,47 +198,6 @@ public class OAuth2LoginTests {
 		verify(requestCache).saveRequest(any());
 	}
 
-	@EnableWebFlux
-	static class OAuth2AuthorizeWithMockObjectsConfig {
-
-		ServerOAuth2AuthorizedClientRepository authorizedClientRepository = mock(
-				ServerOAuth2AuthorizedClientRepository.class);
-
-		ServerAuthorizationRequestRepository authorizationRequestRepository = mock(
-				ServerAuthorizationRequestRepository.class);
-
-		ServerRequestCache requestCache = mock(ServerRequestCache.class);
-
-		@Bean
-		SecurityWebFilterChain springSecurity(ServerHttpSecurity http) {
-			// @formatter:off
-			http
-				.requestCache()
-					.requestCache(this.requestCache)
-					.and()
-				.oauth2Login()
-					.authorizationRequestRepository(this.authorizationRequestRepository);
-			// @formatter:on
-			return http.build();
-		}
-
-		@Bean
-		ServerOAuth2AuthorizedClientRepository authorizedClientRepository() {
-			return this.authorizedClientRepository;
-		}
-
-	}
-
-	@RestController
-	static class AuthorizedClientController {
-
-		@GetMapping("/")
-		String home(@RegisteredOAuth2AuthorizedClient("github") OAuth2AuthorizedClient authorizedClient) {
-			return "home";
-		}
-
-	}
-
 	@Test
 	public void oauth2LoginWhenCustomObjectsThenUsed() {
 		this.spring.register(OAuth2LoginWithSingleClientRegistrations.class,
@@ -359,41 +293,6 @@ public class OAuth2LoginTests {
 		verify(failureHandler).onAuthenticationFailure(any(), any());
 	}
 
-	@Configuration
-	static class OAuth2LoginMockAuthenticationManagerConfig {
-
-		ReactiveAuthenticationManager manager = mock(ReactiveAuthenticationManager.class);
-
-		ServerAuthenticationConverter authenticationConverter = mock(ServerAuthenticationConverter.class);
-
-		ServerWebExchangeMatcher matcher = mock(ServerWebExchangeMatcher.class);
-
-		ServerOAuth2AuthorizationRequestResolver resolver = mock(ServerOAuth2AuthorizationRequestResolver.class);
-
-		ServerAuthenticationSuccessHandler successHandler = mock(ServerAuthenticationSuccessHandler.class);
-
-		ServerAuthenticationFailureHandler failureHandler = mock(ServerAuthenticationFailureHandler.class);
-
-		@Bean
-		public SecurityWebFilterChain springSecurityFilter(ServerHttpSecurity http) {
-			// @formatter:off
-			http
-				.authorizeExchange()
-					.anyExchange().authenticated()
-					.and()
-				.oauth2Login()
-					.authenticationConverter(this.authenticationConverter)
-					.authenticationManager(this.manager)
-					.authenticationMatcher(this.matcher)
-					.authorizationRequestResolver(this.resolver)
-					.authenticationSuccessHandler(this.successHandler)
-					.authenticationFailureHandler(this.failureHandler);
-			// @formatter:on
-			return http.build();
-		}
-
-	}
-
 	@Test
 	public void oauth2LoginWhenCustomObjectsInLambdaThenUsed() {
 		this.spring.register(OAuth2LoginWithSingleClientRegistrations.class,
@@ -440,41 +339,6 @@ public class OAuth2LoginTests {
 		verify(successHandler).onAuthenticationSuccess(any(), any());
 	}
 
-	@Configuration
-	static class OAuth2LoginMockAuthenticationManagerInLambdaConfig {
-
-		ReactiveAuthenticationManager manager = mock(ReactiveAuthenticationManager.class);
-
-		ServerAuthenticationConverter authenticationConverter = mock(ServerAuthenticationConverter.class);
-
-		ServerWebExchangeMatcher matcher = mock(ServerWebExchangeMatcher.class);
-
-		ServerOAuth2AuthorizationRequestResolver resolver = mock(ServerOAuth2AuthorizationRequestResolver.class);
-
-		ServerAuthenticationSuccessHandler successHandler = mock(ServerAuthenticationSuccessHandler.class);
-
-		@Bean
-		public SecurityWebFilterChain springSecurityFilter(ServerHttpSecurity http) {
-			// @formatter:off
-			http
-				.authorizeExchange(exchanges ->
-					exchanges
-						.anyExchange().authenticated()
-				)
-				.oauth2Login(oauth2Login ->
-					oauth2Login
-						.authenticationConverter(this.authenticationConverter)
-						.authenticationManager(this.manager)
-						.authenticationMatcher(this.matcher)
-						.authorizationRequestResolver(this.resolver)
-						.authenticationSuccessHandler(this.successHandler)
-				);
-			// @formatter:on
-			return http.build();
-		}
-
-	}
-
 	@Test
 	public void oauth2LoginWhenCustomBeansThenUsed() {
 		this.spring.register(OAuth2LoginWithMultipleClientRegistrations.class, OAuth2LoginWithCustomBeansConfig.class)
@@ -585,6 +449,177 @@ public class OAuth2LoginTests {
 				.valueEquals("Location", "/login?error");
 	}
 
+	@Test
+	public void logoutWhenUsingOidcLogoutHandlerThenRedirects() {
+		this.spring.register(OAuth2LoginConfigWithOidcLogoutSuccessHandler.class).autowire();
+
+		OAuth2AuthenticationToken token = new OAuth2AuthenticationToken(TestOidcUsers.create(),
+				AuthorityUtils.NO_AUTHORITIES, getBean(ClientRegistration.class).getRegistrationId());
+
+		ServerSecurityContextRepository repository = getBean(ServerSecurityContextRepository.class);
+		when(repository.load(any())).thenReturn(authentication(token));
+
+		this.client.post().uri("/logout").exchange().expectHeader().valueEquals("Location",
+				"https://logout?id_token_hint=id-token");
+	}
+
+	// gh-8609
+	@Test
+	public void oauth2LoginWhenAuthenticationConverterFailsThenDefaultRedirectToLogin() {
+		this.spring.register(OAuth2LoginWithMultipleClientRegistrations.class).autowire();
+
+		WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(this.springSecurity).build();
+
+		webTestClient.get().uri("/login/oauth2/code/google").exchange().expectStatus().is3xxRedirection().expectHeader()
+				.valueEquals("Location", "/login?error");
+	}
+
+	Mono authentication(Authentication authentication) {
+		SecurityContext context = new SecurityContextImpl();
+		context.setAuthentication(authentication);
+		return Mono.just(context);
+	}
+
+	 T getBean(Class beanClass) {
+		return this.spring.getContext().getBean(beanClass);
+	}
+
+	@EnableWebFluxSecurity
+	static class OAuth2LoginWithMultipleClientRegistrations {
+
+		@Bean
+		InMemoryReactiveClientRegistrationRepository clientRegistrationRepository() {
+			return new InMemoryReactiveClientRegistrationRepository(github, google);
+		}
+
+	}
+
+	@EnableWebFlux
+	static class WebFluxConfig {
+
+	}
+
+	@EnableWebFluxSecurity
+	static class OAuth2LoginWithSingleClientRegistrations {
+
+		@Bean
+		InMemoryReactiveClientRegistrationRepository clientRegistrationRepository() {
+			return new InMemoryReactiveClientRegistrationRepository(github);
+		}
+
+	}
+
+	@EnableWebFlux
+	static class OAuth2AuthorizeWithMockObjectsConfig {
+
+		ServerOAuth2AuthorizedClientRepository authorizedClientRepository = mock(
+				ServerOAuth2AuthorizedClientRepository.class);
+
+		ServerAuthorizationRequestRepository authorizationRequestRepository = mock(
+				ServerAuthorizationRequestRepository.class);
+
+		ServerRequestCache requestCache = mock(ServerRequestCache.class);
+
+		@Bean
+		SecurityWebFilterChain springSecurity(ServerHttpSecurity http) {
+			// @formatter:off
+			http
+				.requestCache()
+					.requestCache(this.requestCache)
+					.and()
+				.oauth2Login()
+					.authorizationRequestRepository(this.authorizationRequestRepository);
+			// @formatter:on
+			return http.build();
+		}
+
+		@Bean
+		ServerOAuth2AuthorizedClientRepository authorizedClientRepository() {
+			return this.authorizedClientRepository;
+		}
+
+	}
+
+	@RestController
+	static class AuthorizedClientController {
+
+		@GetMapping("/")
+		String home(@RegisteredOAuth2AuthorizedClient("github") OAuth2AuthorizedClient authorizedClient) {
+			return "home";
+		}
+
+	}
+
+	@Configuration
+	static class OAuth2LoginMockAuthenticationManagerConfig {
+
+		ReactiveAuthenticationManager manager = mock(ReactiveAuthenticationManager.class);
+
+		ServerAuthenticationConverter authenticationConverter = mock(ServerAuthenticationConverter.class);
+
+		ServerWebExchangeMatcher matcher = mock(ServerWebExchangeMatcher.class);
+
+		ServerOAuth2AuthorizationRequestResolver resolver = mock(ServerOAuth2AuthorizationRequestResolver.class);
+
+		ServerAuthenticationSuccessHandler successHandler = mock(ServerAuthenticationSuccessHandler.class);
+
+		ServerAuthenticationFailureHandler failureHandler = mock(ServerAuthenticationFailureHandler.class);
+
+		@Bean
+		public SecurityWebFilterChain springSecurityFilter(ServerHttpSecurity http) {
+			// @formatter:off
+			http
+				.authorizeExchange()
+					.anyExchange().authenticated()
+					.and()
+				.oauth2Login()
+					.authenticationConverter(this.authenticationConverter)
+					.authenticationManager(this.manager)
+					.authenticationMatcher(this.matcher)
+					.authorizationRequestResolver(this.resolver)
+					.authenticationSuccessHandler(this.successHandler)
+					.authenticationFailureHandler(this.failureHandler);
+			// @formatter:on
+			return http.build();
+		}
+
+	}
+
+	@Configuration
+	static class OAuth2LoginMockAuthenticationManagerInLambdaConfig {
+
+		ReactiveAuthenticationManager manager = mock(ReactiveAuthenticationManager.class);
+
+		ServerAuthenticationConverter authenticationConverter = mock(ServerAuthenticationConverter.class);
+
+		ServerWebExchangeMatcher matcher = mock(ServerWebExchangeMatcher.class);
+
+		ServerOAuth2AuthorizationRequestResolver resolver = mock(ServerOAuth2AuthorizationRequestResolver.class);
+
+		ServerAuthenticationSuccessHandler successHandler = mock(ServerAuthenticationSuccessHandler.class);
+
+		@Bean
+		public SecurityWebFilterChain springSecurityFilter(ServerHttpSecurity http) {
+			// @formatter:off
+			http
+				.authorizeExchange(exchanges ->
+					exchanges
+						.anyExchange().authenticated()
+				)
+				.oauth2Login(oauth2Login ->
+					oauth2Login
+						.authenticationConverter(this.authenticationConverter)
+						.authenticationManager(this.manager)
+						.authenticationMatcher(this.matcher)
+						.authorizationRequestResolver(this.resolver)
+						.authenticationSuccessHandler(this.successHandler)
+				);
+			// @formatter:on
+			return http.build();
+		}
+
+	}
+
 	@Configuration
 	static class OAuth2LoginWithCustomBeansConfig {
 
@@ -654,20 +689,6 @@ public class OAuth2LoginTests {
 
 	}
 
-	@Test
-	public void logoutWhenUsingOidcLogoutHandlerThenRedirects() {
-		this.spring.register(OAuth2LoginConfigWithOidcLogoutSuccessHandler.class).autowire();
-
-		OAuth2AuthenticationToken token = new OAuth2AuthenticationToken(TestOidcUsers.create(),
-				AuthorityUtils.NO_AUTHORITIES, getBean(ClientRegistration.class).getRegistrationId());
-
-		ServerSecurityContextRepository repository = getBean(ServerSecurityContextRepository.class);
-		when(repository.load(any())).thenReturn(authentication(token));
-
-		this.client.post().uri("/logout").exchange().expectHeader().valueEquals("Location",
-				"https://logout?id_token_hint=id-token");
-	}
-
 	@EnableWebFlux
 	@EnableWebFluxSecurity
 	static class OAuth2LoginConfigWithOidcLogoutSuccessHandler {
@@ -707,17 +728,6 @@ public class OAuth2LoginTests {
 
 	}
 
-	// gh-8609
-	@Test
-	public void oauth2LoginWhenAuthenticationConverterFailsThenDefaultRedirectToLogin() {
-		this.spring.register(OAuth2LoginWithMultipleClientRegistrations.class).autowire();
-
-		WebTestClient webTestClient = WebTestClientBuilder.bindToWebFilters(this.springSecurity).build();
-
-		webTestClient.get().uri("/login/oauth2/code/google").exchange().expectStatus().is3xxRedirection().expectHeader()
-				.valueEquals("Location", "/login?error");
-	}
-
 	static class GitHubWebFilter implements WebFilter {
 
 		@Override
@@ -730,14 +740,4 @@ public class OAuth2LoginTests {
 
 	}
 
-	Mono authentication(Authentication authentication) {
-		SecurityContext context = new SecurityContextImpl();
-		context.setAuthentication(authentication);
-		return Mono.just(context);
-	}
-
-	 T getBean(Class beanClass) {
-		return this.spring.getContext().getBean(beanClass);
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/config/web/server/OAuth2ResourceServerSpecTests.java b/config/src/test/java/org/springframework/security/config/web/server/OAuth2ResourceServerSpecTests.java
index 8026f28f4d..5d4962a5fa 100644
--- a/config/src/test/java/org/springframework/security/config/web/server/OAuth2ResourceServerSpecTests.java
+++ b/config/src/test/java/org/springframework/security/config/web/server/OAuth2ResourceServerSpecTests.java
@@ -412,6 +412,54 @@ public class OAuth2ResourceServerSpecTests {
 				.isInstanceOf(BeanCreationException.class).hasMessageContaining("authenticationManagerResolver");
 	}
 
+	private static Dispatcher requiresAuth(String username, String password, String response) {
+		return new Dispatcher() {
+			@Override
+			public MockResponse dispatch(RecordedRequest request) {
+				String authorization = request.getHeader(org.springframework.http.HttpHeaders.AUTHORIZATION);
+				return Optional.ofNullable(authorization).filter(a -> isAuthorized(authorization, username, password))
+						.map(a -> ok(response)).orElse(unauthorized());
+			}
+		};
+	}
+
+	private static boolean isAuthorized(String authorization, String username, String password) {
+		String[] values = new String(Base64.getDecoder().decode(authorization.substring(6))).split(":");
+		return username.equals(values[0]) && password.equals(values[1]);
+	}
+
+	private static MockResponse ok(String response) {
+		return new MockResponse().setBody(response).setHeader(org.springframework.http.HttpHeaders.CONTENT_TYPE,
+				MediaType.APPLICATION_JSON_VALUE);
+	}
+
+	private static MockResponse unauthorized() {
+		return new MockResponse().setResponseCode(401);
+	}
+
+	private static RSAPublicKey publicKey() {
+		String modulus = "26323220897278656456354815752829448539647589990395639665273015355787577386000316054335559633864476469390247312823732994485311378484154955583861993455004584140858982659817218753831620205191028763754231454775026027780771426040997832758235764611119743390612035457533732596799927628476322029280486807310749948064176545712270582940917249337311592011920620009965129181413510845780806191965771671528886508636605814099711121026468495328702234901200169245493126030184941412539949521815665744267183140084667383643755535107759061065656273783542590997725982989978433493861515415520051342321336460543070448417126615154138673620797";
+		String exponent = "65537";
+
+		RSAPublicKeySpec spec = new RSAPublicKeySpec(new BigInteger(modulus), new BigInteger(exponent));
+		RSAPublicKey rsaPublicKey = null;
+		try {
+			KeyFactory factory = KeyFactory.getInstance("RSA");
+			rsaPublicKey = (RSAPublicKey) factory.generatePublic(spec);
+		}
+		catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
+			e.printStackTrace();
+		}
+		return rsaPublicKey;
+	}
+
+	private GenericWebApplicationContext autowireWebServerGenericWebApplicationContext() {
+		GenericWebApplicationContext context = new GenericWebApplicationContext();
+		context.registerBean("webHandler", DispatcherHandler.class);
+		this.spring.context(context).autowire();
+		return (GenericWebApplicationContext) this.spring.getContext();
+	}
+
 	@EnableWebFlux
 	@EnableWebFluxSecurity
 	static class PublicKeyConfig {
@@ -865,52 +913,4 @@ public class OAuth2ResourceServerSpecTests {
 
 	}
 
-	private static Dispatcher requiresAuth(String username, String password, String response) {
-		return new Dispatcher() {
-			@Override
-			public MockResponse dispatch(RecordedRequest request) {
-				String authorization = request.getHeader(org.springframework.http.HttpHeaders.AUTHORIZATION);
-				return Optional.ofNullable(authorization).filter(a -> isAuthorized(authorization, username, password))
-						.map(a -> ok(response)).orElse(unauthorized());
-			}
-		};
-	}
-
-	private static boolean isAuthorized(String authorization, String username, String password) {
-		String[] values = new String(Base64.getDecoder().decode(authorization.substring(6))).split(":");
-		return username.equals(values[0]) && password.equals(values[1]);
-	}
-
-	private static MockResponse ok(String response) {
-		return new MockResponse().setBody(response).setHeader(org.springframework.http.HttpHeaders.CONTENT_TYPE,
-				MediaType.APPLICATION_JSON_VALUE);
-	}
-
-	private static MockResponse unauthorized() {
-		return new MockResponse().setResponseCode(401);
-	}
-
-	private static RSAPublicKey publicKey() {
-		String modulus = "26323220897278656456354815752829448539647589990395639665273015355787577386000316054335559633864476469390247312823732994485311378484154955583861993455004584140858982659817218753831620205191028763754231454775026027780771426040997832758235764611119743390612035457533732596799927628476322029280486807310749948064176545712270582940917249337311592011920620009965129181413510845780806191965771671528886508636605814099711121026468495328702234901200169245493126030184941412539949521815665744267183140084667383643755535107759061065656273783542590997725982989978433493861515415520051342321336460543070448417126615154138673620797";
-		String exponent = "65537";
-
-		RSAPublicKeySpec spec = new RSAPublicKeySpec(new BigInteger(modulus), new BigInteger(exponent));
-		RSAPublicKey rsaPublicKey = null;
-		try {
-			KeyFactory factory = KeyFactory.getInstance("RSA");
-			rsaPublicKey = (RSAPublicKey) factory.generatePublic(spec);
-		}
-		catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
-			e.printStackTrace();
-		}
-		return rsaPublicKey;
-	}
-
-	private GenericWebApplicationContext autowireWebServerGenericWebApplicationContext() {
-		GenericWebApplicationContext context = new GenericWebApplicationContext();
-		context.registerBean("webHandler", DispatcherHandler.class);
-		this.spring.context(context).autowire();
-		return (GenericWebApplicationContext) this.spring.getContext();
-	}
-
 }
diff --git a/config/src/test/java/org/springframework/security/htmlunit/server/WebTestClientHtmlUnitDriverBuilderTests.java b/config/src/test/java/org/springframework/security/htmlunit/server/WebTestClientHtmlUnitDriverBuilderTests.java
index c1e4aa01d9..c1c02565db 100644
--- a/config/src/test/java/org/springframework/security/htmlunit/server/WebTestClientHtmlUnitDriverBuilderTests.java
+++ b/config/src/test/java/org/springframework/security/htmlunit/server/WebTestClientHtmlUnitDriverBuilderTests.java
@@ -52,22 +52,6 @@ public class WebTestClientHtmlUnitDriverBuilderTests {
 		assertThat(driver.getPageSource()).contains("Hello World");
 	}
 
-	/**
-	 * @author Rob Winch
-	 * @since 5.0
-	 */
-	@Controller
-	class HelloWorldController {
-
-		@ResponseBody
-		@GetMapping(produces = MediaType.TEXT_HTML_VALUE)
-		public String index() {
-			return "\n" + "\n" + "Hello World\n" + "\n" + "\n"
-					+ "

Hello World

\n" + "\n" + ""; - } - - } - @Test public void cookies() { WebTestClient webTestClient = WebTestClient.bindToController(new CookieController()).build(); @@ -82,6 +66,18 @@ public class WebTestClientHtmlUnitDriverBuilderTests { assertThat(driver.getPageSource()).contains("null"); } + @Controller + class HelloWorldController { + + @ResponseBody + @GetMapping(produces = MediaType.TEXT_HTML_VALUE) + public String index() { + return "\n" + "\n" + "Hello World\n" + "\n" + "\n" + + "

Hello World

\n" + "\n" + ""; + } + + } + @Controller @ResponseBody class CookieController { diff --git a/core/src/main/java/org/springframework/security/core/userdetails/User.java b/core/src/main/java/org/springframework/security/core/userdetails/User.java index 12bf83f72a..e3c8fe469e 100644 --- a/core/src/main/java/org/springframework/security/core/userdetails/User.java +++ b/core/src/main/java/org/springframework/security/core/userdetails/User.java @@ -175,29 +175,6 @@ public class User implements UserDetails, CredentialsContainer { return sortedAuthorities; } - private static class AuthorityComparator implements Comparator, Serializable { - - private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; - - @Override - public int compare(GrantedAuthority g1, GrantedAuthority g2) { - // Neither should ever be null as each entry is checked before adding it to - // the set. - // If the authority is null, it is a custom authority and should precede - // others. - if (g2.getAuthority() == null) { - return -1; - } - - if (g1.getAuthority() == null) { - return 1; - } - - return g1.getAuthority().compareTo(g2.getAuthority()); - } - - } - /** * Returns {@code true} if the supplied object is a {@code User} instance with the * same {@code username} value. @@ -339,6 +316,29 @@ public class User implements UserDetails, CredentialsContainer { .disabled(!userDetails.isEnabled()); } + private static class AuthorityComparator implements Comparator, Serializable { + + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + + @Override + public int compare(GrantedAuthority g1, GrantedAuthority g2) { + // Neither should ever be null as each entry is checked before adding it to + // the set. + // If the authority is null, it is a custom authority and should precede + // others. + if (g2.getAuthority() == null) { + return -1; + } + + if (g1.getAuthority() == null) { + return 1; + } + + return g1.getAuthority().compareTo(g2.getAuthority()); + } + + } + /** * Builds the user to be added. At minimum the username, password, and authorities * should provided. The remaining attributes have reasonable defaults. diff --git a/core/src/test/java/org/springframework/security/authentication/dao/DaoAuthenticationProviderTests.java b/core/src/test/java/org/springframework/security/authentication/dao/DaoAuthenticationProviderTests.java index 46fe362801..b3993f2f5d 100644 --- a/core/src/test/java/org/springframework/security/authentication/dao/DaoAuthenticationProviderTests.java +++ b/core/src/test/java/org/springframework/security/authentication/dao/DaoAuthenticationProviderTests.java @@ -683,6 +683,12 @@ public class DaoAuthenticationProviderTests { verify(encoder, times(0)).matches(anyString(), anyString()); } + private DaoAuthenticationProvider createProvider() { + DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); + provider.setPasswordEncoder(NoOpPasswordEncoder.getInstance()); + return provider; + } + private class MockUserDetailsServiceReturnsNull implements UserDetailsService { @Override @@ -767,10 +773,4 @@ public class DaoAuthenticationProviderTests { } - private DaoAuthenticationProvider createProvider() { - DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); - provider.setPasswordEncoder(NoOpPasswordEncoder.getInstance()); - return provider; - } - } diff --git a/etc/checkstyle/checkstyle-suppressions.xml b/etc/checkstyle/checkstyle-suppressions.xml index 839b07e350..07b0071dd4 100644 --- a/etc/checkstyle/checkstyle-suppressions.xml +++ b/etc/checkstyle/checkstyle-suppressions.xml @@ -3,7 +3,6 @@ "-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN" "https://checkstyle.org/dtds/suppressions_1_2.dtd"> - diff --git a/ldap/src/integration-test/java/org/springframework/security/ldap/server/UnboundIdContainerLdifTests.java b/ldap/src/integration-test/java/org/springframework/security/ldap/server/UnboundIdContainerLdifTests.java index a5fb47cd56..ef8c2b440f 100644 --- a/ldap/src/integration-test/java/org/springframework/security/ldap/server/UnboundIdContainerLdifTests.java +++ b/ldap/src/integration-test/java/org/springframework/security/ldap/server/UnboundIdContainerLdifTests.java @@ -58,6 +58,46 @@ public class UnboundIdContainerLdifTests { assertThat(template.compare("uid=bob,ou=people", "uid", "bob")).isTrue(); } + @Test + public void unboundIdContainerWhenWildcardLdifNameThenLdifLoaded() { + this.appCtx = new AnnotationConfigApplicationContext(WildcardLdifConfig.class); + + DefaultSpringSecurityContextSource contextSource = (DefaultSpringSecurityContextSource) this.appCtx + .getBean(ContextSource.class); + + SpringSecurityLdapTemplate template = new SpringSecurityLdapTemplate(contextSource); + assertThat(template.compare("uid=bob,ou=people", "uid", "bob")).isTrue(); + } + + @Test + public void unboundIdContainerWhenMalformedLdifThenException() { + try { + this.appCtx = new AnnotationConfigApplicationContext(MalformedLdifConfig.class); + failBecauseExceptionWasNotThrown(IllegalStateException.class); + } + catch (Exception e) { + assertThat(e.getCause()).isInstanceOf(IllegalStateException.class); + assertThat(e.getMessage()).contains("Unable to load LDIF classpath:test-server-malformed.txt"); + } + } + + @Test + public void unboundIdContainerWhenMissingLdifThenException() { + try { + this.appCtx = new AnnotationConfigApplicationContext(MissingLdifConfig.class); + failBecauseExceptionWasNotThrown(IllegalStateException.class); + } + catch (Exception e) { + assertThat(e.getCause()).isInstanceOf(IllegalStateException.class); + assertThat(e.getMessage()).contains("Unable to load LDIF classpath:does-not-exist.ldif"); + } + } + + @Test + public void unboundIdContainerWhenWildcardLdifNotFoundThenProceeds() { + new AnnotationConfigApplicationContext(WildcardNoLdifConfig.class); + } + @Configuration static class CustomLdifConfig { @@ -83,17 +123,6 @@ public class UnboundIdContainerLdifTests { } - @Test - public void unboundIdContainerWhenWildcardLdifNameThenLdifLoaded() { - this.appCtx = new AnnotationConfigApplicationContext(WildcardLdifConfig.class); - - DefaultSpringSecurityContextSource contextSource = (DefaultSpringSecurityContextSource) this.appCtx - .getBean(ContextSource.class); - - SpringSecurityLdapTemplate template = new SpringSecurityLdapTemplate(contextSource); - assertThat(template.compare("uid=bob,ou=people", "uid", "bob")).isTrue(); - } - @Configuration static class WildcardLdifConfig { @@ -119,18 +148,6 @@ public class UnboundIdContainerLdifTests { } - @Test - public void unboundIdContainerWhenMalformedLdifThenException() { - try { - this.appCtx = new AnnotationConfigApplicationContext(MalformedLdifConfig.class); - failBecauseExceptionWasNotThrown(IllegalStateException.class); - } - catch (Exception e) { - assertThat(e.getCause()).isInstanceOf(IllegalStateException.class); - assertThat(e.getMessage()).contains("Unable to load LDIF classpath:test-server-malformed.txt"); - } - } - @Configuration static class MalformedLdifConfig { @@ -150,18 +167,6 @@ public class UnboundIdContainerLdifTests { } - @Test - public void unboundIdContainerWhenMissingLdifThenException() { - try { - this.appCtx = new AnnotationConfigApplicationContext(MissingLdifConfig.class); - failBecauseExceptionWasNotThrown(IllegalStateException.class); - } - catch (Exception e) { - assertThat(e.getCause()).isInstanceOf(IllegalStateException.class); - assertThat(e.getMessage()).contains("Unable to load LDIF classpath:does-not-exist.ldif"); - } - } - @Configuration static class MissingLdifConfig { @@ -181,11 +186,6 @@ public class UnboundIdContainerLdifTests { } - @Test - public void unboundIdContainerWhenWildcardLdifNotFoundThenProceeds() { - new AnnotationConfigApplicationContext(WildcardNoLdifConfig.class); - } - @Configuration static class WildcardNoLdifConfig { diff --git a/messaging/src/test/java/org/springframework/security/messaging/context/AuthenticationPrincipalArgumentResolverTests.java b/messaging/src/test/java/org/springframework/security/messaging/context/AuthenticationPrincipalArgumentResolverTests.java index a483b5a870..4bcd5168ec 100644 --- a/messaging/src/test/java/org/springframework/security/messaging/context/AuthenticationPrincipalArgumentResolverTests.java +++ b/messaging/src/test/java/org/springframework/security/messaging/context/AuthenticationPrincipalArgumentResolverTests.java @@ -200,6 +200,12 @@ public class AuthenticationPrincipalArgumentResolverTests { return new MethodParameter(method, 0); } + private void setAuthenticationPrincipal(Object principal) { + this.expectedPrincipal = principal; + SecurityContextHolder.getContext() + .setAuthentication(new TestingAuthenticationToken(this.expectedPrincipal, "password", "ROLE_USER")); + } + @Target({ ElementType.PARAMETER }) @Retention(RetentionPolicy.RUNTIME) @AuthenticationPrincipal @@ -301,10 +307,4 @@ public class AuthenticationPrincipalArgumentResolverTests { } - private void setAuthenticationPrincipal(Object principal) { - this.expectedPrincipal = principal; - SecurityContextHolder.getContext() - .setAuthentication(new TestingAuthenticationToken(this.expectedPrincipal, "password", "ROLE_USER")); - } - } diff --git a/messaging/src/test/java/org/springframework/security/messaging/handler/invocation/ResolvableMethod.java b/messaging/src/test/java/org/springframework/security/messaging/handler/invocation/ResolvableMethod.java index 78e0e1fcbd..25e1e6af82 100644 --- a/messaging/src/test/java/org/springframework/security/messaging/handler/invocation/ResolvableMethod.java +++ b/messaging/src/test/java/org/springframework/security/messaging/handler/invocation/ResolvableMethod.java @@ -255,6 +255,52 @@ public final class ResolvableMethod { return new Builder<>(objectClass); } + @SuppressWarnings("unchecked") + private static T initProxy(Class type, MethodInvocationInterceptor interceptor) { + Assert.notNull(type, "'type' must not be null"); + if (type.isInterface()) { + ProxyFactory factory = new ProxyFactory(EmptyTargetSource.INSTANCE); + factory.addInterface(type); + factory.addInterface(Supplier.class); + factory.addAdvice(interceptor); + return (T) factory.getProxy(); + } + + else { + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(type); + enhancer.setInterfaces(new Class[] { Supplier.class }); + enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); + enhancer.setCallbackType(org.springframework.cglib.proxy.MethodInterceptor.class); + + Class proxyClass = enhancer.createClass(); + Object proxy = null; + + if (objenesis.isWorthTrying()) { + try { + proxy = objenesis.newInstance(proxyClass, enhancer.getUseCache()); + } + catch (ObjenesisException ex) { + logger.debug("Objenesis failed, falling back to default constructor", ex); + } + } + + if (proxy == null) { + try { + proxy = ReflectionUtils.accessibleConstructor(proxyClass).newInstance(); + } + catch (Throwable ex) { + throw new IllegalStateException( + "Unable to instantiate proxy " + "via both Objenesis and default constructor fails as well", + ex); + } + } + + ((Factory) proxy).setCallbacks(new Callback[] { interceptor }); + return (T) proxy; + } + } + /** * Builder for {@code ResolvableMethod}. */ @@ -629,50 +675,4 @@ public final class ResolvableMethod { } - @SuppressWarnings("unchecked") - private static T initProxy(Class type, MethodInvocationInterceptor interceptor) { - Assert.notNull(type, "'type' must not be null"); - if (type.isInterface()) { - ProxyFactory factory = new ProxyFactory(EmptyTargetSource.INSTANCE); - factory.addInterface(type); - factory.addInterface(Supplier.class); - factory.addAdvice(interceptor); - return (T) factory.getProxy(); - } - - else { - Enhancer enhancer = new Enhancer(); - enhancer.setSuperclass(type); - enhancer.setInterfaces(new Class[] { Supplier.class }); - enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); - enhancer.setCallbackType(org.springframework.cglib.proxy.MethodInterceptor.class); - - Class proxyClass = enhancer.createClass(); - Object proxy = null; - - if (objenesis.isWorthTrying()) { - try { - proxy = objenesis.newInstance(proxyClass, enhancer.getUseCache()); - } - catch (ObjenesisException ex) { - logger.debug("Objenesis failed, falling back to default constructor", ex); - } - } - - if (proxy == null) { - try { - proxy = ReflectionUtils.accessibleConstructor(proxyClass).newInstance(); - } - catch (Throwable ex) { - throw new IllegalStateException( - "Unable to instantiate proxy " + "via both Objenesis and default constructor fails as well", - ex); - } - } - - ((Factory) proxy).setCallbacks(new Callback[] { interceptor }); - return (T) proxy; - } - } - } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientProviderBuilder.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientProviderBuilder.java index 4a510258e8..a0541d8eb7 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientProviderBuilder.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/OAuth2AuthorizedClientProviderBuilder.java @@ -86,25 +86,6 @@ public final class OAuth2AuthorizedClientProviderBuilder { return OAuth2AuthorizedClientProviderBuilder.this; } - /** - * A builder for the {@code authorization_code} grant. - */ - public final class AuthorizationCodeGrantBuilder implements Builder { - - private AuthorizationCodeGrantBuilder() { - } - - /** - * Builds an instance of {@link AuthorizationCodeOAuth2AuthorizedClientProvider}. - * @return the {@link AuthorizationCodeOAuth2AuthorizedClientProvider} - */ - @Override - public OAuth2AuthorizedClientProvider build() { - return new AuthorizationCodeOAuth2AuthorizedClientProvider(); - } - - } - /** * Configures support for the {@code refresh_token} grant. * @return the {@link OAuth2AuthorizedClientProviderBuilder} @@ -128,77 +109,6 @@ public final class OAuth2AuthorizedClientProviderBuilder { return OAuth2AuthorizedClientProviderBuilder.this; } - /** - * A builder for the {@code refresh_token} grant. - */ - public final class RefreshTokenGrantBuilder implements Builder { - - private OAuth2AccessTokenResponseClient accessTokenResponseClient; - - private Duration clockSkew; - - private Clock clock; - - private RefreshTokenGrantBuilder() { - } - - /** - * Sets the client used when requesting an access token credential at the Token - * Endpoint. - * @param accessTokenResponseClient the client used when requesting an access - * token credential at the Token Endpoint - * @return the {@link RefreshTokenGrantBuilder} - */ - public RefreshTokenGrantBuilder accessTokenResponseClient( - OAuth2AccessTokenResponseClient accessTokenResponseClient) { - this.accessTokenResponseClient = accessTokenResponseClient; - return this; - } - - /** - * Sets the maximum acceptable clock skew, which is used when checking the access - * token expiry. An access token is considered expired if it's before - * {@code Instant.now(this.clock) - clockSkew}. - * @param clockSkew the maximum acceptable clock skew - * @return the {@link RefreshTokenGrantBuilder} - */ - public RefreshTokenGrantBuilder clockSkew(Duration clockSkew) { - this.clockSkew = clockSkew; - return this; - } - - /** - * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the - * access token expiry. - * @param clock the clock - * @return the {@link RefreshTokenGrantBuilder} - */ - public RefreshTokenGrantBuilder clock(Clock clock) { - this.clock = clock; - return this; - } - - /** - * Builds an instance of {@link RefreshTokenOAuth2AuthorizedClientProvider}. - * @return the {@link RefreshTokenOAuth2AuthorizedClientProvider} - */ - @Override - public OAuth2AuthorizedClientProvider build() { - RefreshTokenOAuth2AuthorizedClientProvider authorizedClientProvider = new RefreshTokenOAuth2AuthorizedClientProvider(); - if (this.accessTokenResponseClient != null) { - authorizedClientProvider.setAccessTokenResponseClient(this.accessTokenResponseClient); - } - if (this.clockSkew != null) { - authorizedClientProvider.setClockSkew(this.clockSkew); - } - if (this.clock != null) { - authorizedClientProvider.setClock(this.clock); - } - return authorizedClientProvider; - } - - } - /** * Configures support for the {@code client_credentials} grant. * @return the {@link OAuth2AuthorizedClientProviderBuilder} @@ -223,77 +133,6 @@ public final class OAuth2AuthorizedClientProviderBuilder { return OAuth2AuthorizedClientProviderBuilder.this; } - /** - * A builder for the {@code client_credentials} grant. - */ - public final class ClientCredentialsGrantBuilder implements Builder { - - private OAuth2AccessTokenResponseClient accessTokenResponseClient; - - private Duration clockSkew; - - private Clock clock; - - private ClientCredentialsGrantBuilder() { - } - - /** - * Sets the client used when requesting an access token credential at the Token - * Endpoint. - * @param accessTokenResponseClient the client used when requesting an access - * token credential at the Token Endpoint - * @return the {@link ClientCredentialsGrantBuilder} - */ - public ClientCredentialsGrantBuilder accessTokenResponseClient( - OAuth2AccessTokenResponseClient accessTokenResponseClient) { - this.accessTokenResponseClient = accessTokenResponseClient; - return this; - } - - /** - * Sets the maximum acceptable clock skew, which is used when checking the access - * token expiry. An access token is considered expired if it's before - * {@code Instant.now(this.clock) - clockSkew}. - * @param clockSkew the maximum acceptable clock skew - * @return the {@link ClientCredentialsGrantBuilder} - */ - public ClientCredentialsGrantBuilder clockSkew(Duration clockSkew) { - this.clockSkew = clockSkew; - return this; - } - - /** - * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the - * access token expiry. - * @param clock the clock - * @return the {@link ClientCredentialsGrantBuilder} - */ - public ClientCredentialsGrantBuilder clock(Clock clock) { - this.clock = clock; - return this; - } - - /** - * Builds an instance of {@link ClientCredentialsOAuth2AuthorizedClientProvider}. - * @return the {@link ClientCredentialsOAuth2AuthorizedClientProvider} - */ - @Override - public OAuth2AuthorizedClientProvider build() { - ClientCredentialsOAuth2AuthorizedClientProvider authorizedClientProvider = new ClientCredentialsOAuth2AuthorizedClientProvider(); - if (this.accessTokenResponseClient != null) { - authorizedClientProvider.setAccessTokenResponseClient(this.accessTokenResponseClient); - } - if (this.clockSkew != null) { - authorizedClientProvider.setClockSkew(this.clockSkew); - } - if (this.clock != null) { - authorizedClientProvider.setClock(this.clock); - } - return authorizedClientProvider; - } - - } - /** * Configures support for the {@code password} grant. * @return the {@link OAuth2AuthorizedClientProviderBuilder} @@ -316,6 +155,25 @@ public final class OAuth2AuthorizedClientProviderBuilder { return OAuth2AuthorizedClientProviderBuilder.this; } + /** + * Builds an instance of {@link DelegatingOAuth2AuthorizedClientProvider} composed of + * one or more {@link OAuth2AuthorizedClientProvider}(s). + * @return the {@link DelegatingOAuth2AuthorizedClientProvider} + */ + public OAuth2AuthorizedClientProvider build() { + List authorizedClientProviders = new ArrayList<>(); + for (Builder builder : this.builders.values()) { + authorizedClientProviders.add(builder.build()); + } + return new DelegatingOAuth2AuthorizedClientProvider(authorizedClientProviders); + } + + interface Builder { + + OAuth2AuthorizedClientProvider build(); + + } + /** * A builder for the {@code password} grant. */ @@ -388,21 +246,163 @@ public final class OAuth2AuthorizedClientProviderBuilder { } /** - * Builds an instance of {@link DelegatingOAuth2AuthorizedClientProvider} composed of - * one or more {@link OAuth2AuthorizedClientProvider}(s). - * @return the {@link DelegatingOAuth2AuthorizedClientProvider} + * A builder for the {@code client_credentials} grant. */ - public OAuth2AuthorizedClientProvider build() { - List authorizedClientProviders = new ArrayList<>(); - for (Builder builder : this.builders.values()) { - authorizedClientProviders.add(builder.build()); + public final class ClientCredentialsGrantBuilder implements Builder { + + private OAuth2AccessTokenResponseClient accessTokenResponseClient; + + private Duration clockSkew; + + private Clock clock; + + private ClientCredentialsGrantBuilder() { } - return new DelegatingOAuth2AuthorizedClientProvider(authorizedClientProviders); + + /** + * Sets the client used when requesting an access token credential at the Token + * Endpoint. + * @param accessTokenResponseClient the client used when requesting an access + * token credential at the Token Endpoint + * @return the {@link ClientCredentialsGrantBuilder} + */ + public ClientCredentialsGrantBuilder accessTokenResponseClient( + OAuth2AccessTokenResponseClient accessTokenResponseClient) { + this.accessTokenResponseClient = accessTokenResponseClient; + return this; + } + + /** + * Sets the maximum acceptable clock skew, which is used when checking the access + * token expiry. An access token is considered expired if it's before + * {@code Instant.now(this.clock) - clockSkew}. + * @param clockSkew the maximum acceptable clock skew + * @return the {@link ClientCredentialsGrantBuilder} + */ + public ClientCredentialsGrantBuilder clockSkew(Duration clockSkew) { + this.clockSkew = clockSkew; + return this; + } + + /** + * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the + * access token expiry. + * @param clock the clock + * @return the {@link ClientCredentialsGrantBuilder} + */ + public ClientCredentialsGrantBuilder clock(Clock clock) { + this.clock = clock; + return this; + } + + /** + * Builds an instance of {@link ClientCredentialsOAuth2AuthorizedClientProvider}. + * @return the {@link ClientCredentialsOAuth2AuthorizedClientProvider} + */ + @Override + public OAuth2AuthorizedClientProvider build() { + ClientCredentialsOAuth2AuthorizedClientProvider authorizedClientProvider = new ClientCredentialsOAuth2AuthorizedClientProvider(); + if (this.accessTokenResponseClient != null) { + authorizedClientProvider.setAccessTokenResponseClient(this.accessTokenResponseClient); + } + if (this.clockSkew != null) { + authorizedClientProvider.setClockSkew(this.clockSkew); + } + if (this.clock != null) { + authorizedClientProvider.setClock(this.clock); + } + return authorizedClientProvider; + } + } - interface Builder { + /** + * A builder for the {@code authorization_code} grant. + */ + public final class AuthorizationCodeGrantBuilder implements Builder { - OAuth2AuthorizedClientProvider build(); + private AuthorizationCodeGrantBuilder() { + } + + /** + * Builds an instance of {@link AuthorizationCodeOAuth2AuthorizedClientProvider}. + * @return the {@link AuthorizationCodeOAuth2AuthorizedClientProvider} + */ + @Override + public OAuth2AuthorizedClientProvider build() { + return new AuthorizationCodeOAuth2AuthorizedClientProvider(); + } + + } + + /** + * A builder for the {@code refresh_token} grant. + */ + public final class RefreshTokenGrantBuilder implements Builder { + + private OAuth2AccessTokenResponseClient accessTokenResponseClient; + + private Duration clockSkew; + + private Clock clock; + + private RefreshTokenGrantBuilder() { + } + + /** + * Sets the client used when requesting an access token credential at the Token + * Endpoint. + * @param accessTokenResponseClient the client used when requesting an access + * token credential at the Token Endpoint + * @return the {@link RefreshTokenGrantBuilder} + */ + public RefreshTokenGrantBuilder accessTokenResponseClient( + OAuth2AccessTokenResponseClient accessTokenResponseClient) { + this.accessTokenResponseClient = accessTokenResponseClient; + return this; + } + + /** + * Sets the maximum acceptable clock skew, which is used when checking the access + * token expiry. An access token is considered expired if it's before + * {@code Instant.now(this.clock) - clockSkew}. + * @param clockSkew the maximum acceptable clock skew + * @return the {@link RefreshTokenGrantBuilder} + */ + public RefreshTokenGrantBuilder clockSkew(Duration clockSkew) { + this.clockSkew = clockSkew; + return this; + } + + /** + * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the + * access token expiry. + * @param clock the clock + * @return the {@link RefreshTokenGrantBuilder} + */ + public RefreshTokenGrantBuilder clock(Clock clock) { + this.clock = clock; + return this; + } + + /** + * Builds an instance of {@link RefreshTokenOAuth2AuthorizedClientProvider}. + * @return the {@link RefreshTokenOAuth2AuthorizedClientProvider} + */ + @Override + public OAuth2AuthorizedClientProvider build() { + RefreshTokenOAuth2AuthorizedClientProvider authorizedClientProvider = new RefreshTokenOAuth2AuthorizedClientProvider(); + if (this.accessTokenResponseClient != null) { + authorizedClientProvider.setAccessTokenResponseClient(this.accessTokenResponseClient); + } + if (this.clockSkew != null) { + authorizedClientProvider.setClockSkew(this.clockSkew); + } + if (this.clock != null) { + authorizedClientProvider.setClock(this.clock); + } + return authorizedClientProvider; + } } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientProviderBuilder.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientProviderBuilder.java index 2e6eb85eb4..c817be8527 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientProviderBuilder.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/ReactiveOAuth2AuthorizedClientProviderBuilder.java @@ -86,26 +86,6 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder { return ReactiveOAuth2AuthorizedClientProviderBuilder.this; } - /** - * A builder for the {@code authorization_code} grant. - */ - public final class AuthorizationCodeGrantBuilder implements Builder { - - private AuthorizationCodeGrantBuilder() { - } - - /** - * Builds an instance of - * {@link AuthorizationCodeReactiveOAuth2AuthorizedClientProvider}. - * @return the {@link AuthorizationCodeReactiveOAuth2AuthorizedClientProvider} - */ - @Override - public ReactiveOAuth2AuthorizedClientProvider build() { - return new AuthorizationCodeReactiveOAuth2AuthorizedClientProvider(); - } - - } - /** * Configures support for the {@code refresh_token} grant. * @return the {@link ReactiveOAuth2AuthorizedClientProviderBuilder} @@ -130,78 +110,6 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder { return ReactiveOAuth2AuthorizedClientProviderBuilder.this; } - /** - * A builder for the {@code refresh_token} grant. - */ - public final class RefreshTokenGrantBuilder implements Builder { - - private ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient; - - private Duration clockSkew; - - private Clock clock; - - private RefreshTokenGrantBuilder() { - } - - /** - * Sets the client used when requesting an access token credential at the Token - * Endpoint. - * @param accessTokenResponseClient the client used when requesting an access - * token credential at the Token Endpoint - * @return the {@link RefreshTokenGrantBuilder} - */ - public RefreshTokenGrantBuilder accessTokenResponseClient( - ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient) { - this.accessTokenResponseClient = accessTokenResponseClient; - return this; - } - - /** - * Sets the maximum acceptable clock skew, which is used when checking the access - * token expiry. An access token is considered expired if it's before - * {@code Instant.now(this.clock) - clockSkew}. - * @param clockSkew the maximum acceptable clock skew - * @return the {@link RefreshTokenGrantBuilder} - */ - public RefreshTokenGrantBuilder clockSkew(Duration clockSkew) { - this.clockSkew = clockSkew; - return this; - } - - /** - * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the - * access token expiry. - * @param clock the clock - * @return the {@link RefreshTokenGrantBuilder} - */ - public RefreshTokenGrantBuilder clock(Clock clock) { - this.clock = clock; - return this; - } - - /** - * Builds an instance of - * {@link RefreshTokenReactiveOAuth2AuthorizedClientProvider}. - * @return the {@link RefreshTokenReactiveOAuth2AuthorizedClientProvider} - */ - @Override - public ReactiveOAuth2AuthorizedClientProvider build() { - RefreshTokenReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = new RefreshTokenReactiveOAuth2AuthorizedClientProvider(); - if (this.accessTokenResponseClient != null) { - authorizedClientProvider.setAccessTokenResponseClient(this.accessTokenResponseClient); - } - if (this.clockSkew != null) { - authorizedClientProvider.setClockSkew(this.clockSkew); - } - if (this.clock != null) { - authorizedClientProvider.setClock(this.clock); - } - return authorizedClientProvider; - } - - } - /** * Configures support for the {@code client_credentials} grant. * @return the {@link ReactiveOAuth2AuthorizedClientProviderBuilder} @@ -227,6 +135,66 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder { return ReactiveOAuth2AuthorizedClientProviderBuilder.this; } + /** + * Configures support for the {@code password} grant. + * @return the {@link ReactiveOAuth2AuthorizedClientProviderBuilder} + */ + public ReactiveOAuth2AuthorizedClientProviderBuilder password() { + this.builders.computeIfAbsent(PasswordReactiveOAuth2AuthorizedClientProvider.class, + k -> new PasswordGrantBuilder()); + return ReactiveOAuth2AuthorizedClientProviderBuilder.this; + } + + /** + * Configures support for the {@code password} grant. + * @param builderConsumer a {@code Consumer} of {@link PasswordGrantBuilder} used for + * further configuration + * @return the {@link ReactiveOAuth2AuthorizedClientProviderBuilder} + */ + public ReactiveOAuth2AuthorizedClientProviderBuilder password(Consumer builderConsumer) { + PasswordGrantBuilder builder = (PasswordGrantBuilder) this.builders + .computeIfAbsent(PasswordReactiveOAuth2AuthorizedClientProvider.class, k -> new PasswordGrantBuilder()); + builderConsumer.accept(builder); + return ReactiveOAuth2AuthorizedClientProviderBuilder.this; + } + + /** + * Builds an instance of {@link DelegatingReactiveOAuth2AuthorizedClientProvider} + * composed of one or more {@link ReactiveOAuth2AuthorizedClientProvider}(s). + * @return the {@link DelegatingReactiveOAuth2AuthorizedClientProvider} + */ + public ReactiveOAuth2AuthorizedClientProvider build() { + List authorizedClientProviders = this.builders.values().stream() + .map(Builder::build).collect(Collectors.toList()); + return new DelegatingReactiveOAuth2AuthorizedClientProvider(authorizedClientProviders); + } + + interface Builder { + + ReactiveOAuth2AuthorizedClientProvider build(); + + } + + /** + * A builder for the {@code authorization_code} grant. + */ + public final class AuthorizationCodeGrantBuilder implements Builder { + + private AuthorizationCodeGrantBuilder() { + } + + /** + * Builds an instance of + * {@link AuthorizationCodeReactiveOAuth2AuthorizedClientProvider}. + * @return the {@link AuthorizationCodeReactiveOAuth2AuthorizedClientProvider} + */ + @Override + public ReactiveOAuth2AuthorizedClientProvider build() { + return new AuthorizationCodeReactiveOAuth2AuthorizedClientProvider(); + } + + } + /** * A builder for the {@code client_credentials} grant. */ @@ -299,29 +267,6 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder { } - /** - * Configures support for the {@code password} grant. - * @return the {@link ReactiveOAuth2AuthorizedClientProviderBuilder} - */ - public ReactiveOAuth2AuthorizedClientProviderBuilder password() { - this.builders.computeIfAbsent(PasswordReactiveOAuth2AuthorizedClientProvider.class, - k -> new PasswordGrantBuilder()); - return ReactiveOAuth2AuthorizedClientProviderBuilder.this; - } - - /** - * Configures support for the {@code password} grant. - * @param builderConsumer a {@code Consumer} of {@link PasswordGrantBuilder} used for - * further configuration - * @return the {@link ReactiveOAuth2AuthorizedClientProviderBuilder} - */ - public ReactiveOAuth2AuthorizedClientProviderBuilder password(Consumer builderConsumer) { - PasswordGrantBuilder builder = (PasswordGrantBuilder) this.builders - .computeIfAbsent(PasswordReactiveOAuth2AuthorizedClientProvider.class, k -> new PasswordGrantBuilder()); - builderConsumer.accept(builder); - return ReactiveOAuth2AuthorizedClientProviderBuilder.this; - } - /** * A builder for the {@code password} grant. */ @@ -394,19 +339,74 @@ public final class ReactiveOAuth2AuthorizedClientProviderBuilder { } /** - * Builds an instance of {@link DelegatingReactiveOAuth2AuthorizedClientProvider} - * composed of one or more {@link ReactiveOAuth2AuthorizedClientProvider}(s). - * @return the {@link DelegatingReactiveOAuth2AuthorizedClientProvider} + * A builder for the {@code refresh_token} grant. */ - public ReactiveOAuth2AuthorizedClientProvider build() { - List authorizedClientProviders = this.builders.values().stream() - .map(Builder::build).collect(Collectors.toList()); - return new DelegatingReactiveOAuth2AuthorizedClientProvider(authorizedClientProviders); - } + public final class RefreshTokenGrantBuilder implements Builder { - interface Builder { + private ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient; - ReactiveOAuth2AuthorizedClientProvider build(); + private Duration clockSkew; + + private Clock clock; + + private RefreshTokenGrantBuilder() { + } + + /** + * Sets the client used when requesting an access token credential at the Token + * Endpoint. + * @param accessTokenResponseClient the client used when requesting an access + * token credential at the Token Endpoint + * @return the {@link RefreshTokenGrantBuilder} + */ + public RefreshTokenGrantBuilder accessTokenResponseClient( + ReactiveOAuth2AccessTokenResponseClient accessTokenResponseClient) { + this.accessTokenResponseClient = accessTokenResponseClient; + return this; + } + + /** + * Sets the maximum acceptable clock skew, which is used when checking the access + * token expiry. An access token is considered expired if it's before + * {@code Instant.now(this.clock) - clockSkew}. + * @param clockSkew the maximum acceptable clock skew + * @return the {@link RefreshTokenGrantBuilder} + */ + public RefreshTokenGrantBuilder clockSkew(Duration clockSkew) { + this.clockSkew = clockSkew; + return this; + } + + /** + * Sets the {@link Clock} used in {@link Instant#now(Clock)} when checking the + * access token expiry. + * @param clock the clock + * @return the {@link RefreshTokenGrantBuilder} + */ + public RefreshTokenGrantBuilder clock(Clock clock) { + this.clock = clock; + return this; + } + + /** + * Builds an instance of + * {@link RefreshTokenReactiveOAuth2AuthorizedClientProvider}. + * @return the {@link RefreshTokenReactiveOAuth2AuthorizedClientProvider} + */ + @Override + public ReactiveOAuth2AuthorizedClientProvider build() { + RefreshTokenReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = new RefreshTokenReactiveOAuth2AuthorizedClientProvider(); + if (this.accessTokenResponseClient != null) { + authorizedClientProvider.setAccessTokenResponseClient(this.accessTokenResponseClient); + } + if (this.clockSkew != null) { + authorizedClientProvider.setClockSkew(this.clockSkew); + } + if (this.clock != null) { + authorizedClientProvider.setClock(this.clock); + } + return authorizedClientProvider; + } } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RemoveAuthorizedClientOAuth2AuthorizationFailureHandler.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RemoveAuthorizedClientOAuth2AuthorizationFailureHandler.java index 51df5fb0c7..79a4007f70 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RemoveAuthorizedClientOAuth2AuthorizationFailureHandler.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RemoveAuthorizedClientOAuth2AuthorizationFailureHandler.java @@ -81,29 +81,6 @@ public class RemoveAuthorizedClientOAuth2AuthorizationFailureHandler implements */ private final OAuth2AuthorizedClientRemover delegate; - /** - * Removes an {@link OAuth2AuthorizedClient} from an - * {@link OAuth2AuthorizedClientRepository} or {@link OAuth2AuthorizedClientService}. - */ - @FunctionalInterface - public interface OAuth2AuthorizedClientRemover { - - /** - * Removes the {@link OAuth2AuthorizedClient} associated to the provided client - * registration identifier and End-User {@link Authentication} (Resource Owner). - * @param clientRegistrationId the identifier for the client's registration - * @param principal the End-User {@link Authentication} (Resource Owner) - * @param attributes an immutable {@code Map} of (optional) attributes present - * under certain conditions. For example, this might contain a - * {@code javax.servlet.http.HttpServletRequest} and - * {@code javax.servlet.http.HttpServletResponse} if the authorization was - * performed within the context of a {@code javax.servlet.ServletContext}. - */ - void removeAuthorizedClient(String clientRegistrationId, Authentication principal, - Map attributes); - - } - /** * Constructs a {@code RemoveAuthorizedClientOAuth2AuthorizationFailureHandler} using * the provided parameters. @@ -159,4 +136,27 @@ public class RemoveAuthorizedClientOAuth2AuthorizationFailureHandler implements return this.removeAuthorizedClientErrorCodes.contains(authorizationException.getError().getErrorCode()); } + /** + * Removes an {@link OAuth2AuthorizedClient} from an + * {@link OAuth2AuthorizedClientRepository} or {@link OAuth2AuthorizedClientService}. + */ + @FunctionalInterface + public interface OAuth2AuthorizedClientRemover { + + /** + * Removes the {@link OAuth2AuthorizedClient} associated to the provided client + * registration identifier and End-User {@link Authentication} (Resource Owner). + * @param clientRegistrationId the identifier for the client's registration + * @param principal the End-User {@link Authentication} (Resource Owner) + * @param attributes an immutable {@code Map} of (optional) attributes present + * under certain conditions. For example, this might contain a + * {@code javax.servlet.http.HttpServletRequest} and + * {@code javax.servlet.http.HttpServletResponse} if the authorization was + * performed within the context of a {@code javax.servlet.ServletContext}. + */ + void removeAuthorizedClient(String clientRegistrationId, Authentication principal, + Map attributes); + + } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler.java index 179ce268ec..0e52150bdb 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler.java @@ -79,32 +79,6 @@ public class RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler */ private final Set removeAuthorizedClientErrorCodes; - /** - * Removes an {@link OAuth2AuthorizedClient} from a - * {@link ServerOAuth2AuthorizedClientRepository} or - * {@link ReactiveOAuth2AuthorizedClientService}. - */ - @FunctionalInterface - public interface OAuth2AuthorizedClientRemover { - - /** - * Removes the {@link OAuth2AuthorizedClient} associated to the provided client - * registration identifier and End-User {@link Authentication} (Resource Owner). - * @param clientRegistrationId the identifier for the client's registration - * @param principal the End-User {@link Authentication} (Resource Owner) - * @param attributes an immutable {@code Map} of extra optional attributes present - * under certain conditions. For example, this might contain a - * {@link org.springframework.web.server.ServerWebExchange ServerWebExchange} if - * the authorization was performed within the context of a - * {@code ServerWebExchange}. - * @return an empty {@link Mono} that completes after this handler has finished - * handling the event. - */ - Mono removeAuthorizedClient(String clientRegistrationId, Authentication principal, - Map attributes); - - } - /** * Constructs a * {@code RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler} using the @@ -165,4 +139,30 @@ public class RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler return this.removeAuthorizedClientErrorCodes.contains(authorizationException.getError().getErrorCode()); } + /** + * Removes an {@link OAuth2AuthorizedClient} from a + * {@link ServerOAuth2AuthorizedClientRepository} or + * {@link ReactiveOAuth2AuthorizedClientService}. + */ + @FunctionalInterface + public interface OAuth2AuthorizedClientRemover { + + /** + * Removes the {@link OAuth2AuthorizedClient} associated to the provided client + * registration identifier and End-User {@link Authentication} (Resource Owner). + * @param clientRegistrationId the identifier for the client's registration + * @param principal the End-User {@link Authentication} (Resource Owner) + * @param attributes an immutable {@code Map} of extra optional attributes present + * under certain conditions. For example, this might contain a + * {@link org.springframework.web.server.ServerWebExchange ServerWebExchange} if + * the authorization was performed within the context of a + * {@code ServerWebExchange}. + * @return an empty {@link Mono} that completes after this handler has finished + * handling the event. + */ + Mono removeAuthorizedClient(String clientRegistrationId, Authentication principal, + Map attributes); + + } + } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistration.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistration.java index b4ecb5748d..12050c253a 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistration.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistration.java @@ -176,6 +176,28 @@ public final class ClientRegistration implements Serializable { + this.providerDetails + ", clientName='" + this.clientName + '\'' + '}'; } + /** + * Returns a new {@link Builder}, initialized with the provided registration + * identifier. + * @param registrationId the identifier for the registration + * @return the {@link Builder} + */ + public static Builder withRegistrationId(String registrationId) { + Assert.hasText(registrationId, "registrationId cannot be empty"); + return new Builder(registrationId); + } + + /** + * Returns a new {@link Builder}, initialized with the provided + * {@link ClientRegistration}. + * @param clientRegistration the {@link ClientRegistration} to copy from + * @return the {@link Builder} + */ + public static Builder withClientRegistration(ClientRegistration clientRegistration) { + Assert.notNull(clientRegistration, "clientRegistration cannot be null"); + return new Builder(clientRegistration); + } + /** * Details of the Provider. */ @@ -297,28 +319,6 @@ public final class ClientRegistration implements Serializable { } - /** - * Returns a new {@link Builder}, initialized with the provided registration - * identifier. - * @param registrationId the identifier for the registration - * @return the {@link Builder} - */ - public static Builder withRegistrationId(String registrationId) { - Assert.hasText(registrationId, "registrationId cannot be empty"); - return new Builder(registrationId); - } - - /** - * Returns a new {@link Builder}, initialized with the provided - * {@link ClientRegistration}. - * @param clientRegistration the {@link ClientRegistration} to copy from - * @return the {@link Builder} - */ - public static Builder withClientRegistration(ClientRegistration clientRegistration) { - Assert.notNull(clientRegistration, "clientRegistration cannot be null"); - return new Builder(clientRegistration); - } - /** * A builder for {@link ClientRegistration}. */ diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistrations.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistrations.java index aa68f450c1..e244de0e8d 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistrations.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistrations.java @@ -64,6 +64,9 @@ public final class ClientRegistrations { private static final ParameterizedTypeReference> typeReference = new ParameterizedTypeReference>() { }; + private ClientRegistrations() { + } + /** * Creates a {@link ClientRegistration.Builder} using the provided Issuer @@ -227,12 +230,6 @@ public final class ClientRegistrations { } } - private interface ThrowingFunction { - - T apply(S src) throws E; - - } - private static ClientRegistration.Builder withProviderConfiguration(AuthorizationServerMetadata metadata, String issuer) { String metadataIssuer = metadata.getIssuer().getValue(); @@ -292,7 +289,10 @@ public final class ClientRegistrations { } } - private ClientRegistrations() { + private interface ThrowingFunction { + + T apply(S src) throws E; + } } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServerOAuth2AuthorizedClientExchangeFilterFunction.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServerOAuth2AuthorizedClientExchangeFilterFunction.java index 9ea3263d5b..d8b0dfea79 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServerOAuth2AuthorizedClientExchangeFilterFunction.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServerOAuth2AuthorizedClientExchangeFilterFunction.java @@ -154,13 +154,6 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements private ClientResponseHandler clientResponseHandler; - @FunctionalInterface - private interface ClientResponseHandler { - - Mono handleResponse(ClientRequest request, Mono response); - - } - /** * Constructs a {@code ServerOAuth2AuthorizedClientExchangeFilterFunction} using the * provided parameters. @@ -534,6 +527,13 @@ public final class ServerOAuth2AuthorizedClientExchangeFilterFunction implements this.clientResponseHandler = new AuthorizationFailureForwarder(authorizationFailureHandler); } + @FunctionalInterface + private interface ClientResponseHandler { + + Mono handleResponse(ClientRequest request, Mono response); + + } + private static final class UnAuthenticatedReactiveOAuth2AuthorizedClientManager implements ReactiveOAuth2AuthorizedClientManager { diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServletOAuth2AuthorizedClientExchangeFilterFunction.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServletOAuth2AuthorizedClientExchangeFilterFunction.java index 6600151027..311e403766 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServletOAuth2AuthorizedClientExchangeFilterFunction.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/reactive/function/client/ServletOAuth2AuthorizedClientExchangeFilterFunction.java @@ -166,13 +166,6 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement private ClientResponseHandler clientResponseHandler; - @FunctionalInterface - private interface ClientResponseHandler { - - Mono handleResponse(ClientRequest request, Mono response); - - } - public ServletOAuth2AuthorizedClientExchangeFilterFunction() { } @@ -631,6 +624,13 @@ public final class ServletOAuth2AuthorizedClientExchangeFilterFunction implement }; } + @FunctionalInterface + private interface ClientResponseHandler { + + Mono handleResponse(ClientRequest request, Mono response); + + } + /** * Forwards authentication and authorization failures to an * {@link OAuth2AuthorizationFailureHandler}. diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusReactiveJwtDecoder.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusReactiveJwtDecoder.java index 53a119cdb0..4fa7bac01a 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusReactiveJwtDecoder.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusReactiveJwtDecoder.java @@ -245,6 +245,19 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { return new JwkSourceReactiveJwtDecoderBuilder(source); } + private static JWTClaimsSet createClaimsSet(JWTProcessor jwtProcessor, + JWT parsedToken, C context) { + try { + return jwtProcessor.process(parsedToken, context); + } + catch (BadJOSEException e) { + throw new BadJwtException("Failed to validate the token", e); + } + catch (JOSEException e) { + throw new JwtException("Failed to validate the token", e); + } + } + /** * A builder for creating {@link NimbusReactiveJwtDecoder} instances based on a * JWK Set @@ -626,17 +639,4 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder { } - private static JWTClaimsSet createClaimsSet(JWTProcessor jwtProcessor, - JWT parsedToken, C context) { - try { - return jwtProcessor.process(parsedToken, context); - } - catch (BadJOSEException e) { - throw new BadJwtException("Failed to validate the token", e); - } - catch (JOSEException e) { - throw new JwtException("Failed to validate the token", e); - } - } - } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProvider.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProvider.java index cf749a5361..842f58df26 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProvider.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProvider.java @@ -562,6 +562,22 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi return xsAny.getTextContent(); } + private static Saml2Error validationError(String code, String description) { + return new Saml2Error(code, description); + } + + private static Saml2AuthenticationException authException(String code, String description) + throws Saml2AuthenticationException { + + return new Saml2AuthenticationException(validationError(code, description)); + } + + private static Saml2AuthenticationException authException(String code, String description, Exception cause) + throws Saml2AuthenticationException { + + return new Saml2AuthenticationException(validationError(code, description), cause); + } + private static class SignatureTrustEngineConverter implements Converter { @@ -651,22 +667,6 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi } - private static Saml2Error validationError(String code, String description) { - return new Saml2Error(code, description); - } - - private static Saml2AuthenticationException authException(String code, String description) - throws Saml2AuthenticationException { - - return new Saml2AuthenticationException(validationError(code, description)); - } - - private static Saml2AuthenticationException authException(String code, String description, Exception cause) - throws Saml2AuthenticationException { - - return new Saml2AuthenticationException(validationError(code, description), cause); - } - /** * A tuple containing the authentication token and the associated OpenSAML * {@link Response}. diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistration.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistration.java index 7a5db9ed5d..db1f7d2d57 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistration.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistration.java @@ -377,6 +377,51 @@ public final class RelyingPartyRegistration { registration.getAssertingPartyDetails().getSingleSignOnServiceBinding())); } + private static Saml2X509Credential fromDeprecated( + org.springframework.security.saml2.credentials.Saml2X509Credential credential) { + PrivateKey privateKey = credential.getPrivateKey(); + X509Certificate certificate = credential.getCertificate(); + Set credentialTypes = new HashSet<>(); + if (credential.isSigningCredential()) { + credentialTypes.add(Saml2X509Credential.Saml2X509CredentialType.SIGNING); + } + if (credential.isSignatureVerficationCredential()) { + credentialTypes.add(Saml2X509Credential.Saml2X509CredentialType.VERIFICATION); + } + if (credential.isEncryptionCredential()) { + credentialTypes.add(Saml2X509Credential.Saml2X509CredentialType.ENCRYPTION); + } + if (credential.isDecryptionCredential()) { + credentialTypes.add(Saml2X509Credential.Saml2X509CredentialType.DECRYPTION); + } + return new Saml2X509Credential(privateKey, certificate, credentialTypes); + } + + private static org.springframework.security.saml2.credentials.Saml2X509Credential toDeprecated( + Saml2X509Credential credential) { + PrivateKey privateKey = credential.getPrivateKey(); + X509Certificate certificate = credential.getCertificate(); + Set credentialTypes = new HashSet<>(); + if (credential.isSigningCredential()) { + credentialTypes.add( + org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.SIGNING); + } + if (credential.isVerificationCredential()) { + credentialTypes.add( + org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.VERIFICATION); + } + if (credential.isEncryptionCredential()) { + credentialTypes.add( + org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.ENCRYPTION); + } + if (credential.isDecryptionCredential()) { + credentialTypes.add( + org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.DECRYPTION); + } + return new org.springframework.security.saml2.credentials.Saml2X509Credential(privateKey, certificate, + credentialTypes); + } + /** * The configuration metadata of the Asserting party * @@ -1000,49 +1045,4 @@ public final class RelyingPartyRegistration { } - private static Saml2X509Credential fromDeprecated( - org.springframework.security.saml2.credentials.Saml2X509Credential credential) { - PrivateKey privateKey = credential.getPrivateKey(); - X509Certificate certificate = credential.getCertificate(); - Set credentialTypes = new HashSet<>(); - if (credential.isSigningCredential()) { - credentialTypes.add(Saml2X509Credential.Saml2X509CredentialType.SIGNING); - } - if (credential.isSignatureVerficationCredential()) { - credentialTypes.add(Saml2X509Credential.Saml2X509CredentialType.VERIFICATION); - } - if (credential.isEncryptionCredential()) { - credentialTypes.add(Saml2X509Credential.Saml2X509CredentialType.ENCRYPTION); - } - if (credential.isDecryptionCredential()) { - credentialTypes.add(Saml2X509Credential.Saml2X509CredentialType.DECRYPTION); - } - return new Saml2X509Credential(privateKey, certificate, credentialTypes); - } - - private static org.springframework.security.saml2.credentials.Saml2X509Credential toDeprecated( - Saml2X509Credential credential) { - PrivateKey privateKey = credential.getPrivateKey(); - X509Certificate certificate = credential.getCertificate(); - Set credentialTypes = new HashSet<>(); - if (credential.isSigningCredential()) { - credentialTypes.add( - org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.SIGNING); - } - if (credential.isVerificationCredential()) { - credentialTypes.add( - org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.VERIFICATION); - } - if (credential.isEncryptionCredential()) { - credentialTypes.add( - org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.ENCRYPTION); - } - if (credential.isDecryptionCredential()) { - credentialTypes.add( - org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.DECRYPTION); - } - return new org.springframework.security.saml2.credentials.Saml2X509Credential(privateKey, certificate, - credentialTypes); - } - } diff --git a/test/src/main/java/org/springframework/security/test/context/support/ReactorContextTestExecutionListener.java b/test/src/main/java/org/springframework/security/test/context/support/ReactorContextTestExecutionListener.java index 3c14d2ce20..97572bdf8e 100644 --- a/test/src/main/java/org/springframework/security/test/context/support/ReactorContextTestExecutionListener.java +++ b/test/src/main/java/org/springframework/security/test/context/support/ReactorContextTestExecutionListener.java @@ -57,6 +57,14 @@ public class ReactorContextTestExecutionListener extends DelegatingTestExecution }; } + /** + * Returns {@code 11000}. + */ + @Override + public int getOrder() { + return 11000; + } + private static class DelegateTestExecutionListener extends AbstractTestExecutionListener { @Override @@ -124,12 +132,4 @@ public class ReactorContextTestExecutionListener extends DelegatingTestExecution } - /** - * Returns {@code 11000}. - */ - @Override - public int getOrder() { - return 11000; - } - } diff --git a/test/src/test/java/org/springframework/security/test/context/showcase/WithUserDetailsTests.java b/test/src/test/java/org/springframework/security/test/context/showcase/WithUserDetailsTests.java index 29cbaebbc5..604dcbfbf9 100644 --- a/test/src/test/java/org/springframework/security/test/context/showcase/WithUserDetailsTests.java +++ b/test/src/test/java/org/springframework/security/test/context/showcase/WithUserDetailsTests.java @@ -76,6 +76,10 @@ public class WithUserDetailsTests { assertThat(getPrincipal()).isInstanceOf(CustomUserDetails.class); } + private Object getPrincipal() { + return SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + } + @EnableGlobalMethodSecurity(prePostEnabled = true) @ComponentScan(basePackageClasses = HelloMessageService.class) static class Config { @@ -95,10 +99,6 @@ public class WithUserDetailsTests { } - private Object getPrincipal() { - return SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - } - static class CustomUserDetailsService implements UserDetailsService { @Override diff --git a/test/src/test/java/org/springframework/security/test/context/support/ReactorContextTestExecutionListenerTests.java b/test/src/test/java/org/springframework/security/test/context/support/ReactorContextTestExecutionListenerTests.java index 82aa46912e..915f0997fc 100644 --- a/test/src/test/java/org/springframework/security/test/context/support/ReactorContextTestExecutionListenerTests.java +++ b/test/src/test/java/org/springframework/security/test/context/support/ReactorContextTestExecutionListenerTests.java @@ -100,26 +100,6 @@ public class ReactorContextTestExecutionListenerTests { assertSecurityContext(context); } - static class CustomContext implements SecurityContext { - - private Authentication authentication; - - CustomContext(Authentication authentication) { - this.authentication = authentication; - } - - @Override - public Authentication getAuthentication() { - return this.authentication; - } - - @Override - public void setAuthentication(Authentication authentication) { - this.authentication = authentication; - } - - } - @Test public void beforeTestMethodWhenExistingAuthenticationThenReactorContextHasOriginalAuthentication() throws Exception { @@ -215,4 +195,24 @@ public class ReactorContextTestExecutionListenerTests { StepVerifier.create(securityContext).expectNext(expected).verifyComplete(); } + static class CustomContext implements SecurityContext { + + private Authentication authentication; + + CustomContext(Authentication authentication) { + this.authentication = authentication; + } + + @Override + public Authentication getAuthentication() { + return this.authentication; + } + + @Override + public void setAuthentication(Authentication authentication) { + this.authentication = authentication; + } + + } + } diff --git a/test/src/test/java/org/springframework/security/test/context/support/WithAnonymousUserTests.java b/test/src/test/java/org/springframework/security/test/context/support/WithAnonymousUserTests.java index 7922953309..451d0be461 100644 --- a/test/src/test/java/org/springframework/security/test/context/support/WithAnonymousUserTests.java +++ b/test/src/test/java/org/springframework/security/test/context/support/WithAnonymousUserTests.java @@ -36,11 +36,6 @@ public class WithAnonymousUserTests { assertThat(context.setupBefore()).isEqualTo(TestExecutionEvent.TEST_METHOD); } - @WithAnonymousUser - private class Annotated { - - } - @Test public void findMergedAnnotationWhenSetupExplicitThenOverridden() { WithSecurityContext context = AnnotatedElementUtils.findMergedAnnotation(SetupExplicit.class, @@ -49,11 +44,6 @@ public class WithAnonymousUserTests { assertThat(context.setupBefore()).isEqualTo(TestExecutionEvent.TEST_METHOD); } - @WithAnonymousUser(setupBefore = TestExecutionEvent.TEST_METHOD) - private class SetupExplicit { - - } - @Test public void findMergedAnnotationWhenSetupOverriddenThenOverridden() { WithSecurityContext context = AnnotatedElementUtils.findMergedAnnotation(SetupOverridden.class, @@ -62,6 +52,16 @@ public class WithAnonymousUserTests { assertThat(context.setupBefore()).isEqualTo(TestExecutionEvent.TEST_EXECUTION); } + @WithAnonymousUser + private class Annotated { + + } + + @WithAnonymousUser(setupBefore = TestExecutionEvent.TEST_METHOD) + private class SetupExplicit { + + } + @WithAnonymousUser(setupBefore = TestExecutionEvent.TEST_EXECUTION) private class SetupOverridden { diff --git a/test/src/test/java/org/springframework/security/test/context/support/WithMockUserTests.java b/test/src/test/java/org/springframework/security/test/context/support/WithMockUserTests.java index 50f1cf76ab..b64c85ef7a 100644 --- a/test/src/test/java/org/springframework/security/test/context/support/WithMockUserTests.java +++ b/test/src/test/java/org/springframework/security/test/context/support/WithMockUserTests.java @@ -39,11 +39,6 @@ public class WithMockUserTests { assertThat(context.setupBefore()).isEqualTo(TestExecutionEvent.TEST_METHOD); } - @WithMockUser - private class Annotated { - - } - @Test public void findMergedAnnotationWhenSetupExplicitThenOverridden() { WithSecurityContext context = AnnotatedElementUtils.findMergedAnnotation(SetupExplicit.class, @@ -52,11 +47,6 @@ public class WithMockUserTests { assertThat(context.setupBefore()).isEqualTo(TestExecutionEvent.TEST_METHOD); } - @WithMockUser(setupBefore = TestExecutionEvent.TEST_METHOD) - private class SetupExplicit { - - } - @Test public void findMergedAnnotationWhenSetupOverriddenThenOverridden() { WithSecurityContext context = AnnotatedElementUtils.findMergedAnnotation(SetupOverridden.class, @@ -65,6 +55,16 @@ public class WithMockUserTests { assertThat(context.setupBefore()).isEqualTo(TestExecutionEvent.TEST_EXECUTION); } + @WithMockUser + private class Annotated { + + } + + @WithMockUser(setupBefore = TestExecutionEvent.TEST_METHOD) + private class SetupExplicit { + + } + @WithMockUser(setupBefore = TestExecutionEvent.TEST_EXECUTION) private class SetupOverridden { diff --git a/test/src/test/java/org/springframework/security/test/context/support/WithUserDetailsTests.java b/test/src/test/java/org/springframework/security/test/context/support/WithUserDetailsTests.java index 886bfc128c..d9b1596a1b 100644 --- a/test/src/test/java/org/springframework/security/test/context/support/WithUserDetailsTests.java +++ b/test/src/test/java/org/springframework/security/test/context/support/WithUserDetailsTests.java @@ -35,11 +35,6 @@ public class WithUserDetailsTests { assertThat(context.setupBefore()).isEqualTo(TestExecutionEvent.TEST_METHOD); } - @WithUserDetails - private static class Annotated { - - } - @Test public void findMergedAnnotationWhenSetupExplicitThenOverridden() { WithSecurityContext context = AnnotatedElementUtils.findMergedAnnotation(SetupExplicit.class, @@ -48,11 +43,6 @@ public class WithUserDetailsTests { assertThat(context.setupBefore()).isEqualTo(TestExecutionEvent.TEST_METHOD); } - @WithUserDetails(setupBefore = TestExecutionEvent.TEST_METHOD) - private class SetupExplicit { - - } - @Test public void findMergedAnnotationWhenSetupOverriddenThenOverridden() { WithSecurityContext context = AnnotatedElementUtils.findMergedAnnotation(SetupOverridden.class, @@ -61,6 +51,16 @@ public class WithUserDetailsTests { assertThat(context.setupBefore()).isEqualTo(TestExecutionEvent.TEST_EXECUTION); } + @WithUserDetails + private static class Annotated { + + } + + @WithUserDetails(setupBefore = TestExecutionEvent.TEST_METHOD) + private class SetupExplicit { + + } + @WithUserDetails(setupBefore = TestExecutionEvent.TEST_EXECUTION) private class SetupOverridden { diff --git a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsCsrfTests.java b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsCsrfTests.java index cfdd8d009a..a220845bba 100644 --- a/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsCsrfTests.java +++ b/test/src/test/java/org/springframework/security/test/web/servlet/request/SecurityMockMvcRequestPostProcessorsCsrfTests.java @@ -172,6 +172,10 @@ public class SecurityMockMvcRequestPostProcessorsCsrfTests { return new CsrfParamResultMatcher(); } + public static ResultMatcher csrfAsHeader() { + return new CsrfHeaderResultMatcher(); + } + static class CsrfParamResultMatcher implements ResultMatcher { @Override @@ -183,10 +187,6 @@ public class SecurityMockMvcRequestPostProcessorsCsrfTests { } - public static ResultMatcher csrfAsHeader() { - return new CsrfHeaderResultMatcher(); - } - static class CsrfHeaderResultMatcher implements ResultMatcher { @Override diff --git a/web/src/main/java/org/springframework/security/web/context/HttpSessionSecurityContextRepository.java b/web/src/main/java/org/springframework/security/web/context/HttpSessionSecurityContextRepository.java index 55d5edf3e3..763d2e7ad2 100644 --- a/web/src/main/java/org/springframework/security/web/context/HttpSessionSecurityContextRepository.java +++ b/web/src/main/java/org/springframework/security/web/context/HttpSessionSecurityContextRepository.java @@ -256,6 +256,21 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo this.springSecurityContextKey = springSecurityContextKey; } + private boolean isTransientAuthentication(Authentication authentication) { + return AnnotationUtils.getAnnotation(authentication.getClass(), Transient.class) != null; + } + + /** + * Sets the {@link AuthenticationTrustResolver} to be used. The default is + * {@link AuthenticationTrustResolverImpl}. + * @param trustResolver the {@link AuthenticationTrustResolver} to use. Cannot be + * null. + */ + public void setTrustResolver(AuthenticationTrustResolver trustResolver) { + Assert.notNull(trustResolver, "trustResolver cannot be null"); + this.trustResolver = trustResolver; + } + private static class SaveToSessionRequestWrapper extends HttpServletRequestWrapper { private final SaveContextOnUpdateOrErrorResponseWrapper response; @@ -435,19 +450,4 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo } - private boolean isTransientAuthentication(Authentication authentication) { - return AnnotationUtils.getAnnotation(authentication.getClass(), Transient.class) != null; - } - - /** - * Sets the {@link AuthenticationTrustResolver} to be used. The default is - * {@link AuthenticationTrustResolverImpl}. - * @param trustResolver the {@link AuthenticationTrustResolver} to use. Cannot be - * null. - */ - public void setTrustResolver(AuthenticationTrustResolver trustResolver) { - Assert.notNull(trustResolver, "trustResolver cannot be null"); - this.trustResolver = trustResolver; - } - } diff --git a/web/src/main/java/org/springframework/security/web/header/writers/ClearSiteDataHeaderWriter.java b/web/src/main/java/org/springframework/security/web/header/writers/ClearSiteDataHeaderWriter.java index 305436fbd1..3ba25039a8 100644 --- a/web/src/main/java/org/springframework/security/web/header/writers/ClearSiteDataHeaderWriter.java +++ b/web/src/main/java/org/springframework/security/web/header/writers/ClearSiteDataHeaderWriter.java @@ -82,6 +82,20 @@ public final class ClearSiteDataHeaderWriter implements HeaderWriter { } } + private String transformToHeaderValue(Directive... directives) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < directives.length - 1; i++) { + sb.append(directives[i].headerValue).append(", "); + } + sb.append(directives[directives.length - 1].headerValue); + return sb.toString(); + } + + @Override + public String toString() { + return getClass().getName() + " [headerValue=" + this.headerValue + "]"; + } + /** *

* Represents the directive values expected by the {@link ClearSiteDataHeaderWriter} @@ -104,15 +118,6 @@ public final class ClearSiteDataHeaderWriter implements HeaderWriter { } - private String transformToHeaderValue(Directive... directives) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < directives.length - 1; i++) { - sb.append(directives[i].headerValue).append(", "); - } - sb.append(directives[directives.length - 1].headerValue); - return sb.toString(); - } - private static final class SecureRequestMatcher implements RequestMatcher { @Override @@ -122,9 +127,4 @@ public final class ClearSiteDataHeaderWriter implements HeaderWriter { } - @Override - public String toString() { - return getClass().getName() + " [headerValue=" + this.headerValue + "]"; - } - } diff --git a/web/src/main/java/org/springframework/security/web/server/authentication/SwitchUserWebFilter.java b/web/src/main/java/org/springframework/security/web/server/authentication/SwitchUserWebFilter.java index 82455c1699..e06fbaada5 100644 --- a/web/src/main/java/org/springframework/security/web/server/authentication/SwitchUserWebFilter.java +++ b/web/src/main/java/org/springframework/security/web/server/authentication/SwitchUserWebFilter.java @@ -314,14 +314,6 @@ public class SwitchUserWebFilter implements WebFilter { return new AuthenticationCredentialsNotFoundException("No target user for the given username"); } - private static class SwitchUserAuthenticationException extends RuntimeException { - - SwitchUserAuthenticationException(AuthenticationException exception) { - super(exception); - } - - } - /** * Sets the repository for persisting the SecurityContext. Default is * {@link WebSessionServerSecurityContextRepository} @@ -372,4 +364,12 @@ public class SwitchUserWebFilter implements WebFilter { this.switchUserMatcher = switchUserMatcher; } + private static class SwitchUserAuthenticationException extends RuntimeException { + + SwitchUserAuthenticationException(AuthenticationException exception) { + super(exception); + } + + } + } diff --git a/web/src/main/java/org/springframework/security/web/server/authorization/ServerWebExchangeDelegatingServerAccessDeniedHandler.java b/web/src/main/java/org/springframework/security/web/server/authorization/ServerWebExchangeDelegatingServerAccessDeniedHandler.java index e2fd9dd5b2..38961c513d 100644 --- a/web/src/main/java/org/springframework/security/web/server/authorization/ServerWebExchangeDelegatingServerAccessDeniedHandler.java +++ b/web/src/main/java/org/springframework/security/web/server/authorization/ServerWebExchangeDelegatingServerAccessDeniedHandler.java @@ -84,6 +84,11 @@ public class ServerWebExchangeDelegatingServerAccessDeniedHandler implements Ser this.defaultHandler = accessDeniedHandler; } + private Mono isMatch(ServerWebExchange exchange, DelegateEntry entry) { + ServerWebExchangeMatcher matcher = entry.getMatcher(); + return matcher.matches(exchange).map(ServerWebExchangeMatcher.MatchResult::isMatch); + } + public static class DelegateEntry { private final ServerWebExchangeMatcher matcher; @@ -105,9 +110,4 @@ public class ServerWebExchangeDelegatingServerAccessDeniedHandler implements Ser } - private Mono isMatch(ServerWebExchange exchange, DelegateEntry entry) { - ServerWebExchangeMatcher matcher = entry.getMatcher(); - return matcher.matches(exchange).map(ServerWebExchangeMatcher.MatchResult::isMatch); - } - } diff --git a/web/src/test/java/org/springframework/security/test/web/reactive/server/WebTestHandler.java b/web/src/test/java/org/springframework/security/test/web/reactive/server/WebTestHandler.java index 6eb74cd5c4..07d478e0f9 100644 --- a/web/src/test/java/org/springframework/security/test/web/reactive/server/WebTestHandler.java +++ b/web/src/test/java/org/springframework/security/test/web/reactive/server/WebTestHandler.java @@ -50,6 +50,10 @@ public final class WebTestHandler { return new WebHandlerResult(this.webHandler.exchange); } + public static WebTestHandler bindToWebFilters(WebFilter... filters) { + return new WebTestHandler(filters); + } + public static final class WebHandlerResult { private final ServerWebExchange exchange; @@ -64,10 +68,6 @@ public final class WebTestHandler { } - public static WebTestHandler bindToWebFilters(WebFilter... filters) { - return new WebTestHandler(filters); - } - static class MockWebHandler implements WebHandler { private ServerWebExchange exchange; diff --git a/web/src/test/java/org/springframework/security/web/access/expression/WebExpressionVoterTests.java b/web/src/test/java/org/springframework/security/web/access/expression/WebExpressionVoterTests.java index f08f177a57..608053c1d7 100644 --- a/web/src/test/java/org/springframework/security/web/access/expression/WebExpressionVoterTests.java +++ b/web/src/test/java/org/springframework/security/web/access/expression/WebExpressionVoterTests.java @@ -96,14 +96,6 @@ public class WebExpressionVoterTests { assertThat(voter.supports(FilterInvocationChild.class)).isTrue(); } - private static class FilterInvocationChild extends FilterInvocation { - - FilterInvocationChild(ServletRequest request, ServletResponse response, FilterChain chain) { - super(request, response, chain); - } - - } - @Test public void supportFilterInvocation() { WebExpressionVoter voter = new WebExpressionVoter(); @@ -116,4 +108,12 @@ public class WebExpressionVoterTests { assertThat(voter.supports(Object.class)).isFalse(); } + private static class FilterInvocationChild extends FilterInvocation { + + FilterInvocationChild(ServletRequest request, ServletResponse response, FilterChain chain) { + super(request, response, chain); + } + + } + } diff --git a/web/src/test/java/org/springframework/security/web/authentication/DefaultLoginPageGeneratingFilterTests.java b/web/src/test/java/org/springframework/security/web/authentication/DefaultLoginPageGeneratingFilterTests.java index ff8e4b3560..ea179bd770 100644 --- a/web/src/test/java/org/springframework/security/web/authentication/DefaultLoginPageGeneratingFilterTests.java +++ b/web/src/test/java/org/springframework/security/web/authentication/DefaultLoginPageGeneratingFilterTests.java @@ -150,26 +150,6 @@ public class DefaultLoginPageGeneratingFilterTests { filter.doFilter(new MockHttpServletRequest("GET", "/login"), new MockHttpServletResponse(), this.chain); } - // Fake OpenID filter (since it's not in this module - @SuppressWarnings("unused") - private static class MockProcessingFilter extends AbstractAuthenticationProcessingFilter { - - MockProcessingFilter() { - super("/someurl"); - } - - @Override - public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) - throws AuthenticationException { - return null; - } - - public String getClaimedIdentityFieldName() { - return "unused"; - } - - } - /* SEC-1111 */ @Test public void handlesNonIso8859CharsInErrorMessage() throws Exception { @@ -218,6 +198,25 @@ public class DefaultLoginPageGeneratingFilterTests { assertThat(response.getContentAsString()).contains("Login with SAML 2.0"); assertThat(response.getContentAsString()) .contains("Google < > " ' &"); + } // Fake OpenID filter (since it's not in this module + + @SuppressWarnings("unused") + private static class MockProcessingFilter extends AbstractAuthenticationProcessingFilter { + + MockProcessingFilter() { + super("/someurl"); + } + + @Override + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) + throws AuthenticationException { + return null; + } + + public String getClaimedIdentityFieldName() { + return "unused"; + } + } } diff --git a/web/src/test/java/org/springframework/security/web/bind/support/AuthenticationPrincipalArgumentResolverTests.java b/web/src/test/java/org/springframework/security/web/bind/support/AuthenticationPrincipalArgumentResolverTests.java index 3a0344cb33..d55357f9ff 100644 --- a/web/src/test/java/org/springframework/security/web/bind/support/AuthenticationPrincipalArgumentResolverTests.java +++ b/web/src/test/java/org/springframework/security/web/bind/support/AuthenticationPrincipalArgumentResolverTests.java @@ -180,6 +180,12 @@ public class AuthenticationPrincipalArgumentResolverTests { return new MethodParameter(method, 0); } + private void setAuthenticationPrincipal(Object principal) { + this.expectedPrincipal = principal; + SecurityContextHolder.getContext() + .setAuthentication(new TestingAuthenticationToken(this.expectedPrincipal, "password", "ROLE_USER")); + } + @Target({ ElementType.PARAMETER }) @Retention(RetentionPolicy.RUNTIME) @AuthenticationPrincipal @@ -227,10 +233,4 @@ public class AuthenticationPrincipalArgumentResolverTests { } - private void setAuthenticationPrincipal(Object principal) { - this.expectedPrincipal = principal; - SecurityContextHolder.getContext() - .setAuthentication(new TestingAuthenticationToken(this.expectedPrincipal, "password", "ROLE_USER")); - } - } diff --git a/web/src/test/java/org/springframework/security/web/context/AbstractSecurityWebApplicationInitializerTests.java b/web/src/test/java/org/springframework/security/web/context/AbstractSecurityWebApplicationInitializerTests.java index dd7f1db152..fdaa0cca8d 100644 --- a/web/src/test/java/org/springframework/security/web/context/AbstractSecurityWebApplicationInitializerTests.java +++ b/web/src/test/java/org/springframework/security/web/context/AbstractSecurityWebApplicationInitializerTests.java @@ -92,11 +92,6 @@ public class AbstractSecurityWebApplicationInitializerTests { verify(context).addListener(any(ContextLoaderListener.class)); } - @Configuration - static class MyRootConfiguration { - - } - @Test public void onStartupWhenEnableHttpSessionEventPublisherIsTrueThenAddsHttpSessionEventPublisher() { ServletContext context = mock(ServletContext.class); @@ -435,4 +430,9 @@ public class AbstractSecurityWebApplicationInitializerTests { assertThat(proxy).hasFieldOrPropertyWithValue("targetBeanName", "springSecurityFilterChain"); } + @Configuration + static class MyRootConfiguration { + + } + } diff --git a/web/src/test/java/org/springframework/security/web/method/ResolvableMethod.java b/web/src/test/java/org/springframework/security/web/method/ResolvableMethod.java index 58c6eccc9b..37fe725548 100644 --- a/web/src/test/java/org/springframework/security/web/method/ResolvableMethod.java +++ b/web/src/test/java/org/springframework/security/web/method/ResolvableMethod.java @@ -250,6 +250,52 @@ public final class ResolvableMethod { return new Builder<>(objectClass); } + @SuppressWarnings("unchecked") + private static T initProxy(Class type, MethodInvocationInterceptor interceptor) { + Assert.notNull(type, "'type' must not be null"); + if (type.isInterface()) { + ProxyFactory factory = new ProxyFactory(EmptyTargetSource.INSTANCE); + factory.addInterface(type); + factory.addInterface(Supplier.class); + factory.addAdvice(interceptor); + return (T) factory.getProxy(); + } + + else { + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(type); + enhancer.setInterfaces(new Class[] { Supplier.class }); + enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); + enhancer.setCallbackType(org.springframework.cglib.proxy.MethodInterceptor.class); + + Class proxyClass = enhancer.createClass(); + Object proxy = null; + + if (objenesis.isWorthTrying()) { + try { + proxy = objenesis.newInstance(proxyClass, enhancer.getUseCache()); + } + catch (ObjenesisException ex) { + logger.debug("Objenesis failed, falling back to default constructor", ex); + } + } + + if (proxy == null) { + try { + proxy = ReflectionUtils.accessibleConstructor(proxyClass).newInstance(); + } + catch (Throwable ex) { + throw new IllegalStateException( + "Unable to instantiate proxy " + "via both Objenesis and default constructor fails as well", + ex); + } + } + + ((Factory) proxy).setCallbacks(new Callback[] { interceptor }); + return (T) proxy; + } + } + /** * Builder for {@code ResolvableMethod}. */ @@ -613,50 +659,4 @@ public final class ResolvableMethod { } - @SuppressWarnings("unchecked") - private static T initProxy(Class type, MethodInvocationInterceptor interceptor) { - Assert.notNull(type, "'type' must not be null"); - if (type.isInterface()) { - ProxyFactory factory = new ProxyFactory(EmptyTargetSource.INSTANCE); - factory.addInterface(type); - factory.addInterface(Supplier.class); - factory.addAdvice(interceptor); - return (T) factory.getProxy(); - } - - else { - Enhancer enhancer = new Enhancer(); - enhancer.setSuperclass(type); - enhancer.setInterfaces(new Class[] { Supplier.class }); - enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); - enhancer.setCallbackType(org.springframework.cglib.proxy.MethodInterceptor.class); - - Class proxyClass = enhancer.createClass(); - Object proxy = null; - - if (objenesis.isWorthTrying()) { - try { - proxy = objenesis.newInstance(proxyClass, enhancer.getUseCache()); - } - catch (ObjenesisException ex) { - logger.debug("Objenesis failed, falling back to default constructor", ex); - } - } - - if (proxy == null) { - try { - proxy = ReflectionUtils.accessibleConstructor(proxyClass).newInstance(); - } - catch (Throwable ex) { - throw new IllegalStateException( - "Unable to instantiate proxy " + "via both Objenesis and default constructor fails as well", - ex); - } - } - - ((Factory) proxy).setCallbacks(new Callback[] { interceptor }); - return (T) proxy; - } - } - } diff --git a/web/src/test/java/org/springframework/security/web/method/annotation/AuthenticationPrincipalArgumentResolverTests.java b/web/src/test/java/org/springframework/security/web/method/annotation/AuthenticationPrincipalArgumentResolverTests.java index 9d5af585de..c4a5545f84 100644 --- a/web/src/test/java/org/springframework/security/web/method/annotation/AuthenticationPrincipalArgumentResolverTests.java +++ b/web/src/test/java/org/springframework/security/web/method/annotation/AuthenticationPrincipalArgumentResolverTests.java @@ -204,6 +204,12 @@ public class AuthenticationPrincipalArgumentResolverTests { return new MethodParameter(method, 0); } + private void setAuthenticationPrincipal(Object principal) { + this.expectedPrincipal = principal; + SecurityContextHolder.getContext() + .setAuthentication(new TestingAuthenticationToken(this.expectedPrincipal, "password", "ROLE_USER")); + } + @Target({ ElementType.PARAMETER }) @Retention(RetentionPolicy.RUNTIME) @AuthenticationPrincipal @@ -305,10 +311,4 @@ public class AuthenticationPrincipalArgumentResolverTests { } - private void setAuthenticationPrincipal(Object principal) { - this.expectedPrincipal = principal; - SecurityContextHolder.getContext() - .setAuthentication(new TestingAuthenticationToken(this.expectedPrincipal, "password", "ROLE_USER")); - } - } diff --git a/web/src/test/java/org/springframework/security/web/method/annotation/CurrentSecurityContextArgumentResolverTests.java b/web/src/test/java/org/springframework/security/web/method/annotation/CurrentSecurityContextArgumentResolverTests.java index 61d4f06744..e2c94bfa5f 100644 --- a/web/src/test/java/org/springframework/security/web/method/annotation/CurrentSecurityContextArgumentResolverTests.java +++ b/web/src/test/java/org/springframework/security/web/method/annotation/CurrentSecurityContextArgumentResolverTests.java @@ -259,6 +259,23 @@ public class CurrentSecurityContextArgumentResolverTests { return new MethodParameter(method, 0); } + private void setAuthenticationPrincipal(Object principal) { + SecurityContextHolder.getContext() + .setAuthentication(new TestingAuthenticationToken(principal, "password", "ROLE_USER")); + } + + private void setAuthenticationPrincipalWithCustomSecurityContext(Object principal) { + CustomSecurityContext csc = new CustomSecurityContext(); + csc.setAuthentication(new TestingAuthenticationToken(principal, "password", "ROLE_USER")); + SecurityContextHolder.setContext(csc); + } + + private void setAuthenticationDetail(Object detail) { + TestingAuthenticationToken tat = new TestingAuthenticationToken("user", "password", "ROLE_USER"); + tat.setDetails(detail); + SecurityContextHolder.getContext().setAuthentication(tat); + } + public static class TestController { public void showSecurityContextNoAnnotation(String user) { @@ -317,17 +334,6 @@ public class CurrentSecurityContextArgumentResolverTests { } - private void setAuthenticationPrincipal(Object principal) { - SecurityContextHolder.getContext() - .setAuthentication(new TestingAuthenticationToken(principal, "password", "ROLE_USER")); - } - - private void setAuthenticationPrincipalWithCustomSecurityContext(Object principal) { - CustomSecurityContext csc = new CustomSecurityContext(); - csc.setAuthentication(new TestingAuthenticationToken(principal, "password", "ROLE_USER")); - SecurityContextHolder.setContext(csc); - } - static class CustomSecurityContext implements SecurityContext { private Authentication authentication; @@ -365,10 +371,4 @@ public class CurrentSecurityContextArgumentResolverTests { } - private void setAuthenticationDetail(Object detail) { - TestingAuthenticationToken tat = new TestingAuthenticationToken("user", "password", "ROLE_USER"); - tat.setDetails(detail); - SecurityContextHolder.getContext().setAuthentication(tat); - } - } diff --git a/web/src/test/java/org/springframework/security/web/reactive/result/method/annotation/CurrentSecurityContextArgumentResolverTests.java b/web/src/test/java/org/springframework/security/web/reactive/result/method/annotation/CurrentSecurityContextArgumentResolverTests.java index a6e3c40c26..f138550b42 100644 --- a/web/src/test/java/org/springframework/security/web/reactive/result/method/annotation/CurrentSecurityContextArgumentResolverTests.java +++ b/web/src/test/java/org/springframework/security/web/reactive/result/method/annotation/CurrentSecurityContextArgumentResolverTests.java @@ -348,6 +348,10 @@ public class CurrentSecurityContextArgumentResolverTests { @CurrentSecurityWithErrorOnInvalidType Mono typeMisMatch) { } + private Authentication buildAuthenticationWithPrincipal(Object principal) { + return new TestingAuthenticationToken(principal, "password", "ROLE_USER"); + } + @Target({ ElementType.PARAMETER }) @Retention(RetentionPolicy.RUNTIME) @CurrentSecurityContext @@ -389,8 +393,4 @@ public class CurrentSecurityContextArgumentResolverTests { } - private Authentication buildAuthenticationWithPrincipal(Object principal) { - return new TestingAuthenticationToken(principal, "password", "ROLE_USER"); - } - } diff --git a/web/src/test/java/org/springframework/security/web/util/ThrowableAnalyzerTests.java b/web/src/test/java/org/springframework/security/web/util/ThrowableAnalyzerTests.java index 390aae5c85..1c6fa7efb6 100644 --- a/web/src/test/java/org/springframework/security/web/util/ThrowableAnalyzerTests.java +++ b/web/src/test/java/org/springframework/security/web/util/ThrowableAnalyzerTests.java @@ -31,39 +31,6 @@ import static org.assertj.core.api.Assertions.fail; @SuppressWarnings("unchecked") public class ThrowableAnalyzerTests { - /** - * Exception for testing purposes. The cause is not retrievable by {@link #getCause()} - * . - */ - public static final class NonStandardException extends Exception { - - private Throwable cause; - - public NonStandardException(String message, Throwable cause) { - super(message); - this.cause = cause; - } - - public Throwable resolveCause() { - return this.cause; - } - - } - - /** - * ThrowableCauseExtractor for handling NonStandardException - * instances. - */ - public static final class NonStandardExceptionCauseExtractor implements ThrowableCauseExtractor { - - @Override - public Throwable extractCause(Throwable throwable) { - ThrowableAnalyzer.verifyThrowableHierarchy(throwable, NonStandardException.class); - return ((NonStandardException) throwable).resolveCause(); - } - - } - /** * An array of nested throwables for testing. The cause of element 0 is element 1, the * cause of element 1 is element 2 and so on. @@ -282,4 +249,37 @@ public class ThrowableAnalyzerTests { } } + /** + * Exception for testing purposes. The cause is not retrievable by {@link #getCause()} + * . + */ + public static final class NonStandardException extends Exception { + + private Throwable cause; + + public NonStandardException(String message, Throwable cause) { + super(message); + this.cause = cause; + } + + public Throwable resolveCause() { + return this.cause; + } + + } + + /** + * ThrowableCauseExtractor for handling NonStandardException + * instances. + */ + public static final class NonStandardExceptionCauseExtractor implements ThrowableCauseExtractor { + + @Override + public Throwable extractCause(Throwable throwable) { + ThrowableAnalyzer.verifyThrowableHierarchy(throwable, NonStandardException.class); + return ((NonStandardException) throwable).resolveCause(); + } + + } + }