浏览代码

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
Phillip Webb 5 年之前
父节点
当前提交
a2f2e9ac8d
共有 100 个文件被更改,包括 8595 次插入8731 次删除
  1. 8 8
      acl/src/test/java/org/springframework/security/acls/jdbc/JdbcMutableAclServiceTests.java
  2. 76 76
      config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderBuilderSecurityBuilderTests.java
  3. 15 15
      config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java
  4. 92 92
      config/src/main/java/org/springframework/security/config/annotation/rsocket/RSocketSecurity.java
  5. 18 18
      config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java
  6. 30 30
      config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java
  7. 29 29
      config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.java
  8. 38 38
      config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractInterceptUrlConfigurer.java
  9. 55 55
      config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java
  10. 351 351
      config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java
  11. 138 138
      config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java
  12. 42 42
      config/src/main/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurer.java
  13. 10 10
      config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurer.java
  14. 211 211
      config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java
  15. 64 64
      config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java
  16. 23 23
      config/src/main/java/org/springframework/security/config/annotation/web/messaging/MessageSecurityMetadataSourceRegistry.java
  17. 19 19
      config/src/main/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurer.java
  18. 1590 1687
      config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java
  19. 52 52
      config/src/test/java/org/springframework/security/config/annotation/authentication/AuthenticationManagerBuilderTests.java
  20. 21 21
      config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationManagerTests.java
  21. 8 8
      config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationProviderTests.java
  22. 7 7
      config/src/test/java/org/springframework/security/config/annotation/authentication/NamespaceJdbcUserServiceTests.java
  23. 14 14
      config/src/test/java/org/springframework/security/config/annotation/authentication/NamespacePasswordEncoderTests.java
  24. 7 7
      config/src/test/java/org/springframework/security/config/annotation/authentication/PasswordEncoderConfigurerTests.java
  25. 194 199
      config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationTests.java
  26. 20 20
      config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/EnableGlobalAuthenticationTests.java
  27. 19 19
      config/src/test/java/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessorTests.java
  28. 197 198
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.java
  29. 198 222
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityTests.java
  30. 11 11
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityConfigurationTests.java
  31. 10 10
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/SampleEnableGlobalMethodSecurityTests.java
  32. 12 12
      config/src/test/java/org/springframework/security/config/annotation/sec2758/Sec2758Tests.java
  33. 33 33
      config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryAnyMatcherTests.java
  34. 100 100
      config/src/test/java/org/springframework/security/config/annotation/web/SampleWebSecurityConfigurerAdapterTests.java
  35. 21 21
      config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterPowermockTests.java
  36. 129 129
      config/src/test/java/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterTests.java
  37. 22 22
      config/src/test/java/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.java
  38. 206 206
      config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java
  39. 44 44
      config/src/test/java/org/springframework/security/config/annotation/web/builders/WebSecurityTests.java
  40. 42 42
      config/src/test/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurityTests.java
  41. 30 30
      config/src/test/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfigurationTests.java
  42. 83 83
      config/src/test/java/org/springframework/security/config/annotation/web/configuration/OAuth2ClientConfigurationTests.java
  43. 23 24
      config/src/test/java/org/springframework/security/config/annotation/web/configuration/Sec2515Tests.java
  44. 186 186
      config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java
  45. 21 21
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/AnonymousConfigurerTests.java
  46. 265 265
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeRequestsTests.java
  47. 14 14
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurerTests.java
  48. 118 118
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/CorsConfigurerTests.java
  49. 34 34
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerIgnoringRequestMatchersTests.java
  50. 7 7
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerNoWebMvcTests.java
  51. 232 232
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerTests.java
  52. 54 54
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultFiltersTests.java
  53. 135 135
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurerTests.java
  54. 20 20
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerAccessDeniedHandlerTests.java
  55. 65 65
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerTests.java
  56. 371 371
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurerTests.java
  57. 192 192
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurerTests.java
  58. 12 12
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerEagerHeadersTests.java
  59. 360 360
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerTests.java
  60. 46 46
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurerTests.java
  61. 19 19
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityAntMatchersTests.java
  62. 8 8
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java
  63. 113 113
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityRequestMatchersTests.java
  64. 30 30
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/Issue55Tests.java
  65. 57 57
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/JeeConfigurerTests.java
  66. 176 176
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurerTests.java
  67. 10 10
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceDebugTests.java
  68. 24 24
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpAnonymousTests.java
  69. 84 84
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpBasicTests.java
  70. 31 31
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpCustomFilterTests.java
  71. 4 4
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpExpressionHandlerTests.java
  72. 12 12
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFirewallTests.java
  73. 30 30
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFormLoginTests.java
  74. 87 92
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpHeadersTests.java
  75. 4 4
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpInterceptUrlTests.java
  76. 25 25
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpJeeTests.java
  77. 67 67
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.java
  78. 53 53
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpOpenIDLoginTests.java
  79. 15 15
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpRequestCacheTests.java
  80. 34 34
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpServerAccessDeniedHandlerTests.java
  81. 52 52
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.java
  82. 154 155
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.java
  83. 98 98
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.java
  84. 7 7
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/PermitAllSupportTests.java
  85. 14 14
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurerTests.java
  86. 113 113
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.java
  87. 94 94
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java
  88. 8 8
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestMatcherConfigurerTests.java
  89. 45 45
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurerTests.java
  90. 121 121
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurerTests.java
  91. 18 18
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java
  92. 20 20
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionCreationPolicyTests.java
  93. 185 185
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTests.java
  94. 49 49
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurerTests.java
  95. 19 19
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationsTests.java
  96. 34 34
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/X509ConfigurerTests.java
  97. 31 31
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java
  98. 83 85
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java
  99. 85 85
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/openid/OpenIDLoginConfigurerTests.java
  100. 38 38
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurerTests.java

+ 8 - 8
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;
-	}
-
 }

+ 76 - 76
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<LdapAuthenticationProvider>) 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<LdapAuthenticationProvider>) 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;
-	}
-
 }

+ 15 - 15
config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java

@@ -379,6 +379,21 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
 		builder.authenticationProvider(provider);
 	}
 
+	private BaseLdapPathContextSource getContextSource() throws Exception {
+		if (this.contextSource == null) {
+			this.contextSource = this.contextSourceBuilder.build();
+		}
+		return this.contextSource;
+	}
+
+	/**
+	 * @return the {@link PasswordCompareConfigurer} for further customizations
+	 */
+	public PasswordCompareConfigurer passwordCompare() {
+		return new PasswordCompareConfigurer().passwordAttribute("password")
+				.passwordEncoder(NoOpPasswordEncoder.getInstance());
+	}
+
 	/**
 	 * Sets up Password based comparison
 	 *
@@ -597,19 +612,4 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
 
 	}
 
-	private BaseLdapPathContextSource getContextSource() throws Exception {
-		if (this.contextSource == null) {
-			this.contextSource = this.contextSourceBuilder.build();
-		}
-		return this.contextSource;
-	}
-
-	/**
-	 * @return the {@link PasswordCompareConfigurer} for further customizations
-	 */
-	public PasswordCompareConfigurer passwordCompare() {
-		return new PasswordCompareConfigurer().passwordAttribute("password")
-				.passwordEncoder(NoOpPasswordEncoder.getInstance());
-	}
-
 }

+ 92 - 92
config/src/main/java/org/springframework/security/config/annotation/rsocket/RSocketSecurity.java

@@ -161,6 +161,98 @@ public class RSocketSecurity {
 		return this;
 	}
 
+	/**
+	 * Adds authentication with BasicAuthenticationPayloadExchangeConverter.
+	 * @param basic
+	 * @return this instance
+	 * @deprecated Use {@link #simpleAuthentication(Customizer)}
+	 */
+	@Deprecated
+	public RSocketSecurity basicAuthentication(Customizer<BasicAuthenticationSpec> basic) {
+		if (this.basicAuthSpec == null) {
+			this.basicAuthSpec = new BasicAuthenticationSpec();
+		}
+		basic.customize(this.basicAuthSpec);
+		return this;
+	}
+
+	public RSocketSecurity jwt(Customizer<JwtSpec> jwt) {
+		if (this.jwtSpec == null) {
+			this.jwtSpec = new JwtSpec();
+		}
+		jwt.customize(this.jwtSpec);
+		return this;
+	}
+
+	public RSocketSecurity authorizePayload(Customizer<AuthorizePayloadsSpec> authorize) {
+		if (this.authorizePayload == null) {
+			this.authorizePayload = new AuthorizePayloadsSpec();
+		}
+		authorize.customize(this.authorizePayload);
+		return this;
+	}
+
+	public PayloadSocketAcceptorInterceptor build() {
+		PayloadSocketAcceptorInterceptor interceptor = new PayloadSocketAcceptorInterceptor(payloadInterceptors());
+		RSocketMessageHandler handler = getBean(RSocketMessageHandler.class);
+		interceptor.setDefaultDataMimeType(handler.getDefaultDataMimeType());
+		interceptor.setDefaultMetadataMimeType(handler.getDefaultMetadataMimeType());
+		return interceptor;
+	}
+
+	private List<PayloadInterceptor> payloadInterceptors() {
+		List<PayloadInterceptor> result = new ArrayList<>(this.payloadInterceptors);
+
+		if (this.basicAuthSpec != null) {
+			result.add(this.basicAuthSpec.build());
+		}
+		if (this.simpleAuthSpec != null) {
+			result.add(this.simpleAuthSpec.build());
+		}
+		if (this.jwtSpec != null) {
+			result.addAll(this.jwtSpec.build());
+		}
+		result.add(anonymous());
+
+		if (this.authorizePayload != null) {
+			result.add(this.authorizePayload.build());
+		}
+		AnnotationAwareOrderComparator.sort(result);
+		return result;
+	}
+
+	private AnonymousPayloadInterceptor anonymous() {
+		AnonymousPayloadInterceptor result = new AnonymousPayloadInterceptor("anonymousUser");
+		result.setOrder(PayloadInterceptorOrder.ANONYMOUS.getOrder());
+		return result;
+	}
+
+	private <T> T getBean(Class<T> beanClass) {
+		if (this.context == null) {
+			return null;
+		}
+		return this.context.getBean(beanClass);
+	}
+
+	private <T> T getBeanOrNull(Class<T> beanClass) {
+		return getBeanOrNull(ResolvableType.forClass(beanClass));
+	}
+
+	private <T> 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
 	 */
@@ -193,21 +285,6 @@ public class RSocketSecurity {
 
 	}
 
-	/**
-	 * Adds authentication with BasicAuthenticationPayloadExchangeConverter.
-	 * @param basic
-	 * @return this instance
-	 * @deprecated Use {@link #simpleAuthentication(Customizer)}
-	 */
-	@Deprecated
-	public RSocketSecurity basicAuthentication(Customizer<BasicAuthenticationSpec> basic) {
-		if (this.basicAuthSpec == null) {
-			this.basicAuthSpec = new BasicAuthenticationSpec();
-		}
-		basic.customize(this.basicAuthSpec);
-		return this;
-	}
-
 	public final class BasicAuthenticationSpec {
 
 		private ReactiveAuthenticationManager authenticationManager;
@@ -236,14 +313,6 @@ public class RSocketSecurity {
 
 	}
 
-	public RSocketSecurity jwt(Customizer<JwtSpec> jwt) {
-		if (this.jwtSpec == null) {
-			this.jwtSpec = new JwtSpec();
-		}
-		jwt.customize(this.jwtSpec);
-		return this;
-	}
-
 	public final class JwtSpec {
 
 		private ReactiveAuthenticationManager authenticationManager;
@@ -283,49 +352,6 @@ public class RSocketSecurity {
 
 	}
 
-	public RSocketSecurity authorizePayload(Customizer<AuthorizePayloadsSpec> authorize) {
-		if (this.authorizePayload == null) {
-			this.authorizePayload = new AuthorizePayloadsSpec();
-		}
-		authorize.customize(this.authorizePayload);
-		return this;
-	}
-
-	public PayloadSocketAcceptorInterceptor build() {
-		PayloadSocketAcceptorInterceptor interceptor = new PayloadSocketAcceptorInterceptor(payloadInterceptors());
-		RSocketMessageHandler handler = getBean(RSocketMessageHandler.class);
-		interceptor.setDefaultDataMimeType(handler.getDefaultDataMimeType());
-		interceptor.setDefaultMetadataMimeType(handler.getDefaultMetadataMimeType());
-		return interceptor;
-	}
-
-	private List<PayloadInterceptor> payloadInterceptors() {
-		List<PayloadInterceptor> result = new ArrayList<>(this.payloadInterceptors);
-
-		if (this.basicAuthSpec != null) {
-			result.add(this.basicAuthSpec.build());
-		}
-		if (this.simpleAuthSpec != null) {
-			result.add(this.simpleAuthSpec.build());
-		}
-		if (this.jwtSpec != null) {
-			result.addAll(this.jwtSpec.build());
-		}
-		result.add(anonymous());
-
-		if (this.authorizePayload != null) {
-			result.add(this.authorizePayload.build());
-		}
-		AnnotationAwareOrderComparator.sort(result);
-		return result;
-	}
-
-	private AnonymousPayloadInterceptor anonymous() {
-		AnonymousPayloadInterceptor result = new AnonymousPayloadInterceptor("anonymousUser");
-		result.setOrder(PayloadInterceptorOrder.ANONYMOUS.getOrder());
-		return result;
-	}
-
 	public class AuthorizePayloadsSpec {
 
 		private PayloadExchangeMatcherReactiveAuthorizationManager.Builder authzBuilder = PayloadExchangeMatcherReactiveAuthorizationManager
@@ -417,30 +443,4 @@ public class RSocketSecurity {
 
 	}
 
-	private <T> T getBean(Class<T> beanClass) {
-		if (this.context == null) {
-			return null;
-		}
-		return this.context.getBean(beanClass);
-	}
-
-	private <T> T getBeanOrNull(Class<T> beanClass) {
-		return getBeanOrNull(ResolvableType.forClass(beanClass));
-	}
-
-	private <T> 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;
-	}
-
 }

+ 18 - 18
config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java

@@ -2912,6 +2912,24 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
 		return requestMatcher(new RegexRequestMatcher(pattern, null));
 	}
 
+	/**
+	 * If the {@link SecurityConfigurer} has already been specified get the original,
+	 * otherwise apply the new {@link SecurityConfigurerAdapter}.
+	 * @param configurer the {@link SecurityConfigurer} to apply if one is not found for
+	 * this {@link SecurityConfigurer} class.
+	 * @return the current {@link SecurityConfigurer} for the configurer passed in
+	 * @throws Exception
+	 */
+	@SuppressWarnings("unchecked")
+	private <C extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity>> 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<Defaul
 
 	}
 
-	/**
-	 * If the {@link SecurityConfigurer} has already been specified get the original,
-	 * otherwise apply the new {@link SecurityConfigurerAdapter}.
-	 * @param configurer the {@link SecurityConfigurer} to apply if one is not found for
-	 * this {@link SecurityConfigurer} class.
-	 * @return the current {@link SecurityConfigurer} for the configurer passed in
-	 * @throws Exception
-	 */
-	@SuppressWarnings("unchecked")
-	private <C extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity>> C getOrApply(C configurer)
-			throws Exception {
-		C existingConfig = (C) getConfigurer(configurer.getClass());
-		if (existingConfig != null) {
-			return existingConfig;
-		}
-		return apply(configurer);
-	}
-
 }

+ 30 - 30
config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java

@@ -304,6 +304,36 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder<Filter,
 		return result;
 	}
 
+	@Override
+	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+		this.defaultWebSecurityExpressionHandler.setApplicationContext(applicationContext);
+
+		try {
+			this.defaultWebSecurityExpressionHandler.setRoleHierarchy(applicationContext.getBean(RoleHierarchy.class));
+		}
+		catch (NoSuchBeanDefinitionException e) {
+		}
+
+		try {
+			this.defaultWebSecurityExpressionHandler
+					.setPermissionEvaluator(applicationContext.getBean(PermissionEvaluator.class));
+		}
+		catch (NoSuchBeanDefinitionException e) {
+		}
+
+		this.ignoredRequestRegistry = new IgnoredRequestConfigurer(applicationContext);
+		try {
+			this.httpFirewall = applicationContext.getBean(HttpFirewall.class);
+		}
+		catch (NoSuchBeanDefinitionException e) {
+		}
+		try {
+			this.requestRejectedHandler = applicationContext.getBean(RequestRejectedHandler.class);
+		}
+		catch (NoSuchBeanDefinitionException e) {
+		}
+	}
+
 	/**
 	 * An {@link IgnoredRequestConfigurer} that allows optionally configuring the
 	 * {@link MvcRequestMatcher#setMethod(HttpMethod)}
@@ -368,34 +398,4 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder<Filter,
 
 	}
 
-	@Override
-	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
-		this.defaultWebSecurityExpressionHandler.setApplicationContext(applicationContext);
-
-		try {
-			this.defaultWebSecurityExpressionHandler.setRoleHierarchy(applicationContext.getBean(RoleHierarchy.class));
-		}
-		catch (NoSuchBeanDefinitionException e) {
-		}
-
-		try {
-			this.defaultWebSecurityExpressionHandler
-					.setPermissionEvaluator(applicationContext.getBean(PermissionEvaluator.class));
-		}
-		catch (NoSuchBeanDefinitionException e) {
-		}
-
-		this.ignoredRequestRegistry = new IgnoredRequestConfigurer(applicationContext);
-		try {
-			this.httpFirewall = applicationContext.getBean(HttpFirewall.class);
-		}
-		catch (NoSuchBeanDefinitionException e) {
-		}
-		try {
-			this.requestRejectedHandler = applicationContext.getBean(RequestRejectedHandler.class);
-		}
-		catch (NoSuchBeanDefinitionException e) {
-		}
-	}
-
 }

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

@@ -188,6 +188,35 @@ public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAwa
 		return new AutowiredWebSecurityConfigurersIgnoreParents(beanFactory);
 	}
 
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.springframework.context.annotation.ImportAware#setImportMetadata(org.
+	 * springframework.core.type.AnnotationMetadata)
+	 */
+	@Override
+	public void setImportMetadata(AnnotationMetadata importMetadata) {
+		Map<String, Object> 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<String, Object> 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;
-	}
-
 }

+ 38 - 38
config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractInterceptUrlConfigurer.java

@@ -102,44 +102,6 @@ abstract class AbstractInterceptUrlConfigurer<C extends AbstractInterceptUrlConf
 	 */
 	abstract List<AccessDecisionVoter<?>> getDecisionVoters(H http);
 
-	abstract class AbstractInterceptUrlRegistry<R extends AbstractInterceptUrlRegistry<R, T>, T>
-			extends AbstractConfigAttributeRequestMatcherRegistry<T> {
-
-		/**
-		 * 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<C extends AbstractInterceptUrlConf
 		return securityInterceptor;
 	}
 
+	abstract class AbstractInterceptUrlRegistry<R extends AbstractInterceptUrlRegistry<R, T>, T>
+			extends AbstractConfigAttributeRequestMatcherRegistry<T> {
+
+		/**
+		 * 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;
+		}
+
+	}
+
 }

+ 55 - 55
config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java

@@ -109,61 +109,6 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
 		return this.REGISTRY;
 	}
 
-	public final class ExpressionInterceptUrlRegistry extends
-			ExpressionUrlAuthorizationConfigurer<H>.AbstractInterceptUrlRegistry<ExpressionInterceptUrlRegistry, AuthorizedUrl> {
-
-		/**
-		 * @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<RequestMatcher> 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<FilterInvocation> 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<H extends HttpSecurityBu
 		return "hasIpAddress('" + ipAddressExpression + "')";
 	}
 
+	public final class ExpressionInterceptUrlRegistry extends
+			ExpressionUrlAuthorizationConfigurer<H>.AbstractInterceptUrlRegistry<ExpressionInterceptUrlRegistry, AuthorizedUrl> {
+
+		/**
+		 * @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<RequestMatcher> 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<FilterInvocation> 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)}

+ 351 - 351
config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java

@@ -145,6 +145,357 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
 		return HeadersConfigurer.this;
 	}
 
+	/**
+	 * <strong>Note this is not comprehensive XSS protection!</strong>
+	 *
+	 * <p>
+	 * Allows customizing the {@link XXssProtectionHeaderWriter} which adds the <a href=
+	 * "https://blogs.msdn.com/b/ieinternals/archive/2011/01/31/controlling-the-internet-explorer-xss-filter-with-the-x-xss-protection-http-header.aspx"
+	 * >X-XSS-Protection header</a>
+	 * </p>
+	 * @return the {@link XXssConfig} for additional customizations
+	 */
+	public XXssConfig xssProtection() {
+		return this.xssProtection.enable();
+	}
+
+	/**
+	 * <strong>Note this is not comprehensive XSS protection!</strong>
+	 *
+	 * <p>
+	 * Allows customizing the {@link XXssProtectionHeaderWriter} which adds the <a href=
+	 * "https://blogs.msdn.com/b/ieinternals/archive/2011/01/31/controlling-the-internet-explorer-xss-filter-with-the-x-xss-protection-http-header.aspx"
+	 * >X-XSS-Protection header</a>
+	 * </p>
+	 * @param xssCustomizer the {@link Customizer} to provide more options for the
+	 * {@link XXssConfig}
+	 * @return the {@link HeadersConfigurer} for additional customizations
+	 */
+	public HeadersConfigurer<H> xssProtection(Customizer<XXssConfig> xssCustomizer) {
+		xssCustomizer.customize(this.xssProtection.enable());
+		return HeadersConfigurer.this;
+	}
+
+	/**
+	 * Allows customizing the {@link CacheControlHeadersWriter}. Specifically it adds the
+	 * following headers:
+	 * <ul>
+	 * <li>Cache-Control: no-cache, no-store, max-age=0, must-revalidate</li>
+	 * <li>Pragma: no-cache</li>
+	 * <li>Expires: 0</li>
+	 * </ul>
+	 * @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:
+	 * <ul>
+	 * <li>Cache-Control: no-cache, no-store, max-age=0, must-revalidate</li>
+	 * <li>Pragma: no-cache</li>
+	 * <li>Expires: 0</li>
+	 * </ul>
+	 * @param cacheControlCustomizer the {@link Customizer} to provide more options for
+	 * the {@link CacheControlConfig}
+	 * @return the {@link HeadersConfigurer} for additional customizations
+	 */
+	public HeadersConfigurer<H> cacheControl(Customizer<CacheControlConfig> cacheControlCustomizer) {
+		cacheControlCustomizer.customize(this.cacheControl.enable());
+		return HeadersConfigurer.this;
+	}
+
+	/**
+	 * Allows customizing the {@link HstsHeaderWriter} which provides support for
+	 * <a href="https://tools.ietf.org/html/rfc6797">HTTP Strict Transport Security
+	 * (HSTS)</a>.
+	 * @return the {@link HstsConfig} for additional customizations
+	 */
+	public HstsConfig httpStrictTransportSecurity() {
+		return this.hsts.enable();
+	}
+
+	/**
+	 * Allows customizing the {@link HstsHeaderWriter} which provides support for
+	 * <a href="https://tools.ietf.org/html/rfc6797">HTTP Strict Transport Security
+	 * (HSTS)</a>.
+	 * @param hstsCustomizer the {@link Customizer} to provide more options for the
+	 * {@link HstsConfig}
+	 * @return the {@link HeadersConfigurer} for additional customizations
+	 */
+	public HeadersConfigurer<H> httpStrictTransportSecurity(Customizer<HstsConfig> 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<H> frameOptions(Customizer<FrameOptionsConfig> frameOptionsCustomizer) {
+		frameOptionsCustomizer.customize(this.frameOptions.enable());
+		return HeadersConfigurer.this;
+	}
+
+	/**
+	 * Allows customizing the {@link HpkpHeaderWriter} which provides support for
+	 * <a href="https://tools.ietf.org/html/rfc7469">HTTP Public Key Pinning (HPKP)</a>.
+	 * @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
+	 * <a href="https://tools.ietf.org/html/rfc7469">HTTP Public Key Pinning (HPKP)</a>.
+	 * @param hpkpCustomizer the {@link Customizer} to provide more options for the
+	 * {@link HpkpConfig}
+	 * @return the {@link HeadersConfigurer} for additional customizations
+	 */
+	public HeadersConfigurer<H> httpPublicKeyPinning(Customizer<HpkpConfig> hpkpCustomizer) {
+		hpkpCustomizer.customize(this.hpkp.enable());
+		return HeadersConfigurer.this;
+	}
+
+	/**
+	 * <p>
+	 * Allows configuration for <a href="https://www.w3.org/TR/CSP2/">Content Security
+	 * Policy (CSP) Level 2</a>.
+	 * </p>
+	 *
+	 * <p>
+	 * Calling this method automatically enables (includes) the Content-Security-Policy
+	 * header in the response using the supplied security policy directive(s).
+	 * </p>
+	 *
+	 * <p>
+	 * Configuration is provided to the {@link ContentSecurityPolicyHeaderWriter} which
+	 * supports the writing of the two headers as detailed in the W3C Candidate
+	 * Recommendation:
+	 * </p>
+	 * <ul>
+	 * <li>Content-Security-Policy</li>
+	 * <li>Content-Security-Policy-Report-Only</li>
+	 * </ul>
+	 * @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;
+	}
+
+	/**
+	 * <p>
+	 * Allows configuration for <a href="https://www.w3.org/TR/CSP2/">Content Security
+	 * Policy (CSP) Level 2</a>.
+	 * </p>
+	 *
+	 * <p>
+	 * Calling this method automatically enables (includes) the Content-Security-Policy
+	 * header in the response using the supplied security policy directive(s).
+	 * </p>
+	 *
+	 * <p>
+	 * Configuration is provided to the {@link ContentSecurityPolicyHeaderWriter} which
+	 * supports the writing of the two headers as detailed in the W3C Candidate
+	 * Recommendation:
+	 * </p>
+	 * <ul>
+	 * <li>Content-Security-Policy</li>
+	 * <li>Content-Security-Policy-Report-Only</li>
+	 * </ul>
+	 * @param contentSecurityCustomizer the {@link Customizer} to provide more options for
+	 * the {@link ContentSecurityPolicyConfig}
+	 * @return the {@link HeadersConfigurer} for additional customizations
+	 * @see ContentSecurityPolicyHeaderWriter
+	 */
+	public HeadersConfigurer<H> contentSecurityPolicy(
+			Customizer<ContentSecurityPolicyConfig> 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:
+	 *
+	 * <pre>
+	 * http.headers().defaultsDisabled().cacheControl();
+	 * </pre>
+	 * @return the {@link HeadersConfigurer} for additional customization
+	 */
+	public HeadersConfigurer<H> 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<HeaderWriter> 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<HeaderWriter> getHeaderWriters() {
+		List<HeaderWriter> 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 <T> void addIfNotNull(List<T> values, T value) {
+		if (value != null) {
+			values.add(value);
+		}
+	}
+
+	/**
+	 * <p>
+	 * Allows configuration for <a href="https://www.w3.org/TR/referrer-policy/">Referrer
+	 * Policy</a>.
+	 * </p>
+	 *
+	 * <p>
+	 * Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support
+	 * the writing of the header as detailed in the W3C Technical Report:
+	 * </p>
+	 * <ul>
+	 * <li>Referrer-Policy</li>
+	 * </ul>
+	 *
+	 * <p>
+	 * Default value is:
+	 * </p>
+	 *
+	 * <pre>
+	 * Referrer-Policy: no-referrer
+	 * </pre>
+	 * @return the {@link ReferrerPolicyConfig} for additional configuration
+	 * @since 4.2
+	 * @see ReferrerPolicyHeaderWriter
+	 */
+	public ReferrerPolicyConfig referrerPolicy() {
+		this.referrerPolicy.writer = new ReferrerPolicyHeaderWriter();
+		return this.referrerPolicy;
+	}
+
+	/**
+	 * <p>
+	 * Allows configuration for <a href="https://www.w3.org/TR/referrer-policy/">Referrer
+	 * Policy</a>.
+	 * </p>
+	 *
+	 * <p>
+	 * Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support
+	 * the writing of the header as detailed in the W3C Technical Report:
+	 * </p>
+	 * <ul>
+	 * <li>Referrer-Policy</li>
+	 * </ul>
+	 * @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;
+	}
+
+	/**
+	 * <p>
+	 * Allows configuration for <a href="https://www.w3.org/TR/referrer-policy/">Referrer
+	 * Policy</a>.
+	 * </p>
+	 *
+	 * <p>
+	 * Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support
+	 * the writing of the header as detailed in the W3C Technical Report:
+	 * </p>
+	 * <ul>
+	 * <li>Referrer-Policy</li>
+	 * </ul>
+	 * @param referrerPolicyCustomizer the {@link Customizer} to provide more options for
+	 * the {@link ReferrerPolicyConfig}
+	 * @return the {@link HeadersConfigurer} for additional customizations
+	 * @see ReferrerPolicyHeaderWriter
+	 */
+	public HeadersConfigurer<H> referrerPolicy(Customizer<ReferrerPolicyConfig> referrerPolicyCustomizer) {
+		this.referrerPolicy.writer = new ReferrerPolicyHeaderWriter();
+		referrerPolicyCustomizer.customize(this.referrerPolicy);
+		return HeadersConfigurer.this;
+	}
+
+	/**
+	 * Allows configuration for <a href="https://wicg.github.io/feature-policy/">Feature
+	 * Policy</a>.
+	 * <p>
+	 * Calling this method automatically enables (includes) the {@code Feature-Policy}
+	 * header in the response using the supplied policy directive(s).
+	 * <p>
+	 * 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<H extends HttpSecurityBuilder<H>>
 
 	}
 
-	/**
-	 * <strong>Note this is not comprehensive XSS protection!</strong>
-	 *
-	 * <p>
-	 * Allows customizing the {@link XXssProtectionHeaderWriter} which adds the <a href=
-	 * "https://blogs.msdn.com/b/ieinternals/archive/2011/01/31/controlling-the-internet-explorer-xss-filter-with-the-x-xss-protection-http-header.aspx"
-	 * >X-XSS-Protection header</a>
-	 * </p>
-	 * @return the {@link XXssConfig} for additional customizations
-	 */
-	public XXssConfig xssProtection() {
-		return this.xssProtection.enable();
-	}
-
-	/**
-	 * <strong>Note this is not comprehensive XSS protection!</strong>
-	 *
-	 * <p>
-	 * Allows customizing the {@link XXssProtectionHeaderWriter} which adds the <a href=
-	 * "https://blogs.msdn.com/b/ieinternals/archive/2011/01/31/controlling-the-internet-explorer-xss-filter-with-the-x-xss-protection-http-header.aspx"
-	 * >X-XSS-Protection header</a>
-	 * </p>
-	 * @param xssCustomizer the {@link Customizer} to provide more options for the
-	 * {@link XXssConfig}
-	 * @return the {@link HeadersConfigurer} for additional customizations
-	 */
-	public HeadersConfigurer<H> xssProtection(Customizer<XXssConfig> xssCustomizer) {
-		xssCustomizer.customize(this.xssProtection.enable());
-		return HeadersConfigurer.this;
-	}
-
 	public final class XXssConfig {
 
 		private XXssProtectionHeaderWriter writer;
@@ -291,37 +611,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
 
 	}
 
-	/**
-	 * Allows customizing the {@link CacheControlHeadersWriter}. Specifically it adds the
-	 * following headers:
-	 * <ul>
-	 * <li>Cache-Control: no-cache, no-store, max-age=0, must-revalidate</li>
-	 * <li>Pragma: no-cache</li>
-	 * <li>Expires: 0</li>
-	 * </ul>
-	 * @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:
-	 * <ul>
-	 * <li>Cache-Control: no-cache, no-store, max-age=0, must-revalidate</li>
-	 * <li>Pragma: no-cache</li>
-	 * <li>Expires: 0</li>
-	 * </ul>
-	 * @param cacheControlCustomizer the {@link Customizer} to provide more options for
-	 * the {@link CacheControlConfig}
-	 * @return the {@link HeadersConfigurer} for additional customizations
-	 */
-	public HeadersConfigurer<H> cacheControl(Customizer<CacheControlConfig> cacheControlCustomizer) {
-		cacheControlCustomizer.customize(this.cacheControl.enable());
-		return HeadersConfigurer.this;
-	}
-
 	public final class CacheControlConfig {
 
 		private CacheControlHeadersWriter writer;
@@ -361,29 +650,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
 
 	}
 
-	/**
-	 * Allows customizing the {@link HstsHeaderWriter} which provides support for
-	 * <a href="https://tools.ietf.org/html/rfc6797">HTTP Strict Transport Security
-	 * (HSTS)</a>.
-	 * @return the {@link HstsConfig} for additional customizations
-	 */
-	public HstsConfig httpStrictTransportSecurity() {
-		return this.hsts.enable();
-	}
-
-	/**
-	 * Allows customizing the {@link HstsHeaderWriter} which provides support for
-	 * <a href="https://tools.ietf.org/html/rfc6797">HTTP Strict Transport Security
-	 * (HSTS)</a>.
-	 * @param hstsCustomizer the {@link Customizer} to provide more options for the
-	 * {@link HstsConfig}
-	 * @return the {@link HeadersConfigurer} for additional customizations
-	 */
-	public HeadersConfigurer<H> httpStrictTransportSecurity(Customizer<HstsConfig> hstsCustomizer) {
-		hstsCustomizer.customize(this.hsts.enable());
-		return HeadersConfigurer.this;
-	}
-
 	public final class HstsConfig {
 
 		private HstsHeaderWriter writer;
@@ -491,25 +757,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
 
 	}
 
-	/**
-	 * 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<H> frameOptions(Customizer<FrameOptionsConfig> frameOptionsCustomizer) {
-		frameOptionsCustomizer.customize(this.frameOptions.enable());
-		return HeadersConfigurer.this;
-	}
-
 	public final class FrameOptionsConfig {
 
 		private XFrameOptionsHeaderWriter writer;
@@ -571,29 +818,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
 
 	}
 
-	/**
-	 * Allows customizing the {@link HpkpHeaderWriter} which provides support for
-	 * <a href="https://tools.ietf.org/html/rfc7469">HTTP Public Key Pinning (HPKP)</a>.
-	 * @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
-	 * <a href="https://tools.ietf.org/html/rfc7469">HTTP Public Key Pinning (HPKP)</a>.
-	 * @param hpkpCustomizer the {@link Customizer} to provide more options for the
-	 * {@link HpkpConfig}
-	 * @return the {@link HeadersConfigurer} for additional customizations
-	 */
-	public HeadersConfigurer<H> httpPublicKeyPinning(Customizer<HpkpConfig> hpkpCustomizer) {
-		hpkpCustomizer.customize(this.hpkp.enable());
-		return HeadersConfigurer.this;
-	}
-
 	public final class HpkpConfig {
 
 		private HpkpHeaderWriter writer;
@@ -761,69 +985,6 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
 
 	}
 
-	/**
-	 * <p>
-	 * Allows configuration for <a href="https://www.w3.org/TR/CSP2/">Content Security
-	 * Policy (CSP) Level 2</a>.
-	 * </p>
-	 *
-	 * <p>
-	 * Calling this method automatically enables (includes) the Content-Security-Policy
-	 * header in the response using the supplied security policy directive(s).
-	 * </p>
-	 *
-	 * <p>
-	 * Configuration is provided to the {@link ContentSecurityPolicyHeaderWriter} which
-	 * supports the writing of the two headers as detailed in the W3C Candidate
-	 * Recommendation:
-	 * </p>
-	 * <ul>
-	 * <li>Content-Security-Policy</li>
-	 * <li>Content-Security-Policy-Report-Only</li>
-	 * </ul>
-	 * @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;
-	}
-
-	/**
-	 * <p>
-	 * Allows configuration for <a href="https://www.w3.org/TR/CSP2/">Content Security
-	 * Policy (CSP) Level 2</a>.
-	 * </p>
-	 *
-	 * <p>
-	 * Calling this method automatically enables (includes) the Content-Security-Policy
-	 * header in the response using the supplied security policy directive(s).
-	 * </p>
-	 *
-	 * <p>
-	 * Configuration is provided to the {@link ContentSecurityPolicyHeaderWriter} which
-	 * supports the writing of the two headers as detailed in the W3C Candidate
-	 * Recommendation:
-	 * </p>
-	 * <ul>
-	 * <li>Content-Security-Policy</li>
-	 * <li>Content-Security-Policy-Report-Only</li>
-	 * </ul>
-	 * @param contentSecurityCustomizer the {@link Customizer} to provide more options for
-	 * the {@link ContentSecurityPolicyConfig}
-	 * @return the {@link HeadersConfigurer} for additional customizations
-	 * @see ContentSecurityPolicyHeaderWriter
-	 */
-	public HeadersConfigurer<H> contentSecurityPolicy(
-			Customizer<ContentSecurityPolicyConfig> 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<H extends HttpSecurityBuilder<H>>
 
 	}
 
-	/**
-	 * 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:
-	 *
-	 * <pre>
-	 * http.headers().defaultsDisabled().cacheControl();
-	 * </pre>
-	 * @return the {@link HeadersConfigurer} for additional customization
-	 */
-	public HeadersConfigurer<H> 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<HeaderWriter> 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<HeaderWriter> getHeaderWriters() {
-		List<HeaderWriter> 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 <T> void addIfNotNull(List<T> values, T value) {
-		if (value != null) {
-			values.add(value);
-		}
-	}
-
-	/**
-	 * <p>
-	 * Allows configuration for <a href="https://www.w3.org/TR/referrer-policy/">Referrer
-	 * Policy</a>.
-	 * </p>
-	 *
-	 * <p>
-	 * Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support
-	 * the writing of the header as detailed in the W3C Technical Report:
-	 * </p>
-	 * <ul>
-	 * <li>Referrer-Policy</li>
-	 * </ul>
-	 *
-	 * <p>
-	 * Default value is:
-	 * </p>
-	 *
-	 * <pre>
-	 * Referrer-Policy: no-referrer
-	 * </pre>
-	 * @return the {@link ReferrerPolicyConfig} for additional configuration
-	 * @since 4.2
-	 * @see ReferrerPolicyHeaderWriter
-	 */
-	public ReferrerPolicyConfig referrerPolicy() {
-		this.referrerPolicy.writer = new ReferrerPolicyHeaderWriter();
-		return this.referrerPolicy;
-	}
-
-	/**
-	 * <p>
-	 * Allows configuration for <a href="https://www.w3.org/TR/referrer-policy/">Referrer
-	 * Policy</a>.
-	 * </p>
-	 *
-	 * <p>
-	 * Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support
-	 * the writing of the header as detailed in the W3C Technical Report:
-	 * </p>
-	 * <ul>
-	 * <li>Referrer-Policy</li>
-	 * </ul>
-	 * @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;
-	}
-
-	/**
-	 * <p>
-	 * Allows configuration for <a href="https://www.w3.org/TR/referrer-policy/">Referrer
-	 * Policy</a>.
-	 * </p>
-	 *
-	 * <p>
-	 * Configuration is provided to the {@link ReferrerPolicyHeaderWriter} which support
-	 * the writing of the header as detailed in the W3C Technical Report:
-	 * </p>
-	 * <ul>
-	 * <li>Referrer-Policy</li>
-	 * </ul>
-	 * @param referrerPolicyCustomizer the {@link Customizer} to provide more options for
-	 * the {@link ReferrerPolicyConfig}
-	 * @return the {@link HeadersConfigurer} for additional customizations
-	 * @see ReferrerPolicyHeaderWriter
-	 */
-	public HeadersConfigurer<H> referrerPolicy(Customizer<ReferrerPolicyConfig> 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<H extends HttpSecurityBuilder<H>>
 
 	}
 
-	/**
-	 * Allows configuration for <a href="https://wicg.github.io/feature-policy/">Feature
-	 * Policy</a>.
-	 * <p>
-	 * Calling this method automatically enables (includes) the {@code Feature-Policy}
-	 * header in the response using the supplied policy directive(s).
-	 * <p>
-	 * 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;

+ 138 - 138
config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java

@@ -311,144 +311,6 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
 		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<H> 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<H> 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<H> 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<H> 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<H> 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<H extends HttpSecurityBuilder<H>>
 		}
 	}
 
+	/**
+	 * 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<H> 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<H> 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<H> 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<H> 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<H> and() {
+			return SessionManagementConfigurer.this;
+		}
+
+		private ConcurrencyControlConfigurer() {
+		}
+
+	}
+
 }

+ 42 - 42
config/src/main/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurer.java

@@ -114,48 +114,6 @@ public final class UrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>>
 		return this;
 	}
 
-	public final class StandardInterceptUrlRegistry extends
-			ExpressionUrlAuthorizationConfigurer<H>.AbstractInterceptUrlRegistry<StandardInterceptUrlRegistry, AuthorizedUrl> {
-
-		/**
-		 * @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<RequestMatcher> 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<H extends HttpSecurityBuilder<H>>
 		return authorities;
 	}
 
+	public final class StandardInterceptUrlRegistry extends
+			ExpressionUrlAuthorizationConfigurer<H>.AbstractInterceptUrlRegistry<StandardInterceptUrlRegistry, AuthorizedUrl> {
+
+		/**
+		 * @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<RequestMatcher> 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)}

+ 10 - 10
config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurer.java

@@ -151,6 +151,16 @@ public final class OAuth2ClientConfigurer<B extends HttpSecurityBuilder<B>>
 		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<B extends HttpSecurityBuilder<B>>
 
 	}
 
-	@Override
-	public void init(B builder) {
-		this.authorizationCodeGrantConfigurer.init(builder);
-	}
-
-	@Override
-	public void configure(B builder) {
-		this.authorizationCodeGrantConfigurer.configure(builder);
-	}
-
 }

+ 211 - 211
config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java

@@ -221,69 +221,6 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
 		return this;
 	}
 
-	/**
-	 * Configuration options for the Authorization Server's Authorization Endpoint.
-	 */
-	public final class AuthorizationEndpointConfig {
-
-		private String authorizationRequestBaseUri;
-
-		private OAuth2AuthorizationRequestResolver authorizationRequestResolver;
-
-		private AuthorizationRequestRepository<OAuth2AuthorizationRequest> 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<OAuth2AuthorizationRequest> 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<B> and() {
-			return OAuth2LoginConfigurer.this;
-		}
-
-	}
-
 	/**
 	 * Returns the {@link TokenEndpointConfig} for configuring the Authorization Server's
 	 * Token Endpoint.
@@ -305,41 +242,6 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
 		return this;
 	}
 
-	/**
-	 * Configuration options for the Authorization Server's Token Endpoint.
-	 */
-	public final class TokenEndpointConfig {
-
-		private OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> 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<OAuth2AuthorizationCodeGrantRequest> 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<B> and() {
-			return OAuth2LoginConfigurer.this;
-		}
-
-	}
-
 	/**
 	 * Returns the {@link RedirectionEndpointConfig} for configuring the Client's
 	 * Redirection Endpoint.
@@ -361,38 +263,6 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
 		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<B> and() {
-			return OAuth2LoginConfigurer.this;
-		}
-
-	}
-
 	/**
 	 * Returns the {@link UserInfoEndpointConfig} for configuring the Authorization
 	 * Server's UserInfo Endpoint.
@@ -413,87 +283,6 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
 		return this;
 	}
 
-	/**
-	 * Configuration options for the Authorization Server's UserInfo Endpoint.
-	 */
-	public final class UserInfoEndpointConfig {
-
-		private OAuth2UserService<OAuth2UserRequest, OAuth2User> userService;
-
-		private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService;
-
-		private Map<String, Class<? extends OAuth2User>> 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<OAuth2UserRequest, OAuth2User> 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<OidcUserRequest, OidcUser> 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<? extends OAuth2User> 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<B> and() {
-			return OAuth2LoginConfigurer.this;
-		}
-
-	}
-
 	@Override
 	public void init(B http) throws Exception {
 		OAuth2LoginAuthenticationFilter authenticationFilter = new OAuth2LoginAuthenticationFilter(
@@ -740,6 +529,217 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
 		return loginEntryPoint;
 	}
 
+	/**
+	 * Configuration options for the Authorization Server's Authorization Endpoint.
+	 */
+	public final class AuthorizationEndpointConfig {
+
+		private String authorizationRequestBaseUri;
+
+		private OAuth2AuthorizationRequestResolver authorizationRequestResolver;
+
+		private AuthorizationRequestRepository<OAuth2AuthorizationRequest> 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<OAuth2AuthorizationRequest> 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<B> and() {
+			return OAuth2LoginConfigurer.this;
+		}
+
+	}
+
+	/**
+	 * Configuration options for the Authorization Server's Token Endpoint.
+	 */
+	public final class TokenEndpointConfig {
+
+		private OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> 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<OAuth2AuthorizationCodeGrantRequest> 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<B> 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<B> and() {
+			return OAuth2LoginConfigurer.this;
+		}
+
+	}
+
+	/**
+	 * Configuration options for the Authorization Server's UserInfo Endpoint.
+	 */
+	public final class UserInfoEndpointConfig {
+
+		private OAuth2UserService<OAuth2UserRequest, OAuth2User> userService;
+
+		private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService;
+
+		private Map<String, Class<? extends OAuth2User>> 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<OAuth2UserRequest, OAuth2User> 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<OidcUserRequest, OidcUser> 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<? extends OAuth2User> 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<B> and() {
+			return OAuth2LoginConfigurer.this;
+		}
+
+	}
+
 	private static class OidcAuthenticationRequestChecker implements AuthenticationProvider {
 
 		@Override

+ 64 - 64
config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java

@@ -277,6 +277,70 @@ public final class OAuth2ResourceServerConfigurer<H extends HttpSecurityBuilder<
 		}
 	}
 
+	private void registerDefaultAccessDeniedHandler(H http) {
+		ExceptionHandlingConfigurer<H> exceptionHandling = http.getConfigurer(ExceptionHandlingConfigurer.class);
+		if (exceptionHandling == null) {
+			return;
+		}
+
+		exceptionHandling.defaultAccessDeniedHandlerFor(this.accessDeniedHandler, this.requestMatcher);
+	}
+
+	private void registerDefaultEntryPoint(H http) {
+		ExceptionHandlingConfigurer<H> exceptionHandling = http.getConfigurer(ExceptionHandlingConfigurer.class);
+		if (exceptionHandling == null) {
+			return;
+		}
+
+		exceptionHandling.defaultAuthenticationEntryPointFor(this.authenticationEntryPoint, this.requestMatcher);
+	}
+
+	private void registerDefaultCsrfOverride(H http) {
+		CsrfConfigurer<H> 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<H extends HttpSecurityBuilder<
 
 	}
 
-	private void registerDefaultAccessDeniedHandler(H http) {
-		ExceptionHandlingConfigurer<H> exceptionHandling = http.getConfigurer(ExceptionHandlingConfigurer.class);
-		if (exceptionHandling == null) {
-			return;
-		}
-
-		exceptionHandling.defaultAccessDeniedHandlerFor(this.accessDeniedHandler, this.requestMatcher);
-	}
-
-	private void registerDefaultEntryPoint(H http) {
-		ExceptionHandlingConfigurer<H> exceptionHandling = http.getConfigurer(ExceptionHandlingConfigurer.class);
-		if (exceptionHandling == null) {
-			return;
-		}
-
-		exceptionHandling.defaultAuthenticationEntryPointFor(this.authenticationEntryPoint, this.requestMatcher);
-	}
-
-	private void registerDefaultCsrfOverride(H http) {
-		CsrfConfigurer<H> 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;

+ 23 - 23
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;

+ 19 - 19
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();
+		}
+
+	}
+
 }

文件差异内容过多而无法显示
+ 1590 - 1687
config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java


+ 52 - 52
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<Object> 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<Object> 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)

+ 21 - 21
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 {
 

+ 8 - 8
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 {
 

+ 7 - 7
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 {
 

+ 14 - 14
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 {
 

+ 7 - 7
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 {
 

+ 194 - 199
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<Object> 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<Class<?>> 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<Object> 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 {
 

+ 20 - 20
config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/EnableGlobalAuthenticationTests.java

@@ -45,25 +45,35 @@ public class EnableGlobalAuthenticationTests {
 		assertThat(auth.getAuthenticationManager()).isNotNull();
 	}
 
-	@Configuration
-	@EnableGlobalAuthentication
-	static class Config {
+	@Test
+	public void enableGlobalAuthenticationWhenNoConfigurationAnnotationThenBeanProxyingEnabled() {
+		this.spring.register(BeanProxyEnabledByDefaultConfig.class).autowire();
 
-		@Autowired
-		public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
-			auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
-		}
+		Child childBean = this.spring.getContext().getBean(Child.class);
+		Parent parentBean = this.spring.getContext().getBean(Parent.class);
 
+		assertThat(parentBean.getChild()).isSameAs(childBean);
 	}
 
 	@Test
-	public void enableGlobalAuthenticationWhenNoConfigurationAnnotationThenBeanProxyingEnabled() {
-		this.spring.register(BeanProxyEnabledByDefaultConfig.class).autowire();
+	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()).isSameAs(childBean);
+		assertThat(parentBean.getChild()).isNotSameAs(childBean);
+	}
+
+	@Configuration
+	@EnableGlobalAuthentication
+	static class Config {
+
+		@Autowired
+		public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
+			auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
+		}
+
 	}
 
 	@EnableGlobalAuthentication
@@ -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 {

+ 19 - 19
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 {
 

+ 197 - 198
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,6 +120,202 @@ public class GlobalMethodSecurityConfigurationTests {
 				.containsOnly((Class) AuthenticationFailureBadCredentialsEvent.class);
 	}
 
+	@Test
+	@WithMockUser
+	public void methodSecurityWhenAuthenticationTrustResolverIsBeanThenAutowires() {
+		this.spring.register(CustomTrustResolverConfig.class).autowire();
+
+		AuthenticationTrustResolver trustResolver = this.spring.getContext().getBean(AuthenticationTrustResolver.class);
+		when(trustResolver.isAnonymous(any())).thenReturn(true, false);
+
+		assertThatThrownBy(() -> this.service.preAuthorizeNotAnonymous()).isInstanceOf(AccessDeniedException.class);
+
+		this.service.preAuthorizeNotAnonymous();
+
+		verify(trustResolver, atLeastOnce()).isAnonymous(any());
+	}
+
+	// SEC-2301
+	@Test
+	@WithMockUser
+	public void defaultWebSecurityExpressionHandlerHasBeanResolverSet() {
+		this.spring.register(ExpressionHandlerHasBeanResolverSetConfig.class).autowire();
+		Authz authz = this.spring.getContext().getBean(Authz.class);
+
+		assertThatThrownBy(() -> this.service.preAuthorizeBean(false)).isInstanceOf(AccessDeniedException.class);
+
+		this.service.preAuthorizeBean(true);
+	}
+
+	@Test
+	@WithMockUser
+	public void methodSecuritySupportsAnnotaitonsOnInterfaceParamerNames() {
+		this.spring.register(MethodSecurityServiceConfig.class).autowire();
+
+		assertThatThrownBy(() -> this.service.postAnnotation("deny")).isInstanceOf(AccessDeniedException.class);
+
+		this.service.postAnnotation("grant");
+		// no exception
+	}
+
+	@Test
+	@WithMockUser
+	public void globalMethodSecurityConfigurationAutowiresPermissionEvaluator() {
+		this.spring.register(AutowirePermissionEvaluatorConfig.class).autowire();
+		PermissionEvaluator permission = this.spring.getContext().getBean(PermissionEvaluator.class);
+		when(permission.hasPermission(any(), eq("something"), eq("read"))).thenReturn(true, false);
+
+		this.service.hasPermission("something");
+		// no exception
+
+		assertThatThrownBy(() -> this.service.hasPermission("something")).isInstanceOf(AccessDeniedException.class);
+	}
+
+	@Test
+	public void multiPermissionEvaluatorConfig() {
+		this.spring.register(MultiPermissionEvaluatorConfig.class).autowire();
+
+		// no exception
+	}
+
+	// SEC-2425
+	@Test
+	@WithMockUser
+	public void enableGlobalMethodSecurityWorksOnSuperclass() {
+		this.spring.register(ChildConfig.class).autowire();
+
+		assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class);
+	}
+
+	// SEC-2479
+	@Test
+	@WithMockUser
+	public void supportAuthenticationManagerInParent() {
+		try (AnnotationConfigWebApplicationContext parent = new AnnotationConfigWebApplicationContext()) {
+			parent.register(Sec2479ParentConfig.class);
+			parent.refresh();
+			try (AnnotationConfigWebApplicationContext child = new AnnotationConfigWebApplicationContext()) {
+				child.setParent(parent);
+				child.register(Sec2479ChildConfig.class);
+				child.refresh();
+				this.spring.context(child).autowire();
+
+				assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class);
+			}
+		}
+	}
+
+	@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 {
 
@@ -143,7 +323,7 @@ public class GlobalMethodSecurityConfigurationTests {
 		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
 			// @formatter:off
 			auth
-				.inMemoryAuthentication();
+			.inMemoryAuthentication();
 			// @formatter:on
 		}
 
@@ -155,21 +335,6 @@ public class GlobalMethodSecurityConfigurationTests {
 
 	}
 
-	@Test
-	@WithMockUser
-	public void methodSecurityWhenAuthenticationTrustResolverIsBeanThenAutowires() {
-		this.spring.register(CustomTrustResolverConfig.class).autowire();
-
-		AuthenticationTrustResolver trustResolver = this.spring.getContext().getBean(AuthenticationTrustResolver.class);
-		when(trustResolver.isAnonymous(any())).thenReturn(true, false);
-
-		assertThatThrownBy(() -> this.service.preAuthorizeNotAnonymous()).isInstanceOf(AccessDeniedException.class);
-
-		this.service.preAuthorizeNotAnonymous();
-
-		verify(trustResolver, atLeastOnce()).isAnonymous(any());
-	}
-
 	@EnableGlobalMethodSecurity(prePostEnabled = true)
 	static class CustomTrustResolverConfig {
 
@@ -185,18 +350,6 @@ public class GlobalMethodSecurityConfigurationTests {
 
 	}
 
-	// SEC-2301
-	@Test
-	@WithMockUser
-	public void defaultWebSecurityExpressionHandlerHasBeanResolverSet() {
-		this.spring.register(ExpressionHandlerHasBeanResolverSetConfig.class).autowire();
-		Authz authz = this.spring.getContext().getBean(Authz.class);
-
-		assertThatThrownBy(() -> this.service.preAuthorizeBean(false)).isInstanceOf(AccessDeniedException.class);
-
-		this.service.preAuthorizeBean(true);
-	}
-
 	@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
 	static class ExpressionHandlerHasBeanResolverSetConfig {
 
@@ -212,17 +365,6 @@ public class GlobalMethodSecurityConfigurationTests {
 
 	}
 
-	@Test
-	@WithMockUser
-	public void methodSecuritySupportsAnnotaitonsOnInterfaceParamerNames() {
-		this.spring.register(MethodSecurityServiceConfig.class).autowire();
-
-		assertThatThrownBy(() -> this.service.postAnnotation("deny")).isInstanceOf(AccessDeniedException.class);
-
-		this.service.postAnnotation("grant");
-		// no exception
-	}
-
 	@EnableGlobalMethodSecurity(prePostEnabled = true)
 	static class MethodSecurityServiceConfig {
 
@@ -233,19 +375,6 @@ public class GlobalMethodSecurityConfigurationTests {
 
 	}
 
-	@Test
-	@WithMockUser
-	public void globalMethodSecurityConfigurationAutowiresPermissionEvaluator() {
-		this.spring.register(AutowirePermissionEvaluatorConfig.class).autowire();
-		PermissionEvaluator permission = this.spring.getContext().getBean(PermissionEvaluator.class);
-		when(permission.hasPermission(any(), eq("something"), eq("read"))).thenReturn(true, false);
-
-		this.service.hasPermission("something");
-		// no exception
-
-		assertThatThrownBy(() -> this.service.hasPermission("something")).isInstanceOf(AccessDeniedException.class);
-	}
-
 	@EnableGlobalMethodSecurity(prePostEnabled = true)
 	public static class AutowirePermissionEvaluatorConfig {
 
@@ -261,13 +390,6 @@ public class GlobalMethodSecurityConfigurationTests {
 
 	}
 
-	@Test
-	public void multiPermissionEvaluatorConfig() {
-		this.spring.register(MultiPermissionEvaluatorConfig.class).autowire();
-
-		// no exception
-	}
-
 	@EnableGlobalMethodSecurity(prePostEnabled = true)
 	public static class MultiPermissionEvaluatorConfig {
 
@@ -283,15 +405,6 @@ public class GlobalMethodSecurityConfigurationTests {
 
 	}
 
-	// SEC-2425
-	@Test
-	@WithMockUser
-	public void enableGlobalMethodSecurityWorksOnSuperclass() {
-		this.spring.register(ChildConfig.class).autowire();
-
-		assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class);
-	}
-
 	@Configuration
 	static class ChildConfig extends ParentConfig {
 
@@ -307,24 +420,6 @@ public class GlobalMethodSecurityConfigurationTests {
 
 	}
 
-	// SEC-2479
-	@Test
-	@WithMockUser
-	public void supportAuthenticationManagerInParent() {
-		try (AnnotationConfigWebApplicationContext parent = new AnnotationConfigWebApplicationContext()) {
-			parent.register(Sec2479ParentConfig.class);
-			parent.refresh();
-			try (AnnotationConfigWebApplicationContext child = new AnnotationConfigWebApplicationContext()) {
-				child.setParent(parent);
-				child.register(Sec2479ChildConfig.class);
-				child.refresh();
-				this.spring.context(child).autowire();
-
-				assertThatThrownBy(() -> this.service.preAuthorize()).isInstanceOf(AccessDeniedException.class);
-			}
-		}
-	}
-
 	@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 {

+ 198 - 222
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 {

+ 11 - 11
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 {
 

+ 10 - 10
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 {
 

+ 12 - 12
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 {

+ 33 - 33
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();
-	}
-
 }

+ 100 - 100
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);
+	}
+
 	/**
 	 * <pre>
 	 *   &lt;http&gt;
@@ -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("/");
-	}
-
 	/**
 	 * <pre>
 	 *   &lt;http security="none" pattern="/resources/**"/&gt;
@@ -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);
-	}
-
 	/**
 	 * <code>
 	 *   &lt;http security="none" pattern="/resources/**"/&gt;

+ 21 - 21
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<CallableProcessingInterceptor> 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<CallableProcessingInterceptor> 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 {
 

+ 129 - 129
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<AuthenticationSuccessEvent> {
@@ -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 {
 

+ 22 - 22
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 {
 

+ 206 - 206
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 {
 

+ 44 - 44
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);
-	}
-
 }

+ 42 - 42
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 {

+ 30 - 30
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<String> 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<String> 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 {
 

+ 83 - 83
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";
+			}
+
+		}
+
 	}
 
 }

+ 23 - 24
config/src/test/java/org/springframework/security/config/annotation/web/configuration/Sec2515Tests.java

@@ -45,6 +45,29 @@ public class Sec2515Tests {
 		this.spring.register(StackOverflowSecurityConfig.class).autowire();
 	}
 
+	@Test(expected = FatalBeanException.class)
+	public void loadConfigWhenAuthenticationManagerNotConfiguredAndRegisterBeanCustomNameThenThrowFatalBeanException() {
+		this.spring.register(CustomBeanNameStackOverflowSecurityConfig.class).autowire();
+	}
+
+	// SEC-2549
+	@Test
+	public void loadConfigWhenChildClassLoaderSetThenContextLoads() {
+		CanLoadWithChildConfig.AUTHENTICATION_MANAGER = mock(AuthenticationManager.class);
+		this.spring.register(CanLoadWithChildConfig.class);
+		AnnotationConfigWebApplicationContext context = (AnnotationConfigWebApplicationContext) this.spring
+				.getContext();
+		context.setClassLoader(new URLClassLoader(new URL[0], context.getClassLoader()));
+		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 {
 
@@ -56,11 +79,6 @@ public class Sec2515Tests {
 
 	}
 
-	@Test(expected = FatalBeanException.class)
-	public void loadConfigWhenAuthenticationManagerNotConfiguredAndRegisterBeanCustomNameThenThrowFatalBeanException() {
-		this.spring.register(CustomBeanNameStackOverflowSecurityConfig.class).autowire();
-	}
-
 	@EnableWebSecurity
 	static class CustomBeanNameStackOverflowSecurityConfig extends WebSecurityConfigurerAdapter {
 
@@ -72,19 +90,6 @@ public class Sec2515Tests {
 
 	}
 
-	// SEC-2549
-	@Test
-	public void loadConfigWhenChildClassLoaderSetThenContextLoads() {
-		CanLoadWithChildConfig.AUTHENTICATION_MANAGER = mock(AuthenticationManager.class);
-		this.spring.register(CanLoadWithChildConfig.class);
-		AnnotationConfigWebApplicationContext context = (AnnotationConfigWebApplicationContext) this.spring
-				.getContext();
-		context.setClassLoader(new URLClassLoader(new URL[0], context.getClassLoader()));
-		this.spring.autowire();
-
-		assertThat(this.spring.getContext().getBean(AuthenticationManager.class)).isNotNull();
-	}
-
 	@EnableWebSecurity
 	static class CanLoadWithChildConfig extends WebSecurityConfigurerAdapter {
 
@@ -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 {
 

+ 186 - 186
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<SecurityFilterChain> 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<SecurityFilterChain> 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<SecurityFilterChain> 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<SecurityFilterChain> 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();
-		}
-
 	}
 
 }

+ 21 - 21
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 {
 

+ 265 - 265
config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeRequestsTests.java

@@ -99,6 +99,268 @@ public class AuthorizeRequestsTests {
 		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
 	}
 
+	@Test
+	public void postWhenPostDenyAllInLambdaThenRespondsWithForbidden() throws Exception {
+		loadConfig(AntMatchersNoPatternsInLambdaConfig.class);
+		this.request.setMethod("POST");
+
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
+	}
+
+	// SEC-2256
+	@Test
+	public void antMatchersPathVariables() throws Exception {
+		loadConfig(AntPatchersPathVariables.class);
+
+		this.request.setServletPath("/user/user");
+
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
+
+		this.setup();
+		this.request.setServletPath("/user/deny");
+
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
+	}
+
+	// SEC-2256
+	@Test
+	public void antMatchersPathVariablesCaseInsensitive() throws Exception {
+		loadConfig(AntPatchersPathVariables.class);
+
+		this.request.setServletPath("/USER/user");
+
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
+
+		this.setup();
+		this.request.setServletPath("/USER/deny");
+
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
+	}
+
+	// gh-3786
+	@Test
+	public void antMatchersPathVariablesCaseInsensitiveCamelCaseVariables() throws Exception {
+		loadConfig(AntMatchersPathVariablesCamelCaseVariables.class);
+
+		this.request.setServletPath("/USER/user");
+
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
+
+		this.setup();
+		this.request.setServletPath("/USER/deny");
+
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
+	}
+
+	// gh-3394
+	@Test
+	public void roleHiearchy() throws Exception {
+		loadConfig(RoleHiearchyConfig.class);
+
+		SecurityContext securityContext = new SecurityContextImpl();
+		securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("test", "notused",
+				AuthorityUtils.createAuthorityList("ROLE_USER")));
+		this.request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,
+				securityContext);
+
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
+	}
+
+	@Test
+	public void mvcMatcher() throws Exception {
+		loadConfig(MvcMatcherConfig.class, LegacyMvcMatchingConfig.class);
+
+		this.request.setRequestURI("/path");
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
+
+		setup();
+
+		this.request.setRequestURI("/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 requestWhenMvcMatcherDenyAllThenRespondsWithUnauthorized() throws Exception {
+		loadConfig(MvcMatcherInLambdaConfig.class, LegacyMvcMatchingConfig.class);
+
+		this.request.setRequestURI("/path");
+		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+
+		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
+
+		setup();
+
+		this.request.setRequestURI("/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 requestWhenMvcMatcherServletPathDenyAllThenMatchesOnServletPath() throws Exception {
+		loadConfig(MvcMatcherServletPathInLambdaConfig.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);
+	}
+
+	@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 {
@@ -116,20 +378,10 @@ public class AuthorizeRequestsTests {
 		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
 			// @formatter:off
 			auth
-				.inMemoryAuthentication();
-			// @formatter:on
-		}
-
-	}
-
-	@Test
-	public void postWhenPostDenyAllInLambdaThenRespondsWithForbidden() throws Exception {
-		loadConfig(AntMatchersNoPatternsInLambdaConfig.class);
-		this.request.setMethod("POST");
-
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
+				.inMemoryAuthentication();
+			// @formatter:on
+		}
 
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
 	}
 
 	@EnableWebSecurity
@@ -157,44 +409,6 @@ public class AuthorizeRequestsTests {
 
 	}
 
-	// SEC-2256
-	@Test
-	public void antMatchersPathVariables() throws Exception {
-		loadConfig(AntPatchersPathVariables.class);
-
-		this.request.setServletPath("/user/user");
-
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
-
-		this.setup();
-		this.request.setServletPath("/user/deny");
-
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
-	}
-
-	// SEC-2256
-	@Test
-	public void antMatchersPathVariablesCaseInsensitive() throws Exception {
-		loadConfig(AntPatchersPathVariables.class);
-
-		this.request.setServletPath("/USER/user");
-
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
-
-		this.setup();
-		this.request.setServletPath("/USER/deny");
-
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
-	}
-
 	@EnableWebSecurity
 	@Configuration
 	static class AntPatchersPathVariables extends WebSecurityConfigurerAdapter {
@@ -219,25 +433,6 @@ public class AuthorizeRequestsTests {
 
 	}
 
-	// gh-3786
-	@Test
-	public void antMatchersPathVariablesCaseInsensitiveCamelCaseVariables() throws Exception {
-		loadConfig(AntMatchersPathVariablesCamelCaseVariables.class);
-
-		this.request.setServletPath("/USER/user");
-
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
-
-		this.setup();
-		this.request.setServletPath("/USER/deny");
-
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
-	}
-
 	@EnableWebSecurity
 	@Configuration
 	static class AntMatchersPathVariablesCamelCaseVariables extends WebSecurityConfigurerAdapter {
@@ -262,22 +457,6 @@ public class AuthorizeRequestsTests {
 
 	}
 
-	// gh-3394
-	@Test
-	public void roleHiearchy() throws Exception {
-		loadConfig(RoleHiearchyConfig.class);
-
-		SecurityContext securityContext = new SecurityContextImpl();
-		securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("test", "notused",
-				AuthorityUtils.createAuthorityList("ROLE_USER")));
-		this.request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,
-				securityContext);
-
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
-	}
-
 	@EnableWebSecurity
 	@Configuration
 	static class RoleHiearchyConfig extends WebSecurityConfigurerAdapter {
@@ -308,30 +487,6 @@ public class AuthorizeRequestsTests {
 
 	}
 
-	@Test
-	public void mvcMatcher() throws Exception {
-		loadConfig(MvcMatcherConfig.class, LegacyMvcMatchingConfig.class);
-
-		this.request.setRequestURI("/path");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
-
-		setup();
-
-		this.request.setRequestURI("/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
@@ -367,30 +522,6 @@ public class AuthorizeRequestsTests {
 
 	}
 
-	@Test
-	public void requestWhenMvcMatcherDenyAllThenRespondsWithUnauthorized() throws Exception {
-		loadConfig(MvcMatcherInLambdaConfig.class, LegacyMvcMatchingConfig.class);
-
-		this.request.setRequestURI("/path");
-		this.springSecurityFilterChain.doFilter(this.request, this.response, this.chain);
-
-		assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_UNAUTHORIZED);
-
-		setup();
-
-		this.request.setRequestURI("/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
@@ -428,49 +559,6 @@ public class AuthorizeRequestsTests {
 
 	}
 
-	@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
@@ -506,49 +594,6 @@ public class AuthorizeRequestsTests {
 
 	}
 
-	@Test
-	public void requestWhenMvcMatcherServletPathDenyAllThenMatchesOnServletPath() throws Exception {
-		loadConfig(MvcMatcherServletPathInLambdaConfig.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
@@ -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);
-	}
-
 }

+ 14 - 14
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 {
 

+ 118 - 118
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 {
 

+ 34 - 34
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 {
 

+ 7 - 7
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;
-	}
-
 }

+ 232 - 232
config/src/test/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerTests.java

@@ -179,6 +179,238 @@ public class CsrfConfigurerTests {
 		assertThat(this.spring.getContext().getBean(RequestDataValueProcessor.class)).isNotNull();
 	}
 
+	@Test
+	public void postWhenCsrfDisabledThenRespondsWithOk() throws Exception {
+		this.spring.register(DisableCsrfConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(post("/")).andExpect(status().isOk());
+	}
+
+	@Test
+	public void postWhenCsrfDisabledInLambdaThenRespondsWithOk() throws Exception {
+		this.spring.register(DisableCsrfInLambdaConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(post("/")).andExpect(status().isOk());
+	}
+
+	// SEC-2498
+	@Test
+	public void loginWhenCsrfDisabledThenRedirectsToPreviousPostRequest() throws Exception {
+		this.spring.register(DisableCsrfEnablesRequestCacheConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(post("/to-save")).andReturn();
+
+		this.mvc.perform(post("/login").param("username", "user").param("password", "password")
+				.session((MockHttpSession) mvcResult.getRequest().getSession())).andExpect(status().isFound())
+				.andExpect(redirectedUrl("http://localhost/to-save"));
+	}
+
+	@Test
+	public void loginWhenCsrfEnabledThenDoesNotRedirectToPreviousPostRequest() throws Exception {
+		CsrfDisablesPostRequestFromRequestCacheConfig.REPO = mock(CsrfTokenRepository.class);
+		DefaultCsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "token");
+		when(CsrfDisablesPostRequestFromRequestCacheConfig.REPO.loadToken(any())).thenReturn(csrfToken);
+		when(CsrfDisablesPostRequestFromRequestCacheConfig.REPO.generateToken(any())).thenReturn(csrfToken);
+		this.spring.register(CsrfDisablesPostRequestFromRequestCacheConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(post("/some-url")).andReturn();
+		this.mvc.perform(post("/login").param("username", "user").param("password", "password").with(csrf())
+				.session((MockHttpSession) mvcResult.getRequest().getSession())).andExpect(status().isFound())
+				.andExpect(redirectedUrl("/"));
+
+		verify(CsrfDisablesPostRequestFromRequestCacheConfig.REPO, atLeastOnce())
+				.loadToken(any(HttpServletRequest.class));
+	}
+
+	@Test
+	public void loginWhenCsrfEnabledThenRedirectsToPreviousGetRequest() throws Exception {
+		CsrfDisablesPostRequestFromRequestCacheConfig.REPO = mock(CsrfTokenRepository.class);
+		DefaultCsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "token");
+		when(CsrfDisablesPostRequestFromRequestCacheConfig.REPO.loadToken(any())).thenReturn(csrfToken);
+		when(CsrfDisablesPostRequestFromRequestCacheConfig.REPO.generateToken(any())).thenReturn(csrfToken);
+		this.spring.register(CsrfDisablesPostRequestFromRequestCacheConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/some-url")).andReturn();
+		this.mvc.perform(post("/login").param("username", "user").param("password", "password").with(csrf())
+				.session((MockHttpSession) mvcResult.getRequest().getSession())).andExpect(status().isFound())
+				.andExpect(redirectedUrl("http://localhost/some-url"));
+
+		verify(CsrfDisablesPostRequestFromRequestCacheConfig.REPO, atLeastOnce())
+				.loadToken(any(HttpServletRequest.class));
+	}
+
+	// SEC-2422
+	@Test
+	public void postWhenCsrfEnabledAndSessionIsExpiredThenRespondsWithForbidden() throws Exception {
+		this.spring.register(InvalidSessionUrlConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(post("/").param("_csrf", "abc")).andExpect(status().isFound())
+				.andExpect(redirectedUrl("/error/sessionError")).andReturn();
+
+		this.mvc.perform(post("/").session((MockHttpSession) mvcResult.getRequest().getSession()))
+				.andExpect(status().isForbidden());
+	}
+
+	@Test
+	public void requireCsrfProtectionMatcherWhenRequestDoesNotMatchThenRespondsWithOk() throws Exception {
+		this.spring.register(RequireCsrfProtectionMatcherConfig.class, BasicController.class).autowire();
+		when(RequireCsrfProtectionMatcherConfig.MATCHER.matches(any())).thenReturn(false);
+
+		this.mvc.perform(get("/")).andExpect(status().isOk());
+	}
+
+	@Test
+	public void requireCsrfProtectionMatcherWhenRequestMatchesThenRespondsWithForbidden() throws Exception {
+		RequireCsrfProtectionMatcherConfig.MATCHER = mock(RequestMatcher.class);
+		when(RequireCsrfProtectionMatcherConfig.MATCHER.matches(any())).thenReturn(true);
+		this.spring.register(RequireCsrfProtectionMatcherConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(status().isForbidden());
+	}
+
+	@Test
+	public void requireCsrfProtectionMatcherInLambdaWhenRequestDoesNotMatchThenRespondsWithOk() throws Exception {
+		RequireCsrfProtectionMatcherInLambdaConfig.MATCHER = mock(RequestMatcher.class);
+		this.spring.register(RequireCsrfProtectionMatcherInLambdaConfig.class, BasicController.class).autowire();
+		when(RequireCsrfProtectionMatcherInLambdaConfig.MATCHER.matches(any())).thenReturn(false);
+
+		this.mvc.perform(get("/")).andExpect(status().isOk());
+	}
+
+	@Test
+	public void requireCsrfProtectionMatcherInLambdaWhenRequestMatchesThenRespondsWithForbidden() throws Exception {
+		RequireCsrfProtectionMatcherInLambdaConfig.MATCHER = mock(RequestMatcher.class);
+		when(RequireCsrfProtectionMatcherInLambdaConfig.MATCHER.matches(any())).thenReturn(true);
+		this.spring.register(RequireCsrfProtectionMatcherInLambdaConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(status().isForbidden());
+	}
+
+	@Test
+	public void getWhenCustomCsrfTokenRepositoryThenRepositoryIsUsed() throws Exception {
+		CsrfTokenRepositoryConfig.REPO = mock(CsrfTokenRepository.class);
+		when(CsrfTokenRepositoryConfig.REPO.loadToken(any()))
+				.thenReturn(new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "token"));
+		this.spring.register(CsrfTokenRepositoryConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(status().isOk());
+		verify(CsrfTokenRepositoryConfig.REPO).loadToken(any(HttpServletRequest.class));
+	}
+
+	@Test
+	public void logoutWhenCustomCsrfTokenRepositoryThenCsrfTokenIsCleared() throws Exception {
+		CsrfTokenRepositoryConfig.REPO = mock(CsrfTokenRepository.class);
+		this.spring.register(CsrfTokenRepositoryConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(post("/logout").with(csrf()).with(user("user")));
+
+		verify(CsrfTokenRepositoryConfig.REPO).saveToken(isNull(), any(HttpServletRequest.class),
+				any(HttpServletResponse.class));
+	}
+
+	@Test
+	public void loginWhenCustomCsrfTokenRepositoryThenCsrfTokenIsCleared() throws Exception {
+		CsrfTokenRepositoryConfig.REPO = mock(CsrfTokenRepository.class);
+		DefaultCsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "token");
+		when(CsrfTokenRepositoryConfig.REPO.loadToken(any())).thenReturn(csrfToken);
+		when(CsrfTokenRepositoryConfig.REPO.generateToken(any())).thenReturn(csrfToken);
+		this.spring.register(CsrfTokenRepositoryConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"))
+				.andExpect(redirectedUrl("/"));
+
+		verify(CsrfTokenRepositoryConfig.REPO).saveToken(isNull(), any(HttpServletRequest.class),
+				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 {
 
@@ -200,13 +432,6 @@ public class CsrfConfigurerTests {
 
 	}
 
-	@Test
-	public void postWhenCsrfDisabledThenRespondsWithOk() throws Exception {
-		this.spring.register(DisableCsrfConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(post("/")).andExpect(status().isOk());
-	}
-
 	@EnableWebSecurity
 	static class DisableCsrfConfig extends WebSecurityConfigurerAdapter {
 
@@ -221,13 +446,6 @@ public class CsrfConfigurerTests {
 
 	}
 
-	@Test
-	public void postWhenCsrfDisabledInLambdaThenRespondsWithOk() throws Exception {
-		this.spring.register(DisableCsrfInLambdaConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(post("/")).andExpect(status().isOk());
-	}
-
 	@EnableWebSecurity
 	static class DisableCsrfInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -241,18 +459,6 @@ public class CsrfConfigurerTests {
 
 	}
 
-	// SEC-2498
-	@Test
-	public void loginWhenCsrfDisabledThenRedirectsToPreviousPostRequest() throws Exception {
-		this.spring.register(DisableCsrfEnablesRequestCacheConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(post("/to-save")).andReturn();
-
-		this.mvc.perform(post("/login").param("username", "user").param("password", "password")
-				.session((MockHttpSession) mvcResult.getRequest().getSession())).andExpect(status().isFound())
-				.andExpect(redirectedUrl("http://localhost/to-save"));
-	}
-
 	@EnableWebSecurity
 	static class DisableCsrfEnablesRequestCacheConfig extends WebSecurityConfigurerAdapter {
 
@@ -281,40 +487,6 @@ public class CsrfConfigurerTests {
 
 	}
 
-	@Test
-	public void loginWhenCsrfEnabledThenDoesNotRedirectToPreviousPostRequest() throws Exception {
-		CsrfDisablesPostRequestFromRequestCacheConfig.REPO = mock(CsrfTokenRepository.class);
-		DefaultCsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "token");
-		when(CsrfDisablesPostRequestFromRequestCacheConfig.REPO.loadToken(any())).thenReturn(csrfToken);
-		when(CsrfDisablesPostRequestFromRequestCacheConfig.REPO.generateToken(any())).thenReturn(csrfToken);
-		this.spring.register(CsrfDisablesPostRequestFromRequestCacheConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(post("/some-url")).andReturn();
-		this.mvc.perform(post("/login").param("username", "user").param("password", "password").with(csrf())
-				.session((MockHttpSession) mvcResult.getRequest().getSession())).andExpect(status().isFound())
-				.andExpect(redirectedUrl("/"));
-
-		verify(CsrfDisablesPostRequestFromRequestCacheConfig.REPO, atLeastOnce())
-				.loadToken(any(HttpServletRequest.class));
-	}
-
-	@Test
-	public void loginWhenCsrfEnabledThenRedirectsToPreviousGetRequest() throws Exception {
-		CsrfDisablesPostRequestFromRequestCacheConfig.REPO = mock(CsrfTokenRepository.class);
-		DefaultCsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "token");
-		when(CsrfDisablesPostRequestFromRequestCacheConfig.REPO.loadToken(any())).thenReturn(csrfToken);
-		when(CsrfDisablesPostRequestFromRequestCacheConfig.REPO.generateToken(any())).thenReturn(csrfToken);
-		this.spring.register(CsrfDisablesPostRequestFromRequestCacheConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/some-url")).andReturn();
-		this.mvc.perform(post("/login").param("username", "user").param("password", "password").with(csrf())
-				.session((MockHttpSession) mvcResult.getRequest().getSession())).andExpect(status().isFound())
-				.andExpect(redirectedUrl("http://localhost/some-url"));
-
-		verify(CsrfDisablesPostRequestFromRequestCacheConfig.REPO, atLeastOnce())
-				.loadToken(any(HttpServletRequest.class));
-	}
-
 	@EnableWebSecurity
 	static class CsrfDisablesPostRequestFromRequestCacheConfig extends WebSecurityConfigurerAdapter {
 
@@ -345,18 +517,6 @@ public class CsrfConfigurerTests {
 
 	}
 
-	// SEC-2422
-	@Test
-	public void postWhenCsrfEnabledAndSessionIsExpiredThenRespondsWithForbidden() throws Exception {
-		this.spring.register(InvalidSessionUrlConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(post("/").param("_csrf", "abc")).andExpect(status().isFound())
-				.andExpect(redirectedUrl("/error/sessionError")).andReturn();
-
-		this.mvc.perform(post("/").session((MockHttpSession) mvcResult.getRequest().getSession()))
-				.andExpect(status().isForbidden());
-	}
-
 	@EnableWebSecurity
 	static class InvalidSessionUrlConfig extends WebSecurityConfigurerAdapter {
 
@@ -373,23 +533,6 @@ public class CsrfConfigurerTests {
 
 	}
 
-	@Test
-	public void requireCsrfProtectionMatcherWhenRequestDoesNotMatchThenRespondsWithOk() throws Exception {
-		this.spring.register(RequireCsrfProtectionMatcherConfig.class, BasicController.class).autowire();
-		when(RequireCsrfProtectionMatcherConfig.MATCHER.matches(any())).thenReturn(false);
-
-		this.mvc.perform(get("/")).andExpect(status().isOk());
-	}
-
-	@Test
-	public void requireCsrfProtectionMatcherWhenRequestMatchesThenRespondsWithForbidden() throws Exception {
-		RequireCsrfProtectionMatcherConfig.MATCHER = mock(RequestMatcher.class);
-		when(RequireCsrfProtectionMatcherConfig.MATCHER.matches(any())).thenReturn(true);
-		this.spring.register(RequireCsrfProtectionMatcherConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(status().isForbidden());
-	}
-
 	@EnableWebSecurity
 	static class RequireCsrfProtectionMatcherConfig extends WebSecurityConfigurerAdapter {
 
@@ -406,24 +549,6 @@ public class CsrfConfigurerTests {
 
 	}
 
-	@Test
-	public void requireCsrfProtectionMatcherInLambdaWhenRequestDoesNotMatchThenRespondsWithOk() throws Exception {
-		RequireCsrfProtectionMatcherInLambdaConfig.MATCHER = mock(RequestMatcher.class);
-		this.spring.register(RequireCsrfProtectionMatcherInLambdaConfig.class, BasicController.class).autowire();
-		when(RequireCsrfProtectionMatcherInLambdaConfig.MATCHER.matches(any())).thenReturn(false);
-
-		this.mvc.perform(get("/")).andExpect(status().isOk());
-	}
-
-	@Test
-	public void requireCsrfProtectionMatcherInLambdaWhenRequestMatchesThenRespondsWithForbidden() throws Exception {
-		RequireCsrfProtectionMatcherInLambdaConfig.MATCHER = mock(RequestMatcher.class);
-		when(RequireCsrfProtectionMatcherInLambdaConfig.MATCHER.matches(any())).thenReturn(true);
-		this.spring.register(RequireCsrfProtectionMatcherInLambdaConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(status().isForbidden());
-	}
-
 	@EnableWebSecurity
 	static class RequireCsrfProtectionMatcherInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -439,43 +564,6 @@ public class CsrfConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenCustomCsrfTokenRepositoryThenRepositoryIsUsed() throws Exception {
-		CsrfTokenRepositoryConfig.REPO = mock(CsrfTokenRepository.class);
-		when(CsrfTokenRepositoryConfig.REPO.loadToken(any()))
-				.thenReturn(new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "token"));
-		this.spring.register(CsrfTokenRepositoryConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(status().isOk());
-		verify(CsrfTokenRepositoryConfig.REPO).loadToken(any(HttpServletRequest.class));
-	}
-
-	@Test
-	public void logoutWhenCustomCsrfTokenRepositoryThenCsrfTokenIsCleared() throws Exception {
-		CsrfTokenRepositoryConfig.REPO = mock(CsrfTokenRepository.class);
-		this.spring.register(CsrfTokenRepositoryConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(post("/logout").with(csrf()).with(user("user")));
-
-		verify(CsrfTokenRepositoryConfig.REPO).saveToken(isNull(), any(HttpServletRequest.class),
-				any(HttpServletResponse.class));
-	}
-
-	@Test
-	public void loginWhenCustomCsrfTokenRepositoryThenCsrfTokenIsCleared() throws Exception {
-		CsrfTokenRepositoryConfig.REPO = mock(CsrfTokenRepository.class);
-		DefaultCsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "token");
-		when(CsrfTokenRepositoryConfig.REPO.loadToken(any())).thenReturn(csrfToken);
-		when(CsrfTokenRepositoryConfig.REPO.generateToken(any())).thenReturn(csrfToken);
-		this.spring.register(CsrfTokenRepositoryConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"))
-				.andExpect(redirectedUrl("/"));
-
-		verify(CsrfTokenRepositoryConfig.REPO).saveToken(isNull(), any(HttpServletRequest.class),
-				any(HttpServletResponse.class));
-	}
-
 	@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 {
 

+ 54 - 54
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 {
 

+ 135 - 135
config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurerTests.java

@@ -176,31 +176,6 @@ public class DefaultLoginPageConfigurerTests {
 						+ "      </form>\n" + "</div>\n" + "</body></html>"));
 	}
 
-	@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 {
 						+ "      </form>\n" + "</div>\n" + "</body></html>"));
 	}
 
-	@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 {
 						+ "      </form>\n" + "</div>\n" + "</body></html>"));
 	}
 
-	@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,8 +286,51 @@ public class DefaultLoginPageConfigurerTests {
 						+ "      </form>\n" + "</div>\n" + "</body></html>"));
 	}
 
+	@Test
+	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnDefaultLoginPageGeneratingFilter() {
+		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
+		this.spring.register(ObjectPostProcessorConfig.class).autowire();
+
+		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(DefaultLoginPageGeneratingFilter.class));
+	}
+
+	@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));
+	}
+
+	@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 DefaultLoginPageWithFormLoginOpenIDRememberMeConfig extends WebSecurityConfigurerAdapter {
+	static class DefaultLoginPageConfig extends WebSecurityConfigurerAdapter {
 
 		@Override
 		protected void configure(HttpSecurity http) throws Exception {
@@ -393,76 +339,130 @@ public class DefaultLoginPageConfigurerTests {
 				.authorizeRequests()
 					.anyRequest().hasRole("USER")
 					.and()
-				.rememberMe()
-					.and()
-				.formLogin()
-					.and()
-				.openidLogin();
+				.formLogin();
+			// @formatter:on
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			// @formatter:off
+			auth
+				.inMemoryAuthentication()
+					.withUser(PasswordEncodedUser.user());
 			// @formatter:on
 		}
 
 	}
 
-	@Test
-	public void configureWhenAuthenticationEntryPointThenNoDefaultLoginPageGeneratingFilter() {
-		this.spring.register(DefaultLoginWithCustomAuthenticationEntryPointConfig.class).autowire();
+	@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
+		}
 
-		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 {
+	static class DefaultLoginPageCustomLogoutSuccessUrlConfig extends WebSecurityConfigurerAdapter {
 
 		@Override
 		protected void configure(HttpSecurity http) throws Exception {
 			// @formatter:off
 			http
-				.exceptionHandling()
-					.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login"))
-					.and()
 				.authorizeRequests()
 					.anyRequest().hasRole("USER")
 					.and()
+				.logout()
+					.logoutSuccessUrl("/login?logout")
+					.and()
 				.formLogin();
 			// @formatter:on
 		}
 
 	}
 
-	@Test
-	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnDefaultLoginPageGeneratingFilter() {
-		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
-		this.spring.register(ObjectPostProcessorConfig.class).autowire();
+	@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
+		}
 
-		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(DefaultLoginPageGeneratingFilter.class));
 	}
 
-	@Test
-	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnUsernamePasswordAuthenticationFilter() {
-		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
-		this.spring.register(ObjectPostProcessorConfig.class).autowire();
+	@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
+		}
 
-		verify(ObjectPostProcessorConfig.objectPostProcessor)
-				.postProcess(any(UsernamePasswordAuthenticationFilter.class));
 	}
 
-	@Test
-	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnLoginUrlAuthenticationEntryPoint() {
-		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
-		this.spring.register(ObjectPostProcessorConfig.class).autowire();
+	@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
+		}
 
-		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(LoginUrlAuthenticationEntryPoint.class));
 	}
 
-	@Test
-	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnExceptionTranslationFilter() {
-		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
-		this.spring.register(ObjectPostProcessorConfig.class).autowire();
+	@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
+		}
 
-		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(ExceptionTranslationFilter.class));
 	}
 
 	@EnableWebSecurity

+ 20 - 20
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 {
 

+ 65 - 65
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<Object> objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.exceptionHandling();
-			// @formatter:on
-		}
-
-		@Bean
-		static ObjectPostProcessor<Object> objectPostProcessor() {
-			return objectPostProcessor;
-		}
-
-	}
-
-	static class ReflectingObjectPostProcessor implements ObjectPostProcessor<Object> {
-
-		@Override
-		public <O> 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<Object> objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.exceptionHandling();
+			// @formatter:on
+		}
+
+		@Bean
+		static ObjectPostProcessor<Object> objectPostProcessor() {
+			return objectPostProcessor;
+		}
+
+	}
+
+	static class ReflectingObjectPostProcessor implements ObjectPostProcessor<Object> {
+
+		@Override
+		public <O> 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 {
 

+ 371 - 371
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<Object> objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.authorizeRequests()
-					.anyRequest().hasRole("USER");
-			// @formatter:on
-		}
-
-		@Bean
-		static ObjectPostProcessor<Object> 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,69 +190,414 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 		this.mvc.perform(get("/")).andExpect(status().isUnauthorized());
 	}
 
+	@Test
+	public void getWhenHasAnyRoleUserConfiguredAndRoleIsUserThenRespondsWithOk() throws Exception {
+		this.spring.register(RoleUserConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/").with(user("user").roles("USER"))).andExpect(status().isOk());
+	}
+
+	@Test
+	public void getWhenHasAnyRoleUserConfiguredAndRoleIsAdminThenRespondsWithForbidden() throws Exception {
+		this.spring.register(RoleUserConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/").with(user("user").roles("ADMIN"))).andExpect(status().isForbidden());
+	}
+
+	@Test
+	public void getWhenRoleUserOrAdminConfiguredAndRoleIsUserThenRespondsWithOk() throws Exception {
+		this.spring.register(RoleUserOrAdminConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/").with(user("user").roles("USER"))).andExpect(status().isOk());
+	}
+
+	@Test
+	public void getWhenRoleUserOrAdminConfiguredAndRoleIsAdminThenRespondsWithOk() throws Exception {
+		this.spring.register(RoleUserOrAdminConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/").with(user("user").roles("ADMIN"))).andExpect(status().isOk());
+	}
+
+	@Test
+	public void getWhenRoleUserOrAdminConfiguredAndRoleIsOtherThenRespondsWithForbidden() throws Exception {
+		this.spring.register(RoleUserOrAdminConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/").with(user("user").roles("OTHER"))).andExpect(status().isForbidden());
+	}
+
+	@Test
+	public void getWhenHasIpAddressConfiguredAndIpAddressMatchesThenRespondsWithOk() throws Exception {
+		this.spring.register(HasIpAddressConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/").with(request -> {
+			request.setRemoteAddr("192.168.1.0");
+			return request;
+		})).andExpect(status().isOk());
+	}
+
+	@Test
+	public void getWhenHasIpAddressConfiguredAndIpAddressDoesNotMatchThenRespondsWithUnauthorized() throws Exception {
+		this.spring.register(HasIpAddressConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/").with(request -> {
+			request.setRemoteAddr("192.168.1.1");
+			return request;
+		})).andExpect(status().isUnauthorized());
+	}
+
+	@Test
+	public void getWhenAnonymousConfiguredAndAnonymousUserThenRespondsWithOk() throws Exception {
+		this.spring.register(AnonymousConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(status().isOk());
+	}
+
+	@Test
+	public void getWhenAnonymousConfiguredAndLoggedInUserThenRespondsWithForbidden() throws Exception {
+		this.spring.register(AnonymousConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/").with(user("user"))).andExpect(status().isForbidden());
+	}
+
+	@Test
+	public void getWhenRememberMeConfiguredAndNoUserThenRespondsWithUnauthorized() throws Exception {
+		this.spring.register(RememberMeConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(status().isUnauthorized());
+	}
+
+	@Test
+	public void getWhenRememberMeConfiguredAndRememberMeTokenThenRespondsWithOk() throws Exception {
+		this.spring.register(RememberMeConfig.class, BasicController.class).autowire();
+
+		this.mvc.perform(get("/").with(authentication(
+				new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))))
+				.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 RoleUserOrRoleAdminAuthorityConfig extends WebSecurityConfigurerAdapter {
+	static class HasRoleStartingWithRoleConfig extends WebSecurityConfigurerAdapter {
 
 		@Override
 		protected void configure(HttpSecurity http) throws Exception {
 			// @formatter:off
 			http
-				.httpBasic()
-					.and()
 				.authorizeRequests()
-					.anyRequest().hasAnyAuthority("ROLE_USER", "ROLE_ADMIN");
+					.anyRequest().hasRole("ROLE_USER");
 			// @formatter:on
 		}
 
 	}
 
-	@Test
-	public void getWhenHasAnyRoleUserConfiguredAndRoleIsUserThenRespondsWithOk() throws Exception {
-		this.spring.register(RoleUserConfig.class, BasicController.class).autowire();
+	@EnableWebSecurity
+	static class NoSpecificAccessDecisionManagerConfig extends WebSecurityConfigurerAdapter {
+
+		static ObjectPostProcessor<Object> objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER");
+			// @formatter:on
+		}
+
+		@Bean
+		static ObjectPostProcessor<Object> objectPostProcessor() {
+			return objectPostProcessor;
+		}
 
-		this.mvc.perform(get("/").with(user("user").roles("USER"))).andExpect(status().isOk());
 	}
 
-	@Test
-	public void getWhenHasAnyRoleUserConfiguredAndRoleIsAdminThenRespondsWithForbidden() throws Exception {
-		this.spring.register(RoleUserConfig.class, BasicController.class).autowire();
+	@EnableWebSecurity
+	static class NoRequestsConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.authorizeRequests();
+			// @formatter:on
+		}
 
-		this.mvc.perform(get("/").with(user("user").roles("ADMIN"))).andExpect(status().isForbidden());
 	}
 
 	@EnableWebSecurity
-	static class RoleUserConfig extends WebSecurityConfigurerAdapter {
+	static class IncompleteMappingConfig extends WebSecurityConfigurerAdapter {
 
 		@Override
 		protected void configure(HttpSecurity http) throws Exception {
 			// @formatter:off
 			http
 				.authorizeRequests()
-					.anyRequest().hasAnyRole("USER");
+					.antMatchers("/a").authenticated()
+					.anyRequest();
 			// @formatter:on
 		}
 
 	}
 
-	@Test
-	public void getWhenRoleUserOrAdminConfiguredAndRoleIsUserThenRespondsWithOk() throws Exception {
-		this.spring.register(RoleUserOrAdminConfig.class, BasicController.class).autowire();
+	@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
+		}
 
-		this.mvc.perform(get("/").with(user("user").roles("USER"))).andExpect(status().isOk());
 	}
 
-	@Test
-	public void getWhenRoleUserOrAdminConfiguredAndRoleIsAdminThenRespondsWithOk() throws Exception {
-		this.spring.register(RoleUserOrAdminConfig.class, BasicController.class).autowire();
+	@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
+		}
 
-		this.mvc.perform(get("/").with(user("user").roles("ADMIN"))).andExpect(status().isOk());
 	}
 
-	@Test
-	public void getWhenRoleUserOrAdminConfiguredAndRoleIsOtherThenRespondsWithForbidden() throws Exception {
-		this.spring.register(RoleUserOrAdminConfig.class, BasicController.class).autowire();
+	@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
+		}
 
-		this.mvc.perform(get("/").with(user("user").roles("OTHER"))).andExpect(status().isForbidden());
 	}
 
 	@EnableWebSecurity
@@ -364,26 +614,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenHasIpAddressConfiguredAndIpAddressMatchesThenRespondsWithOk() throws Exception {
-		this.spring.register(HasIpAddressConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(get("/").with(request -> {
-			request.setRemoteAddr("192.168.1.0");
-			return request;
-		})).andExpect(status().isOk());
-	}
-
-	@Test
-	public void getWhenHasIpAddressConfiguredAndIpAddressDoesNotMatchThenRespondsWithUnauthorized() throws Exception {
-		this.spring.register(HasIpAddressConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(get("/").with(request -> {
-			request.setRemoteAddr("192.168.1.1");
-			return request;
-		})).andExpect(status().isUnauthorized());
-	}
-
 	@EnableWebSecurity
 	static class HasIpAddressConfig extends WebSecurityConfigurerAdapter {
 
@@ -400,20 +630,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenAnonymousConfiguredAndAnonymousUserThenRespondsWithOk() throws Exception {
-		this.spring.register(AnonymousConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(status().isOk());
-	}
-
-	@Test
-	public void getWhenAnonymousConfiguredAndLoggedInUserThenRespondsWithForbidden() throws Exception {
-		this.spring.register(AnonymousConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(get("/").with(user("user"))).andExpect(status().isForbidden());
-	}
-
 	@EnableWebSecurity
 	static class AnonymousConfig extends WebSecurityConfigurerAdapter {
 
@@ -430,22 +646,6 @@ public class ExpressionUrlAuthorizationConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenRememberMeConfiguredAndNoUserThenRespondsWithUnauthorized() throws Exception {
-		this.spring.register(RememberMeConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(status().isUnauthorized());
-	}
-
-	@Test
-	public void getWhenRememberMeConfiguredAndRememberMeTokenThenRespondsWithOk() throws Exception {
-		this.spring.register(RememberMeConfig.class, BasicController.class).autowire();
-
-		this.mvc.perform(get("/").with(authentication(
-				new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))))
-				.andExpect(status().isOk());
-	}
-
 	@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 {
 

+ 192 - 192
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 {
 

+ 12 - 12
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"));
-	}
-
 }

+ 360 - 360
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,27 +95,373 @@ public class HeadersConfigurerTests {
 				HttpHeaders.CACHE_CONTROL, HttpHeaders.EXPIRES, HttpHeaders.PRAGMA, HttpHeaders.X_XSS_PROTECTION);
 	}
 
+	@Test
+	public void getWhenHeaderDefaultsDisabledAndContentTypeConfiguredThenOnlyContentTypeHeaderInResponse()
+			throws Exception {
+		this.spring.register(ContentTypeOptionsConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/"))
+				.andExpect(header().string(HttpHeaders.X_CONTENT_TYPE_OPTIONS, "nosniff")).andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_CONTENT_TYPE_OPTIONS);
+	}
+
+	@Test
+	public void getWhenOnlyContentTypeConfiguredInLambdaThenOnlyContentTypeHeaderInResponse() throws Exception {
+		this.spring.register(ContentTypeOptionsInLambdaConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/"))
+				.andExpect(header().string(HttpHeaders.X_CONTENT_TYPE_OPTIONS, "nosniff")).andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_CONTENT_TYPE_OPTIONS);
+	}
+
+	@Test
+	public void getWhenHeaderDefaultsDisabledAndFrameOptionsConfiguredThenOnlyFrameOptionsHeaderInResponse()
+			throws Exception {
+		this.spring.register(FrameOptionsConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/"))
+				.andExpect(header().string(HttpHeaders.X_FRAME_OPTIONS, XFrameOptionsMode.DENY.name())).andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_FRAME_OPTIONS);
+	}
+
+	@Test
+	public void getWhenHeaderDefaultsDisabledAndHstsConfiguredThenOnlyStrictTransportSecurityHeaderInResponse()
+			throws Exception {
+		this.spring.register(HstsConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
+				.andExpect(
+						header().string(HttpHeaders.STRICT_TRANSPORT_SECURITY, "max-age=31536000 ; includeSubDomains"))
+				.andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.STRICT_TRANSPORT_SECURITY);
+	}
+
+	@Test
+	public void getWhenHeaderDefaultsDisabledAndCacheControlConfiguredThenCacheControlAndExpiresAndPragmaHeadersInResponse()
+			throws Exception {
+		this.spring.register(CacheControlConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
+				.andExpect(header().string(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate"))
+				.andExpect(header().string(HttpHeaders.EXPIRES, "0"))
+				.andExpect(header().string(HttpHeaders.PRAGMA, "no-cache")).andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactlyInAnyOrder(HttpHeaders.CACHE_CONTROL,
+				HttpHeaders.EXPIRES, HttpHeaders.PRAGMA);
+	}
+
+	@Test
+	public void getWhenOnlyCacheControlConfiguredInLambdaThenCacheControlAndExpiresAndPragmaHeadersInResponse()
+			throws Exception {
+		this.spring.register(CacheControlInLambdaConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
+				.andExpect(header().string(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate"))
+				.andExpect(header().string(HttpHeaders.EXPIRES, "0"))
+				.andExpect(header().string(HttpHeaders.PRAGMA, "no-cache")).andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactlyInAnyOrder(HttpHeaders.CACHE_CONTROL,
+				HttpHeaders.EXPIRES, HttpHeaders.PRAGMA);
+	}
+
+	@Test
+	public void getWhenHeaderDefaultsDisabledAndXssProtectionConfiguredThenOnlyXssProtectionHeaderInResponse()
+			throws Exception {
+		this.spring.register(XssProtectionConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
+				.andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block")).andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_XSS_PROTECTION);
+	}
+
+	@Test
+	public void getWhenOnlyXssProtectionConfiguredInLambdaThenOnlyXssProtectionHeaderInResponse() throws Exception {
+		this.spring.register(XssProtectionInLambdaConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
+				.andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block")).andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_XSS_PROTECTION);
+	}
+
+	@Test
+	public void getWhenFrameOptionsSameOriginConfiguredThenFrameOptionsHeaderHasValueSameOrigin() throws Exception {
+		this.spring.register(HeadersCustomSameOriginConfig.class).autowire();
+
+		this.mvc.perform(get("/").secure(true))
+				.andExpect(header().string(HttpHeaders.X_FRAME_OPTIONS, XFrameOptionsMode.SAMEORIGIN.name()))
+				.andReturn();
+	}
+
+	@Test
+	public void getWhenFrameOptionsSameOriginConfiguredInLambdaThenFrameOptionsHeaderHasValueSameOrigin()
+			throws Exception {
+		this.spring.register(HeadersCustomSameOriginInLambdaConfig.class).autowire();
+
+		this.mvc.perform(get("/").secure(true))
+				.andExpect(header().string(HttpHeaders.X_FRAME_OPTIONS, XFrameOptionsMode.SAMEORIGIN.name()))
+				.andReturn();
+	}
+
+	@Test
+	public void getWhenHeaderDefaultsDisabledAndPublicHpkpWithNoPinThenNoHeadersInResponse() throws Exception {
+		this.spring.register(HpkpConfigNoPins.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/")).andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).isEmpty();
+	}
+
+	@Test
+	public void getWhenSecureRequestAndHpkpWithPinThenPublicKeyPinsReportOnlyHeaderInResponse() throws Exception {
+		this.spring.register(HpkpConfig.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=\""))
+				.andReturn();
+		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY);
+	}
+
+	@Test
+	public void getWhenInsecureRequestHeaderDefaultsDisabledAndHpkpWithPinThenNoHeadersInResponse() throws Exception {
+		this.spring.register(HpkpConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/")).andReturn();
+		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 HeadersInLambdaConfig extends WebSecurityConfigurerAdapter {
+	static class HeadersConfig extends WebSecurityConfigurerAdapter {
 
 		@Override
 		protected void configure(HttpSecurity http) throws Exception {
 			// @formatter:off
 			http
-				.headers(withDefaults());
+				.headers();
 			// @formatter:on
 		}
 
 	}
 
-	@Test
-	public void getWhenHeaderDefaultsDisabledAndContentTypeConfiguredThenOnlyContentTypeHeaderInResponse()
-			throws Exception {
-		this.spring.register(ContentTypeOptionsConfig.class).autowire();
+	@EnableWebSecurity
+	static class HeadersInLambdaConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.headers(withDefaults());
+			// @formatter:on
+		}
 
-		MvcResult mvcResult = this.mvc.perform(get("/"))
-				.andExpect(header().string(HttpHeaders.X_CONTENT_TYPE_OPTIONS, "nosniff")).andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_CONTENT_TYPE_OPTIONS);
 	}
 
 	@EnableWebSecurity
@@ -146,15 +479,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenOnlyContentTypeConfiguredInLambdaThenOnlyContentTypeHeaderInResponse() throws Exception {
-		this.spring.register(ContentTypeOptionsInLambdaConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/"))
-				.andExpect(header().string(HttpHeaders.X_CONTENT_TYPE_OPTIONS, "nosniff")).andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_CONTENT_TYPE_OPTIONS);
-	}
-
 	@EnableWebSecurity
 	static class ContentTypeOptionsInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -172,16 +496,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenHeaderDefaultsDisabledAndFrameOptionsConfiguredThenOnlyFrameOptionsHeaderInResponse()
-			throws Exception {
-		this.spring.register(FrameOptionsConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/"))
-				.andExpect(header().string(HttpHeaders.X_FRAME_OPTIONS, XFrameOptionsMode.DENY.name())).andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_FRAME_OPTIONS);
-	}
-
 	@EnableWebSecurity
 	static class FrameOptionsConfig extends WebSecurityConfigurerAdapter {
 
@@ -197,18 +511,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenHeaderDefaultsDisabledAndHstsConfiguredThenOnlyStrictTransportSecurityHeaderInResponse()
-			throws Exception {
-		this.spring.register(HstsConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
-				.andExpect(
-						header().string(HttpHeaders.STRICT_TRANSPORT_SECURITY, "max-age=31536000 ; includeSubDomains"))
-				.andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.STRICT_TRANSPORT_SECURITY);
-	}
-
 	@EnableWebSecurity
 	static class HstsConfig extends WebSecurityConfigurerAdapter {
 
@@ -224,19 +526,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenHeaderDefaultsDisabledAndCacheControlConfiguredThenCacheControlAndExpiresAndPragmaHeadersInResponse()
-			throws Exception {
-		this.spring.register(CacheControlConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
-				.andExpect(header().string(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate"))
-				.andExpect(header().string(HttpHeaders.EXPIRES, "0"))
-				.andExpect(header().string(HttpHeaders.PRAGMA, "no-cache")).andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactlyInAnyOrder(HttpHeaders.CACHE_CONTROL,
-				HttpHeaders.EXPIRES, HttpHeaders.PRAGMA);
-	}
-
 	@EnableWebSecurity
 	static class CacheControlConfig extends WebSecurityConfigurerAdapter {
 
@@ -252,19 +541,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenOnlyCacheControlConfiguredInLambdaThenCacheControlAndExpiresAndPragmaHeadersInResponse()
-			throws Exception {
-		this.spring.register(CacheControlInLambdaConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
-				.andExpect(header().string(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate"))
-				.andExpect(header().string(HttpHeaders.EXPIRES, "0"))
-				.andExpect(header().string(HttpHeaders.PRAGMA, "no-cache")).andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactlyInAnyOrder(HttpHeaders.CACHE_CONTROL,
-				HttpHeaders.EXPIRES, HttpHeaders.PRAGMA);
-	}
-
 	@EnableWebSecurity
 	static class CacheControlInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -282,16 +558,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenHeaderDefaultsDisabledAndXssProtectionConfiguredThenOnlyXssProtectionHeaderInResponse()
-			throws Exception {
-		this.spring.register(XssProtectionConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
-				.andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block")).andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_XSS_PROTECTION);
-	}
-
 	@EnableWebSecurity
 	static class XssProtectionConfig extends WebSecurityConfigurerAdapter {
 
@@ -307,15 +573,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenOnlyXssProtectionConfiguredInLambdaThenOnlyXssProtectionHeaderInResponse() throws Exception {
-		this.spring.register(XssProtectionInLambdaConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").secure(true))
-				.andExpect(header().string(HttpHeaders.X_XSS_PROTECTION, "1; mode=block")).andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.X_XSS_PROTECTION);
-	}
-
 	@EnableWebSecurity
 	static class XssProtectionInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -325,21 +582,12 @@ public class HeadersConfigurerTests {
 			http
 				.headers(headers ->
 					headers
-						.defaultsDisabled()
-						.xssProtection(withDefaults())
-				);
-			// @formatter:on
-		}
-
-	}
-
-	@Test
-	public void getWhenFrameOptionsSameOriginConfiguredThenFrameOptionsHeaderHasValueSameOrigin() throws Exception {
-		this.spring.register(HeadersCustomSameOriginConfig.class).autowire();
+						.defaultsDisabled()
+						.xssProtection(withDefaults())
+				);
+			// @formatter:on
+		}
 
-		this.mvc.perform(get("/").secure(true))
-				.andExpect(header().string(HttpHeaders.X_FRAME_OPTIONS, XFrameOptionsMode.SAMEORIGIN.name()))
-				.andReturn();
 	}
 
 	@EnableWebSecurity
@@ -356,16 +604,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenFrameOptionsSameOriginConfiguredInLambdaThenFrameOptionsHeaderHasValueSameOrigin()
-			throws Exception {
-		this.spring.register(HeadersCustomSameOriginInLambdaConfig.class).autowire();
-
-		this.mvc.perform(get("/").secure(true))
-				.andExpect(header().string(HttpHeaders.X_FRAME_OPTIONS, XFrameOptionsMode.SAMEORIGIN.name()))
-				.andReturn();
-	}
-
 	@EnableWebSecurity
 	static class HeadersCustomSameOriginInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -382,14 +620,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenHeaderDefaultsDisabledAndPublicHpkpWithNoPinThenNoHeadersInResponse() throws Exception {
-		this.spring.register(HpkpConfigNoPins.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/")).andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).isEmpty();
-	}
-
 	@EnableWebSecurity
 	static class HpkpConfigNoPins extends WebSecurityConfigurerAdapter {
 
@@ -405,25 +635,6 @@ public class HeadersConfigurerTests {
 
 	}
 
-	@Test
-	public void getWhenSecureRequestAndHpkpWithPinThenPublicKeyPinsReportOnlyHeaderInResponse() throws Exception {
-		this.spring.register(HpkpConfig.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=\""))
-				.andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.PUBLIC_KEY_PINS_REPORT_ONLY);
-	}
-
-	@Test
-	public void getWhenInsecureRequestHeaderDefaultsDisabledAndHpkpWithPinThenNoHeadersInResponse() throws Exception {
-		this.spring.register(HpkpConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/")).andReturn();
-		assertThat(mvcResult.getResponse().getHeaderNames()).isEmpty();
-	}
-
 	@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 {
 

+ 46 - 46
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 {

+ 19 - 19
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);
-	}
-
 }

+ 8 - 8
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);
-	}
-
 }

+ 113 - 113
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);
-	}
-
 }

+ 30 - 30
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<Filter> 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<Filter> 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);
-	}
-
 }

+ 57 - 57
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 {
 

+ 176 - 176
config/src/test/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurerTests.java

@@ -70,6 +70,182 @@ public class LogoutConfigurerTests {
 				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
 	}
 
+	@Test
+	public void configureWhenDefaultLogoutSuccessHandlerForHasNullLogoutHandlerInLambdaThenException() {
+		assertThatThrownBy(() -> this.spring.register(NullLogoutSuccessHandlerInLambdaConfig.class).autowire())
+				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
+	}
+
+	@Test
+	public void configureWhenDefaultLogoutSuccessHandlerForHasNullMatcherThenException() {
+		assertThatThrownBy(() -> this.spring.register(NullMatcherConfig.class).autowire())
+				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
+	}
+
+	@Test
+	public void configureWhenDefaultLogoutSuccessHandlerForHasNullMatcherInLambdaThenException() {
+		assertThatThrownBy(() -> this.spring.register(NullMatcherInLambdaConfig.class).autowire())
+				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
+	}
+
+	@Test
+	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnLogoutFilter() {
+		this.spring.register(ObjectPostProcessorConfig.class).autowire();
+
+		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(LogoutFilter.class));
+	}
+
+	@Test
+	public void logoutWhenInvokedTwiceThenUsesOriginalLogoutUrl() throws Exception {
+		this.spring.register(DuplicateDoesNotOverrideConfig.class).autowire();
+
+		this.mvc.perform(post("/custom/logout").with(csrf())).andExpect(status().isFound())
+				.andExpect(redirectedUrl("/login?logout"));
+	}
+
+	// SEC-2311
+	@Test
+	public void logoutWhenGetRequestAndCsrfDisabledThenRedirectsToLogin() throws Exception {
+		this.spring.register(CsrfDisabledConfig.class).autowire();
+
+		this.mvc.perform(get("/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
+	}
+
+	@Test
+	public void logoutWhenPostRequestAndCsrfDisabledThenRedirectsToLogin() throws Exception {
+		this.spring.register(CsrfDisabledConfig.class).autowire();
+
+		this.mvc.perform(post("/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
+	}
+
+	@Test
+	public void logoutWhenPutRequestAndCsrfDisabledThenRedirectsToLogin() throws Exception {
+		this.spring.register(CsrfDisabledConfig.class).autowire();
+
+		this.mvc.perform(put("/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
+	}
+
+	@Test
+	public void logoutWhenDeleteRequestAndCsrfDisabledThenRedirectsToLogin() throws Exception {
+		this.spring.register(CsrfDisabledConfig.class).autowire();
+
+		this.mvc.perform(delete("/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
+	}
+
+	@Test
+	public void logoutWhenGetRequestAndCsrfDisabledAndCustomLogoutUrlThenRedirectsToLogin() throws Exception {
+		this.spring.register(CsrfDisabledAndCustomLogoutConfig.class).autowire();
+
+		this.mvc.perform(get("/custom/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
+	}
+
+	@Test
+	public void logoutWhenPostRequestAndCsrfDisabledAndCustomLogoutUrlThenRedirectsToLogin() throws Exception {
+		this.spring.register(CsrfDisabledAndCustomLogoutConfig.class).autowire();
+
+		this.mvc.perform(post("/custom/logout")).andExpect(status().isFound())
+				.andExpect(redirectedUrl("/login?logout"));
+	}
+
+	@Test
+	public void logoutWhenPutRequestAndCsrfDisabledAndCustomLogoutUrlThenRedirectsToLogin() throws Exception {
+		this.spring.register(CsrfDisabledAndCustomLogoutConfig.class).autowire();
+
+		this.mvc.perform(put("/custom/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
+	}
+
+	@Test
+	public void logoutWhenDeleteRequestAndCsrfDisabledAndCustomLogoutUrlThenRedirectsToLogin() throws Exception {
+		this.spring.register(CsrfDisabledAndCustomLogoutConfig.class).autowire();
+
+		this.mvc.perform(delete("/custom/logout")).andExpect(status().isFound())
+				.andExpect(redirectedUrl("/login?logout"));
+	}
+
+	@Test
+	public void logoutWhenCustomLogoutUrlInLambdaThenRedirectsToLogin() throws Exception {
+		this.spring.register(CsrfDisabledAndCustomLogoutInLambdaConfig.class).autowire();
+
+		this.mvc.perform(get("/custom/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
+	}
+
+	// SEC-3170
+	@Test
+	public void configureWhenLogoutHandlerNullThenException() {
+		assertThatThrownBy(() -> this.spring.register(NullLogoutHandlerConfig.class).autowire())
+				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
+	}
+
+	@Test
+	public void configureWhenLogoutHandlerNullInLambdaThenException() {
+		assertThatThrownBy(() -> this.spring.register(NullLogoutHandlerInLambdaConfig.class).autowire())
+				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
+	}
+
+	// SEC-3170
+	@Test
+	public void rememberMeWhenRememberMeServicesNotLogoutHandlerThenRedirectsToLogin() throws Exception {
+		this.spring.register(RememberMeNoLogoutHandler.class).autowire();
+
+		this.mvc.perform(post("/logout").with(csrf())).andExpect(status().isFound())
+				.andExpect(redirectedUrl("/login?logout"));
+	}
+
+	@Test
+	public void logoutWhenAcceptTextHtmlThenRedirectsToLogin() throws Exception {
+		this.spring.register(BasicSecurityConfig.class).autowire();
+
+		this.mvc.perform(
+				post("/logout").with(csrf()).with(user("user")).header(HttpHeaders.ACCEPT, MediaType.TEXT_HTML_VALUE))
+				.andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
+	}
+
+	// gh-3282
+	@Test
+	public void logoutWhenAcceptApplicationJsonThenReturnsStatusNoContent() throws Exception {
+		this.spring.register(BasicSecurityConfig.class).autowire();
+
+		this.mvc.perform(post("/logout").with(csrf()).with(user("user")).header(HttpHeaders.ACCEPT,
+				MediaType.APPLICATION_JSON_VALUE)).andExpect(status().isNoContent());
+	}
+
+	// gh-4831
+	@Test
+	public void logoutWhenAcceptAllThenReturnsStatusNoContent() throws Exception {
+		this.spring.register(BasicSecurityConfig.class).autowire();
+
+		this.mvc.perform(
+				post("/logout").with(csrf()).with(user("user")).header(HttpHeaders.ACCEPT, MediaType.ALL_VALUE))
+				.andExpect(status().isNoContent());
+	}
+
+	// gh-3902
+	@Test
+	public void logoutWhenAcceptFromChromeThenRedirectsToLogin() throws Exception {
+		this.spring.register(BasicSecurityConfig.class).autowire();
+
+		this.mvc.perform(post("/logout").with(csrf()).with(user("user")).header(HttpHeaders.ACCEPT,
+				"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"))
+				.andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
+	}
+
+	// gh-3997
+	@Test
+	public void logoutWhenXMLHttpRequestThenReturnsStatusNoContent() throws Exception {
+		this.spring.register(BasicSecurityConfig.class).autowire();
+
+		this.mvc.perform(post("/logout").with(csrf()).with(user("user"))
+				.header(HttpHeaders.ACCEPT, "text/html,application/json").header("X-Requested-With", "XMLHttpRequest"))
+				.andExpect(status().isNoContent());
+	}
+
+	@Test
+	public void logoutWhenDisabledThenLogoutUrlNotFound() throws Exception {
+		this.spring.register(LogoutDisabledConfig.class).autowire();
+
+		this.mvc.perform(post("/logout").with(csrf())).andExpect(status().isNotFound());
+	}
+
 	@EnableWebSecurity
 	static class NullLogoutSuccessHandlerConfig extends WebSecurityConfigurerAdapter {
 
@@ -84,12 +260,6 @@ public class LogoutConfigurerTests {
 
 	}
 
-	@Test
-	public void configureWhenDefaultLogoutSuccessHandlerForHasNullLogoutHandlerInLambdaThenException() {
-		assertThatThrownBy(() -> this.spring.register(NullLogoutSuccessHandlerInLambdaConfig.class).autowire())
-				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
-	}
-
 	@EnableWebSecurity
 	static class NullLogoutSuccessHandlerInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -105,12 +275,6 @@ public class LogoutConfigurerTests {
 
 	}
 
-	@Test
-	public void configureWhenDefaultLogoutSuccessHandlerForHasNullMatcherThenException() {
-		assertThatThrownBy(() -> this.spring.register(NullMatcherConfig.class).autowire())
-				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
-	}
-
 	@EnableWebSecurity
 	static class NullMatcherConfig extends WebSecurityConfigurerAdapter {
 
@@ -125,12 +289,6 @@ public class LogoutConfigurerTests {
 
 	}
 
-	@Test
-	public void configureWhenDefaultLogoutSuccessHandlerForHasNullMatcherInLambdaThenException() {
-		assertThatThrownBy(() -> this.spring.register(NullMatcherInLambdaConfig.class).autowire())
-				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
-	}
-
 	@EnableWebSecurity
 	static class NullMatcherInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -146,13 +304,6 @@ public class LogoutConfigurerTests {
 
 	}
 
-	@Test
-	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnLogoutFilter() {
-		this.spring.register(ObjectPostProcessorConfig.class).autowire();
-
-		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(LogoutFilter.class));
-	}
-
 	@EnableWebSecurity
 	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
 
@@ -182,14 +333,6 @@ public class LogoutConfigurerTests {
 
 	}
 
-	@Test
-	public void logoutWhenInvokedTwiceThenUsesOriginalLogoutUrl() throws Exception {
-		this.spring.register(DuplicateDoesNotOverrideConfig.class).autowire();
-
-		this.mvc.perform(post("/custom/logout").with(csrf())).andExpect(status().isFound())
-				.andExpect(redirectedUrl("/login?logout"));
-	}
-
 	@EnableWebSecurity
 	static class DuplicateDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
 
@@ -214,35 +357,6 @@ public class LogoutConfigurerTests {
 
 	}
 
-	// SEC-2311
-	@Test
-	public void logoutWhenGetRequestAndCsrfDisabledThenRedirectsToLogin() throws Exception {
-		this.spring.register(CsrfDisabledConfig.class).autowire();
-
-		this.mvc.perform(get("/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
-	}
-
-	@Test
-	public void logoutWhenPostRequestAndCsrfDisabledThenRedirectsToLogin() throws Exception {
-		this.spring.register(CsrfDisabledConfig.class).autowire();
-
-		this.mvc.perform(post("/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
-	}
-
-	@Test
-	public void logoutWhenPutRequestAndCsrfDisabledThenRedirectsToLogin() throws Exception {
-		this.spring.register(CsrfDisabledConfig.class).autowire();
-
-		this.mvc.perform(put("/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
-	}
-
-	@Test
-	public void logoutWhenDeleteRequestAndCsrfDisabledThenRedirectsToLogin() throws Exception {
-		this.spring.register(CsrfDisabledConfig.class).autowire();
-
-		this.mvc.perform(delete("/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
-	}
-
 	@EnableWebSecurity
 	static class CsrfDisabledConfig extends WebSecurityConfigurerAdapter {
 
@@ -258,36 +372,6 @@ public class LogoutConfigurerTests {
 
 	}
 
-	@Test
-	public void logoutWhenGetRequestAndCsrfDisabledAndCustomLogoutUrlThenRedirectsToLogin() throws Exception {
-		this.spring.register(CsrfDisabledAndCustomLogoutConfig.class).autowire();
-
-		this.mvc.perform(get("/custom/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
-	}
-
-	@Test
-	public void logoutWhenPostRequestAndCsrfDisabledAndCustomLogoutUrlThenRedirectsToLogin() throws Exception {
-		this.spring.register(CsrfDisabledAndCustomLogoutConfig.class).autowire();
-
-		this.mvc.perform(post("/custom/logout")).andExpect(status().isFound())
-				.andExpect(redirectedUrl("/login?logout"));
-	}
-
-	@Test
-	public void logoutWhenPutRequestAndCsrfDisabledAndCustomLogoutUrlThenRedirectsToLogin() throws Exception {
-		this.spring.register(CsrfDisabledAndCustomLogoutConfig.class).autowire();
-
-		this.mvc.perform(put("/custom/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
-	}
-
-	@Test
-	public void logoutWhenDeleteRequestAndCsrfDisabledAndCustomLogoutUrlThenRedirectsToLogin() throws Exception {
-		this.spring.register(CsrfDisabledAndCustomLogoutConfig.class).autowire();
-
-		this.mvc.perform(delete("/custom/logout")).andExpect(status().isFound())
-				.andExpect(redirectedUrl("/login?logout"));
-	}
-
 	@EnableWebSecurity
 	static class CsrfDisabledAndCustomLogoutConfig extends WebSecurityConfigurerAdapter {
 
@@ -304,13 +388,6 @@ public class LogoutConfigurerTests {
 
 	}
 
-	@Test
-	public void logoutWhenCustomLogoutUrlInLambdaThenRedirectsToLogin() throws Exception {
-		this.spring.register(CsrfDisabledAndCustomLogoutInLambdaConfig.class).autowire();
-
-		this.mvc.perform(get("/custom/logout")).andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
-	}
-
 	@EnableWebSecurity
 	static class CsrfDisabledAndCustomLogoutInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -326,13 +403,6 @@ public class LogoutConfigurerTests {
 
 	}
 
-	// SEC-3170
-	@Test
-	public void configureWhenLogoutHandlerNullThenException() {
-		assertThatThrownBy(() -> this.spring.register(NullLogoutHandlerConfig.class).autowire())
-				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
-	}
-
 	@EnableWebSecurity
 	static class NullLogoutHandlerConfig extends WebSecurityConfigurerAdapter {
 
@@ -347,12 +417,6 @@ public class LogoutConfigurerTests {
 
 	}
 
-	@Test
-	public void configureWhenLogoutHandlerNullInLambdaThenException() {
-		assertThatThrownBy(() -> this.spring.register(NullLogoutHandlerInLambdaConfig.class).autowire())
-				.isInstanceOf(BeanCreationException.class).hasRootCauseInstanceOf(IllegalArgumentException.class);
-	}
-
 	@EnableWebSecurity
 	static class NullLogoutHandlerInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -366,15 +430,6 @@ public class LogoutConfigurerTests {
 
 	}
 
-	// SEC-3170
-	@Test
-	public void rememberMeWhenRememberMeServicesNotLogoutHandlerThenRedirectsToLogin() throws Exception {
-		this.spring.register(RememberMeNoLogoutHandler.class).autowire();
-
-		this.mvc.perform(post("/logout").with(csrf())).andExpect(status().isFound())
-				.andExpect(redirectedUrl("/login?logout"));
-	}
-
 	@EnableWebSecurity
 	static class RememberMeNoLogoutHandler extends WebSecurityConfigurerAdapter {
 
@@ -391,66 +446,11 @@ public class LogoutConfigurerTests {
 
 	}
 
-	@Test
-	public void logoutWhenAcceptTextHtmlThenRedirectsToLogin() throws Exception {
-		this.spring.register(BasicSecurityConfig.class).autowire();
-
-		this.mvc.perform(
-				post("/logout").with(csrf()).with(user("user")).header(HttpHeaders.ACCEPT, MediaType.TEXT_HTML_VALUE))
-				.andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
-	}
-
-	// gh-3282
-	@Test
-	public void logoutWhenAcceptApplicationJsonThenReturnsStatusNoContent() throws Exception {
-		this.spring.register(BasicSecurityConfig.class).autowire();
-
-		this.mvc.perform(post("/logout").with(csrf()).with(user("user")).header(HttpHeaders.ACCEPT,
-				MediaType.APPLICATION_JSON_VALUE)).andExpect(status().isNoContent());
-	}
-
-	// gh-4831
-	@Test
-	public void logoutWhenAcceptAllThenReturnsStatusNoContent() throws Exception {
-		this.spring.register(BasicSecurityConfig.class).autowire();
-
-		this.mvc.perform(
-				post("/logout").with(csrf()).with(user("user")).header(HttpHeaders.ACCEPT, MediaType.ALL_VALUE))
-				.andExpect(status().isNoContent());
-	}
-
-	// gh-3902
-	@Test
-	public void logoutWhenAcceptFromChromeThenRedirectsToLogin() throws Exception {
-		this.spring.register(BasicSecurityConfig.class).autowire();
-
-		this.mvc.perform(post("/logout").with(csrf()).with(user("user")).header(HttpHeaders.ACCEPT,
-				"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"))
-				.andExpect(status().isFound()).andExpect(redirectedUrl("/login?logout"));
-	}
-
-	// gh-3997
-	@Test
-	public void logoutWhenXMLHttpRequestThenReturnsStatusNoContent() throws Exception {
-		this.spring.register(BasicSecurityConfig.class).autowire();
-
-		this.mvc.perform(post("/logout").with(csrf()).with(user("user"))
-				.header(HttpHeaders.ACCEPT, "text/html,application/json").header("X-Requested-With", "XMLHttpRequest"))
-				.andExpect(status().isNoContent());
-	}
-
 	@EnableWebSecurity
 	static class BasicSecurityConfig extends WebSecurityConfigurerAdapter {
 
 	}
 
-	@Test
-	public void logoutWhenDisabledThenLogoutUrlNotFound() throws Exception {
-		this.spring.register(LogoutDisabledConfig.class).autowire();
-
-		this.mvc.perform(post("/logout").with(csrf())).andExpect(status().isNotFound());
-	}
-
 	@EnableWebSecurity
 	static class LogoutDisabledConfig extends WebSecurityConfigurerAdapter {
 

+ 10 - 10
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<ILoggingEvent> 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<ILoggingEvent> mockAppenderFor(String name) {
 		Appender<ILoggingEvent> 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 {
+
+	}
+
 }

+ 24 - 24
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 {
 

+ 84 - 84
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<HttpServletRequest, ?> 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<HttpServletRequest, ?> 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<HttpServletRequest, ?> 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<HttpServletRequest, ?> 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 {
 

+ 31 - 31
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<Class<?>> assertThatFilters() {
+		FilterChainProxy filterChain = this.spring.getContext().getBean(FilterChainProxy.class);
+		List<Class<?>> 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<Class<?>> assertThatFilters() {
-		FilterChainProxy filterChain = this.spring.getContext().getBean(FilterChainProxy.class);
-		List<Class<?>> filters = filterChain.getFilters("/").stream().map(Object::getClass)
-				.collect(Collectors.toList());
-		return assertThat(filters);
-	}
-
 }

+ 4 - 4
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> T verifyBean(String beanName, Class<T> 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> T verifyBean(String beanName, Class<T> beanClass) {
-		return verify(this.spring.getContext().getBean(beanName, beanClass));
-	}
-
 }

+ 12 - 12
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 {
 

+ 30 - 30
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> T verifyBean(Class<T> 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> T verifyBean(Class<T> beanClass) {
-		return verify(this.spring.getContext().getBean(beanClass));
-	}
-
 }

+ 87 - 92
config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpHeadersTests.java

@@ -73,6 +73,93 @@ public class NamespaceHttpHeadersTests {
 		this.mvc.perform(get("/").secure(true)).andExpect(includesDefaults());
 	}
 
+	@Test
+	public void secureRequestWhenCacheControlOnlyThenBehaviorMatchesNamespace() throws Exception {
+		this.spring.register(HeadersCacheControlConfig.class).autowire();
+
+		this.mvc.perform(get("/").secure(true)).andExpect(includes("Cache-Control", "Expires", "Pragma"));
+	}
+
+	@Test
+	public void secureRequestWhenHstsOnlyThenBehaviorMatchesNamespace() throws Exception {
+		this.spring.register(HstsConfig.class).autowire();
+
+		this.mvc.perform(get("/").secure(true)).andExpect(includes("Strict-Transport-Security"));
+	}
+
+	@Test
+	public void requestWhenHstsCustomThenBehaviorMatchesNamespace() throws Exception {
+		this.spring.register(HstsCustomConfig.class).autowire();
+
+		this.mvc.perform(get("/"))
+				.andExpect(includes(Collections.singletonMap("Strict-Transport-Security", "max-age=15768000")));
+	}
+
+	@Test
+	public void requestWhenFrameOptionsSameOriginThenBehaviorMatchesNamespace() throws Exception {
+		this.spring.register(FrameOptionsSameOriginConfig.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(includes(Collections.singletonMap("X-Frame-Options", "SAMEORIGIN")));
+	}
+
+	@Test
+	public void requestWhenFrameOptionsAllowFromThenBehaviorMatchesNamespace() throws Exception {
+		this.spring.register(FrameOptionsAllowFromConfig.class).autowire();
+
+		this.mvc.perform(get("/"))
+				.andExpect(includes(Collections.singletonMap("X-Frame-Options", "ALLOW-FROM https://example.com")));
+	}
+
+	@Test
+	public void requestWhenXssOnlyThenBehaviorMatchesNamespace() throws Exception {
+		this.spring.register(XssProtectionConfig.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(includes("X-XSS-Protection"));
+	}
+
+	@Test
+	public void requestWhenXssCustomThenBehaviorMatchesNamespace() throws Exception {
+		this.spring.register(XssProtectionCustomConfig.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(includes(Collections.singletonMap("X-XSS-Protection", "1")));
+	}
+
+	@Test
+	public void requestWhenXContentTypeOptionsOnlyThenBehaviorMatchesNamespace() throws Exception {
+		this.spring.register(ContentTypeOptionsConfig.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(includes("X-Content-Type-Options"));
+	}
+
+	@Test
+	public void requestWhenCustomHeaderOnlyThenBehaviorMatchesNamespace() throws Exception {
+		this.spring.register(HeaderRefConfig.class).autowire();
+
+		this.mvc.perform(get("/"))
+				.andExpect(includes(Collections.singletonMap("customHeaderName", "customHeaderValue")));
+	}
+
+	private static ResultMatcher includesDefaults() {
+		return includes(defaultHeaders);
+	}
+
+	private static ResultMatcher includes(String... headerNames) {
+		return includes(defaultHeaders, headerNames);
+	}
+
+	private static ResultMatcher includes(Map<String, String> headers) {
+		return includes(headers, headers.keySet().toArray(new String[headers.size()]));
+	}
+
+	private static ResultMatcher includes(Map<String, String> headers, String... headerNames) {
+		return result -> {
+			assertThat(result.getResponse().getHeaderNames()).hasSameSizeAs(headerNames);
+			for (String headerName : headerNames) {
+				header().string(headerName, headers.get(headerName)).match(result);
+			}
+		};
+	}
+
 	@EnableWebSecurity
 	static class HeadersDefaultConfig extends WebSecurityConfigurerAdapter {
 
@@ -86,13 +173,6 @@ public class NamespaceHttpHeadersTests {
 
 	}
 
-	@Test
-	public void secureRequestWhenCacheControlOnlyThenBehaviorMatchesNamespace() throws Exception {
-		this.spring.register(HeadersCacheControlConfig.class).autowire();
-
-		this.mvc.perform(get("/").secure(true)).andExpect(includes("Cache-Control", "Expires", "Pragma"));
-	}
-
 	@EnableWebSecurity
 	static class HeadersCacheControlConfig extends WebSecurityConfigurerAdapter {
 
@@ -108,13 +188,6 @@ public class NamespaceHttpHeadersTests {
 
 	}
 
-	@Test
-	public void secureRequestWhenHstsOnlyThenBehaviorMatchesNamespace() throws Exception {
-		this.spring.register(HstsConfig.class).autowire();
-
-		this.mvc.perform(get("/").secure(true)).andExpect(includes("Strict-Transport-Security"));
-	}
-
 	@EnableWebSecurity
 	static class HstsConfig extends WebSecurityConfigurerAdapter {
 
@@ -130,14 +203,6 @@ public class NamespaceHttpHeadersTests {
 
 	}
 
-	@Test
-	public void requestWhenHstsCustomThenBehaviorMatchesNamespace() throws Exception {
-		this.spring.register(HstsCustomConfig.class).autowire();
-
-		this.mvc.perform(get("/"))
-				.andExpect(includes(Collections.singletonMap("Strict-Transport-Security", "max-age=15768000")));
-	}
-
 	@EnableWebSecurity
 	static class HstsCustomConfig extends WebSecurityConfigurerAdapter {
 
@@ -157,13 +222,6 @@ public class NamespaceHttpHeadersTests {
 
 	}
 
-	@Test
-	public void requestWhenFrameOptionsSameOriginThenBehaviorMatchesNamespace() throws Exception {
-		this.spring.register(FrameOptionsSameOriginConfig.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(includes(Collections.singletonMap("X-Frame-Options", "SAMEORIGIN")));
-	}
-
 	@EnableWebSecurity
 	static class FrameOptionsSameOriginConfig extends WebSecurityConfigurerAdapter {
 
@@ -181,17 +239,6 @@ public class NamespaceHttpHeadersTests {
 
 	}
 
-	// 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();
-
-		this.mvc.perform(get("/"))
-				.andExpect(includes(Collections.singletonMap("X-Frame-Options", "ALLOW-FROM https://example.com")));
-	}
-
 	@EnableWebSecurity
 	static class FrameOptionsAllowFromConfig extends WebSecurityConfigurerAdapter {
 
@@ -209,13 +256,6 @@ public class NamespaceHttpHeadersTests {
 
 	}
 
-	@Test
-	public void requestWhenXssOnlyThenBehaviorMatchesNamespace() throws Exception {
-		this.spring.register(XssProtectionConfig.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(includes("X-XSS-Protection"));
-	}
-
 	@EnableWebSecurity
 	static class XssProtectionConfig extends WebSecurityConfigurerAdapter {
 
@@ -232,13 +272,6 @@ public class NamespaceHttpHeadersTests {
 
 	}
 
-	@Test
-	public void requestWhenXssCustomThenBehaviorMatchesNamespace() throws Exception {
-		this.spring.register(XssProtectionCustomConfig.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(includes(Collections.singletonMap("X-XSS-Protection", "1")));
-	}
-
 	@EnableWebSecurity
 	static class XssProtectionCustomConfig extends WebSecurityConfigurerAdapter {
 
@@ -257,13 +290,6 @@ public class NamespaceHttpHeadersTests {
 
 	}
 
-	@Test
-	public void requestWhenXContentTypeOptionsOnlyThenBehaviorMatchesNamespace() throws Exception {
-		this.spring.register(ContentTypeOptionsConfig.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(includes("X-Content-Type-Options"));
-	}
-
 	@EnableWebSecurity
 	static class ContentTypeOptionsConfig extends WebSecurityConfigurerAdapter {
 
@@ -280,16 +306,6 @@ public class NamespaceHttpHeadersTests {
 
 	}
 
-	// header@name / header@value are not provided instead use header@ref
-
-	@Test
-	public void requestWhenCustomHeaderOnlyThenBehaviorMatchesNamespace() throws Exception {
-		this.spring.register(HeaderRefConfig.class).autowire();
-
-		this.mvc.perform(get("/"))
-				.andExpect(includes(Collections.singletonMap("customHeaderName", "customHeaderValue")));
-	}
-
 	@EnableWebSecurity
 	static class HeaderRefConfig extends WebSecurityConfigurerAdapter {
 
@@ -305,25 +321,4 @@ public class NamespaceHttpHeadersTests {
 
 	}
 
-	private static ResultMatcher includesDefaults() {
-		return includes(defaultHeaders);
-	}
-
-	private static ResultMatcher includes(String... headerNames) {
-		return includes(defaultHeaders, headerNames);
-	}
-
-	private static ResultMatcher includes(Map<String, String> headers) {
-		return includes(headers, headers.keySet().toArray(new String[headers.size()]));
-	}
-
-	private static ResultMatcher includes(Map<String, String> headers, String... headerNames) {
-		return result -> {
-			assertThat(result.getResponse().getHeaderNames()).hasSameSizeAs(headerNames);
-			for (String headerName : headerNames) {
-				header().string(headerName, headers.get(headerName)).match(result);
-			}
-		};
-	}
-
 }

+ 4 - 4
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));
-	}
-
 }

+ 25 - 25
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> T bean(Class<T> beanClass) {
+		return this.spring.getContext().getBean(beanClass);
+	}
+
+	private <T> T verifyBean(Class<T> 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> T bean(Class<T> beanClass) {
-		return this.spring.getContext().getBean(beanClass);
-	}
-
-	private <T> T verifyBean(Class<T> beanClass) {
-		return verify(this.spring.getContext().getBean(beanClass));
-	}
-
 }

+ 67 - 67
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<HttpSession> 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<HttpSession> sessionPredicate) {
-		return result -> assertThat(result.getRequest().getSession(false))
-				.is(new Condition<>(sessionPredicate, "sessionPredicate failed"));
-	}
-
 }

+ 53 - 53
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 {

+ 15 - 15
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> T verifyBean(Class<T> 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> T verifyBean(Class<T> beanClass) {
-		return verify(this.spring.getContext().getBean(beanClass));
-	}
-
 }

+ 34 - 34
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> T verifyBean(Class<T> 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> T verifyBean(Class<T> beanClass) {
-		return verify(this.spring.getContext().getBean(beanClass));
-	}
-
 }

+ 52 - 52
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 extends Certificate> 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> T verifyBean(Class<T> 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 extends Certificate> 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> T verifyBean(Class<T> beanClass) {
-		return verify(this.spring.getContext().getBean(beanClass));
-	}
-
 }

+ 154 - 155
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

+ 98 - 98
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> T verifyBean(Class<T> 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> T verifyBean(Class<T> clazz) {
-		return verify(this.spring.getContext().getBean(clazz));
-	}
-
 	static class MockEventListener implements ApplicationListener<SessionFixationProtectionEvent> {
 
 		List<SessionFixationProtectionEvent> 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;

+ 7 - 7
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 {
 

+ 14 - 14
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 {
 

+ 113 - 113
config/src/test/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.java

@@ -86,6 +86,119 @@ public class RememberMeConfigurerTests {
 				.param("remember-me", "true").with(csrf()))).hasMessageContaining("UserDetailsService is required");
 	}
 
+	@Test
+	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnRememberMeAuthenticationFilter() {
+		this.spring.register(ObjectPostProcessorConfig.class).autowire();
+
+		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(RememberMeAuthenticationFilter.class));
+	}
+
+	@Test
+	public void rememberMeWhenInvokedTwiceThenUsesOriginalUserDetailsService() throws Exception {
+		when(DuplicateDoesNotOverrideConfig.userDetailsService.loadUserByUsername(anyString()))
+				.thenReturn(new User("user", "password", Collections.emptyList()));
+		this.spring.register(DuplicateDoesNotOverrideConfig.class).autowire();
+
+		this.mvc.perform(get("/").with(httpBasic("user", "password")).param("remember-me", "true"));
+
+		verify(DuplicateDoesNotOverrideConfig.userDetailsService).loadUserByUsername("user");
+	}
+
+	@Test
+	public void loginWhenRememberMeTrueThenRespondsWithRememberMeCookie() throws Exception {
+		this.spring.register(RememberMeConfig.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 getWhenRememberMeCookieThenAuthenticationIsRememberMeAuthenticationToken() throws Exception {
+		this.spring.register(RememberMeConfig.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)));
+	}
+
+	@Test
+	public void logoutWhenRememberMeCookieThenAuthenticationIsRememberMeCookieExpired() throws Exception {
+		this.spring.register(RememberMeConfig.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");
+		HttpSession session = mvcResult.getRequest().getSession();
+
+		this.mvc.perform(post("/logout").with(csrf()).cookie(rememberMeCookie).session((MockHttpSession) session))
+				.andExpect(redirectedUrl("/login?logout")).andExpect(cookie().maxAge("remember-me", 0));
+	}
+
+	@Test
+	public void getWhenRememberMeCookieAndLoggedOutThenRedirectsToLogin() throws Exception {
+		this.spring.register(RememberMeConfig.class).autowire();
+
+		MvcResult loginMvcResult = this.mvc.perform(post("/login").with(csrf()).param("username", "user")
+				.param("password", "password").param("remember-me", "true")).andReturn();
+		Cookie rememberMeCookie = loginMvcResult.getResponse().getCookie("remember-me");
+		HttpSession session = loginMvcResult.getRequest().getSession();
+		MvcResult logoutMvcResult = this.mvc
+				.perform(post("/logout").with(csrf()).cookie(rememberMeCookie).session((MockHttpSession) session))
+				.andReturn();
+		Cookie expiredRememberMeCookie = logoutMvcResult.getResponse().getCookie("remember-me");
+
+		this.mvc.perform(get("/abc").with(csrf()).cookie(expiredRememberMeCookie))
+				.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 {
 
@@ -115,13 +228,6 @@ public class RememberMeConfigurerTests {
 
 	}
 
-	@Test
-	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnRememberMeAuthenticationFilter() {
-		this.spring.register(ObjectPostProcessorConfig.class).autowire();
-
-		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(RememberMeAuthenticationFilter.class));
-	}
-
 	@EnableWebSecurity
 	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
 
@@ -160,17 +266,6 @@ public class RememberMeConfigurerTests {
 
 	}
 
-	@Test
-	public void rememberMeWhenInvokedTwiceThenUsesOriginalUserDetailsService() throws Exception {
-		when(DuplicateDoesNotOverrideConfig.userDetailsService.loadUserByUsername(anyString()))
-				.thenReturn(new User("user", "password", Collections.emptyList()));
-		this.spring.register(DuplicateDoesNotOverrideConfig.class).autowire();
-
-		this.mvc.perform(get("/").with(httpBasic("user", "password")).param("remember-me", "true"));
-
-		verify(DuplicateDoesNotOverrideConfig.userDetailsService).loadUserByUsername("user");
-	}
-
 	@EnableWebSecurity
 	static class DuplicateDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
 
@@ -205,56 +300,6 @@ public class RememberMeConfigurerTests {
 
 	}
 
-	@Test
-	public void loginWhenRememberMeTrueThenRespondsWithRememberMeCookie() throws Exception {
-		this.spring.register(RememberMeConfig.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 getWhenRememberMeCookieThenAuthenticationIsRememberMeAuthenticationToken() throws Exception {
-		this.spring.register(RememberMeConfig.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)));
-	}
-
-	@Test
-	public void logoutWhenRememberMeCookieThenAuthenticationIsRememberMeCookieExpired() throws Exception {
-		this.spring.register(RememberMeConfig.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");
-		HttpSession session = mvcResult.getRequest().getSession();
-
-		this.mvc.perform(post("/logout").with(csrf()).cookie(rememberMeCookie).session((MockHttpSession) session))
-				.andExpect(redirectedUrl("/login?logout")).andExpect(cookie().maxAge("remember-me", 0));
-	}
-
-	@Test
-	public void getWhenRememberMeCookieAndLoggedOutThenRedirectsToLogin() throws Exception {
-		this.spring.register(RememberMeConfig.class).autowire();
-
-		MvcResult loginMvcResult = this.mvc.perform(post("/login").with(csrf()).param("username", "user")
-				.param("password", "password").param("remember-me", "true")).andReturn();
-		Cookie rememberMeCookie = loginMvcResult.getResponse().getCookie("remember-me");
-		HttpSession session = loginMvcResult.getRequest().getSession();
-		MvcResult logoutMvcResult = this.mvc
-				.perform(post("/logout").with(csrf()).cookie(rememberMeCookie).session((MockHttpSession) session))
-				.andReturn();
-		Cookie expiredRememberMeCookie = logoutMvcResult.getResponse().getCookie("remember-me");
-
-		this.mvc.perform(get("/abc").with(csrf()).cookie(expiredRememberMeCookie))
-				.andExpect(redirectedUrl("http://localhost/login"));
-	}
-
 	@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 {
 

+ 94 - 94
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<Object> objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			// @formatter:off
-			http
-				.requestCache();
-			// @formatter:on
-		}
-
-		@Bean
-		static ObjectPostProcessor<Object> objectPostProcessor() {
-			return objectPostProcessor;
-		}
-
-	}
-
-	static class ReflectingObjectPostProcessor implements ObjectPostProcessor<Object> {
-
-		@Override
-		public <O> 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,25 +219,110 @@ 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 RequestCacheDisabledConfig extends WebSecurityConfigurerAdapter {
+	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
+
+		static ObjectPostProcessor<Object> objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
 
 		@Override
 		protected void configure(HttpSecurity http) throws Exception {
-			super.configure(http);
-			http.requestCache().disable();
+			// @formatter:off
+			http
+				.requestCache();
+			// @formatter:on
+		}
+
+		@Bean
+		static ObjectPostProcessor<Object> objectPostProcessor() {
+			return objectPostProcessor;
 		}
 
 	}
 
-	@Test
-	public void getWhenRequestCacheIsDisabledInLambdaThenExceptionTranslationFilterDoesNotStoreRequest()
-			throws Exception {
-		this.spring.register(RequestCacheDisabledInLambdaConfig.class, DefaultSecurityConfig.class).autowire();
+	static class ReflectingObjectPostProcessor implements ObjectPostProcessor<Object> {
 
-		MockHttpSession session = (MockHttpSession) this.mvc.perform(get("/bob")).andReturn().getRequest().getSession();
+		@Override
+		public <O> 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 {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			super.configure(http);
+			http.requestCache().disable();
+		}
 
-		this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/"));
 	}
 
 	@EnableWebSecurity
@@ -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());
-	}
-
 }

+ 8 - 8
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 {
 

+ 45 - 45
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 {
 

+ 121 - 121
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<LogoutHandler> scaLogoutHandlers = getFieldValue(scaFilter, "logoutHandlers");
+		List<LogoutHandler> 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 extends Filter> T getFilter(Class<T> filterClass) {
+		return (T) getFilters().stream().filter(filterClass::isInstance).findFirst().orElse(null);
+	}
+
+	private List<Filter> getFilters() {
+		FilterChainProxy proxy = this.spring.getContext().getBean(FilterChainProxy.class);
+		return proxy.getFilters("/");
+	}
+
+	private <T> 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<LogoutHandler> scaLogoutHandlers = getFieldValue(scaFilter, "logoutHandlers");
-		List<LogoutHandler> 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 extends Filter> T getFilter(Class<T> filterClass) {
-		return (T) getFilters().stream().filter(filterClass::isInstance).findFirst().orElse(null);
-	}
-
-	private List<Filter> getFilters() {
-		FilterChainProxy proxy = this.spring.getContext().getBean(FilterChainProxy.class);
-		return proxy.getFilters("/");
-	}
-
-	private <T> T getFieldValue(Object target, String fieldName) {
-		try {
-			return (T) FieldUtils.getFieldValue(target, fieldName);
-		}
-		catch (Exception e) {
-			throw new RuntimeException(e);
-		}
-	}
-
 }

+ 18 - 18
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());
-	}
-
 }

+ 20 - 20
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 {
 

+ 185 - 185
config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTests.java

@@ -90,6 +90,191 @@ public class SessionManagementConfigurerTests {
 				any(HttpServletResponse.class));
 	}
 
+	@Test
+	public void sessionManagementWhenConfiguredThenDoesNotOverrideSecurityContextRepository() throws Exception {
+		SessionManagementSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO = mock(SecurityContextRepository.class);
+		when(SessionManagementSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO
+				.loadContext(any(HttpRequestResponseHolder.class))).thenReturn(mock(SecurityContext.class));
+		this.spring.register(SessionManagementSecurityContextRepositoryConfig.class).autowire();
+
+		this.mvc.perform(get("/"));
+
+		verify(SessionManagementSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO)
+				.saveContext(any(SecurityContext.class), any(HttpServletRequest.class), any(HttpServletResponse.class));
+	}
+
+	@Test
+	public void sessionManagementWhenInvokedTwiceThenUsesOriginalSessionCreationPolicy() throws Exception {
+		this.spring.register(InvokeTwiceDoesNotOverride.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/")).andReturn();
+		HttpSession session = mvcResult.getRequest().getSession(false);
+
+		assertThat(session).isNull();
+	}
+
+	// SEC-2137
+	@Test
+	public void getWhenSessionFixationDisabledAndConcurrencyControlEnabledThenSessionIsNotInvalidated()
+			throws Exception {
+		this.spring.register(DisableSessionFixationEnableConcurrencyControlConfig.class).autowire();
+		MockHttpSession session = new MockHttpSession();
+		String sessionId = session.getId();
+
+		MvcResult mvcResult = this.mvc.perform(get("/").with(httpBasic("user", "password")).session(session))
+				.andExpect(status().isNotFound()).andReturn();
+
+		assertThat(mvcResult.getRequest().getSession().getId()).isEqualTo(sessionId);
+	}
+
+	@Test
+	public void authenticateWhenNewSessionFixationProtectionInLambdaThenCreatesNewSession() throws Exception {
+		this.spring.register(SFPNewSessionInLambdaConfig.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();
+	}
+
+	@Test
+	public void loginWhenUserLoggedInAndMaxSessionsIsOneThenLoginPrevented() throws Exception {
+		this.spring.register(ConcurrencyControlConfig.class).autowire();
+
+		this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"));
+
+		this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"))
+				.andExpect(status().isFound()).andExpect(redirectedUrl("/login?error"));
+	}
+
+	@Test
+	public void loginWhenUserSessionExpiredAndMaxSessionsIsOneThenLoggedIn() throws Exception {
+		this.spring.register(ConcurrencyControlConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc
+				.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"))
+				.andReturn();
+		HttpSession authenticatedSession = mvcResult.getRequest().getSession();
+		this.spring.getContext().publishEvent(new HttpSessionDestroyedEvent(authenticatedSession));
+
+		this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"))
+				.andExpect(status().isFound()).andExpect(redirectedUrl("/"));
+	}
+
+	@Test
+	public void loginWhenUserLoggedInAndMaxSessionsOneInLambdaThenLoginPrevented() throws Exception {
+		this.spring.register(ConcurrencyControlInLambdaConfig.class).autowire();
+
+		this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"));
+
+		this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"))
+				.andExpect(status().isFound()).andExpect(redirectedUrl("/login?error"));
+	}
+
+	@Test
+	public void requestWhenSessionCreationPolicyStateLessInLambdaThenNoSessionCreated() throws Exception {
+		this.spring.register(SessionCreationPolicyStateLessInLambdaConfig.class).autowire();
+
+		MvcResult mvcResult = this.mvc.perform(get("/")).andReturn();
+		HttpSession session = mvcResult.getRequest().getSession(false);
+
+		assertThat(session).isNull();
+	}
+
+	@Test
+	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnSessionManagementFilter() {
+		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
+		this.spring.register(ObjectPostProcessorConfig.class).autowire();
+
+		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(SessionManagementFilter.class));
+	}
+
+	@Test
+	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnConcurrentSessionFilter() {
+		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
+		this.spring.register(ObjectPostProcessorConfig.class).autowire();
+
+		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(ConcurrentSessionFilter.class));
+	}
+
+	@Test
+	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnConcurrentSessionControlAuthenticationStrategy() {
+		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
+		this.spring.register(ObjectPostProcessorConfig.class).autowire();
+
+		verify(ObjectPostProcessorConfig.objectPostProcessor)
+				.postProcess(any(ConcurrentSessionControlAuthenticationStrategy.class));
+	}
+
+	@Test
+	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnCompositeSessionAuthenticationStrategy() {
+		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
+		this.spring.register(ObjectPostProcessorConfig.class).autowire();
+
+		verify(ObjectPostProcessorConfig.objectPostProcessor)
+				.postProcess(any(CompositeSessionAuthenticationStrategy.class));
+	}
+
+	@Test
+	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnRegisterSessionAuthenticationStrategy() {
+		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
+		this.spring.register(ObjectPostProcessorConfig.class).autowire();
+
+		verify(ObjectPostProcessorConfig.objectPostProcessor)
+				.postProcess(any(RegisterSessionAuthenticationStrategy.class));
+	}
+
+	@Test
+	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnChangeSessionIdAuthenticationStrategy() {
+		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
+		this.spring.register(ObjectPostProcessorConfig.class).autowire();
+
+		verify(ObjectPostProcessorConfig.objectPostProcessor)
+				.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 {
 
@@ -109,19 +294,6 @@ public class SessionManagementConfigurerTests {
 
 	}
 
-	@Test
-	public void sessionManagementWhenConfiguredThenDoesNotOverrideSecurityContextRepository() throws Exception {
-		SessionManagementSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO = mock(SecurityContextRepository.class);
-		when(SessionManagementSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO
-				.loadContext(any(HttpRequestResponseHolder.class))).thenReturn(mock(SecurityContext.class));
-		this.spring.register(SessionManagementSecurityContextRepositoryConfig.class).autowire();
-
-		this.mvc.perform(get("/"));
-
-		verify(SessionManagementSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO)
-				.saveContext(any(SecurityContext.class), any(HttpServletRequest.class), any(HttpServletResponse.class));
-	}
-
 	@EnableWebSecurity
 	static class SessionManagementSecurityContextRepositoryConfig extends WebSecurityConfigurerAdapter {
 
@@ -141,16 +313,6 @@ public class SessionManagementConfigurerTests {
 
 	}
 
-	@Test
-	public void sessionManagementWhenInvokedTwiceThenUsesOriginalSessionCreationPolicy() throws Exception {
-		this.spring.register(InvokeTwiceDoesNotOverride.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/")).andReturn();
-		HttpSession session = mvcResult.getRequest().getSession(false);
-
-		assertThat(session).isNull();
-	}
-
 	@EnableWebSecurity
 	static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
 
@@ -167,20 +329,6 @@ public class SessionManagementConfigurerTests {
 
 	}
 
-	// SEC-2137
-	@Test
-	public void getWhenSessionFixationDisabledAndConcurrencyControlEnabledThenSessionIsNotInvalidated()
-			throws Exception {
-		this.spring.register(DisableSessionFixationEnableConcurrencyControlConfig.class).autowire();
-		MockHttpSession session = new MockHttpSession();
-		String sessionId = session.getId();
-
-		MvcResult mvcResult = this.mvc.perform(get("/").with(httpBasic("user", "password")).session(session))
-				.andExpect(status().isNotFound()).andReturn();
-
-		assertThat(mvcResult.getRequest().getSession().getId()).isEqualTo(sessionId);
-	}
-
 	@EnableWebSecurity
 	static class DisableSessionFixationEnableConcurrencyControlConfig extends WebSecurityConfigurerAdapter {
 
@@ -207,22 +355,6 @@ public class SessionManagementConfigurerTests {
 
 	}
 
-	@Test
-	public void authenticateWhenNewSessionFixationProtectionInLambdaThenCreatesNewSession() throws Exception {
-		this.spring.register(SFPNewSessionInLambdaConfig.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 SFPNewSessionInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -251,30 +383,6 @@ public class SessionManagementConfigurerTests {
 
 	}
 
-	@Test
-	public void loginWhenUserLoggedInAndMaxSessionsIsOneThenLoginPrevented() throws Exception {
-		this.spring.register(ConcurrencyControlConfig.class).autowire();
-
-		this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"));
-
-		this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"))
-				.andExpect(status().isFound()).andExpect(redirectedUrl("/login?error"));
-	}
-
-	@Test
-	public void loginWhenUserSessionExpiredAndMaxSessionsIsOneThenLoggedIn() throws Exception {
-		this.spring.register(ConcurrencyControlConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc
-				.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"))
-				.andReturn();
-		HttpSession authenticatedSession = mvcResult.getRequest().getSession();
-		this.spring.getContext().publishEvent(new HttpSessionDestroyedEvent(authenticatedSession));
-
-		this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"))
-				.andExpect(status().isFound()).andExpect(redirectedUrl("/"));
-	}
-
 	@EnableWebSecurity
 	static class ConcurrencyControlConfig extends WebSecurityConfigurerAdapter {
 
@@ -301,16 +409,6 @@ public class SessionManagementConfigurerTests {
 
 	}
 
-	@Test
-	public void loginWhenUserLoggedInAndMaxSessionsOneInLambdaThenLoginPrevented() throws Exception {
-		this.spring.register(ConcurrencyControlInLambdaConfig.class).autowire();
-
-		this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"));
-
-		this.mvc.perform(post("/login").with(csrf()).param("username", "user").param("password", "password"))
-				.andExpect(status().isFound()).andExpect(redirectedUrl("/login?error"));
-	}
-
 	@EnableWebSecurity
 	static class ConcurrencyControlInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -341,16 +439,6 @@ public class SessionManagementConfigurerTests {
 
 	}
 
-	@Test
-	public void requestWhenSessionCreationPolicyStateLessInLambdaThenNoSessionCreated() throws Exception {
-		this.spring.register(SessionCreationPolicyStateLessInLambdaConfig.class).autowire();
-
-		MvcResult mvcResult = this.mvc.perform(get("/")).andReturn();
-		HttpSession session = mvcResult.getRequest().getSession(false);
-
-		assertThat(session).isNull();
-	}
-
 	@EnableWebSecurity
 	static class SessionCreationPolicyStateLessInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -367,58 +455,6 @@ public class SessionManagementConfigurerTests {
 
 	}
 
-	@Test
-	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnSessionManagementFilter() {
-		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
-		this.spring.register(ObjectPostProcessorConfig.class).autowire();
-
-		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(SessionManagementFilter.class));
-	}
-
-	@Test
-	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnConcurrentSessionFilter() {
-		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
-		this.spring.register(ObjectPostProcessorConfig.class).autowire();
-
-		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(ConcurrentSessionFilter.class));
-	}
-
-	@Test
-	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnConcurrentSessionControlAuthenticationStrategy() {
-		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
-		this.spring.register(ObjectPostProcessorConfig.class).autowire();
-
-		verify(ObjectPostProcessorConfig.objectPostProcessor)
-				.postProcess(any(ConcurrentSessionControlAuthenticationStrategy.class));
-	}
-
-	@Test
-	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnCompositeSessionAuthenticationStrategy() {
-		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
-		this.spring.register(ObjectPostProcessorConfig.class).autowire();
-
-		verify(ObjectPostProcessorConfig.objectPostProcessor)
-				.postProcess(any(CompositeSessionAuthenticationStrategy.class));
-	}
-
-	@Test
-	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnRegisterSessionAuthenticationStrategy() {
-		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
-		this.spring.register(ObjectPostProcessorConfig.class).autowire();
-
-		verify(ObjectPostProcessorConfig.objectPostProcessor)
-				.postProcess(any(RegisterSessionAuthenticationStrategy.class));
-	}
-
-	@Test
-	public void configureWhenRegisteringObjectPostProcessorThenInvokedOnChangeSessionIdAuthenticationStrategy() {
-		ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
-		this.spring.register(ObjectPostProcessorConfig.class).autowire();
-
-		verify(ObjectPostProcessorConfig.objectPostProcessor)
-				.postProcess(any(ChangeSessionIdAuthenticationStrategy.class));
-	}
-
 	@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 {
 

+ 49 - 49
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,10 +141,24 @@ 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 MvcMatcherServletPathConfig extends WebSecurityConfigurerAdapter {
+	static class MvcMatcherConfig extends WebSecurityConfigurerAdapter {
 
 		@Override
 		protected void configure(HttpSecurity http) throws Exception {
@@ -187,7 +166,7 @@ public class UrlAuthorizationConfigurerTests {
 			http
 				.httpBasic().and()
 				.apply(new UrlAuthorizationConfigurer(getApplicationContext())).getRegistry()
-					.mvcMatchers("/path").servletPath("/spring").hasRole("ADMIN");
+					.mvcMatchers("/path").hasRole("ADMIN");
 			// @formatter:on
 		}
 
@@ -211,9 +190,39 @@ public class UrlAuthorizationConfigurerTests {
 
 	}
 
-	@Test
-	public void anonymousUrlAuthorization() {
-		loadConfig(AnonymousUrlAuthorizationConfig.class);
+	@EnableWebSecurity
+	@Configuration
+	@EnableWebMvc
+	static class MvcMatcherServletPathConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+				.httpBasic().and()
+				.apply(new UrlAuthorizationConfigurer(getApplicationContext())).getRegistry()
+					.mvcMatchers("/path").servletPath("/spring").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
@@ -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);
-	}
-
 }

+ 19 - 19
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 {
 

+ 34 - 34
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 extends Certificate> 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 extends Certificate> 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);
-		}
-	}
-
 }

+ 31 - 31
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<OAuth2AuthorizationCodeGrantRequest> createOauth2AccessTokenResponseClient() {
+		return request -> {
+			Map<String, Object> 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<OAuth2UserRequest, OAuth2User> createOauth2UserService() {
+		Map<String, Object> userAttributes = Collections.singletonMap("name", "spring");
+		return request -> new DefaultOAuth2User(Collections.singleton(new OAuth2UserAuthority(userAttributes)),
+				userAttributes, "name");
+	}
+
+	private static OAuth2UserService<OidcUserRequest, OidcUser> 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<GrantedAuthority> 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<AuthenticationSuccessEvent> {
@@ -985,35 +1016,4 @@ public class OAuth2LoginConfigurerTests {
 
 	}
 
-	private static OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> createOauth2AccessTokenResponseClient() {
-		return request -> {
-			Map<String, Object> 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<OAuth2UserRequest, OAuth2User> createOauth2UserService() {
-		Map<String, Object> userAttributes = Collections.singletonMap("name", "spring");
-		return request -> new DefaultOAuth2User(Collections.singleton(new OAuth2UserAuthority(userAttributes)),
-				userAttributes, "name");
-	}
-
-	private static OAuth2UserService<OidcUserRequest, OidcUser> 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<GrantedAuthority> mappedAuthorities = new ArrayList<>(authorities);
-			mappedAuthorities.add(new SimpleGrantedAuthority(isOidc ? "ROLE_OIDC_USER" : "ROLE_OAUTH2_USER"));
-			return mappedAuthorities;
-		};
-	}
-
 }

+ 83 - 85
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 <T> void registerMockBean(GenericApplicationContext context, String name, Class<T> 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<String, Object> 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<String> entity = new ResponseEntity<>(response, headers, HttpStatus.OK);
+		when(rest.exchange(any(RequestEntity.class), eq(String.class))).thenReturn(entity);
+	}
+
+	private <T> T bean(Class<T> beanClass) {
+		return this.spring.getContext().getBean(beanClass);
+	}
+
+	private <T> T verifyBean(Class<T> 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 <T> void registerMockBean(GenericApplicationContext context, String name, Class<T> 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<String, Object> 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<String> entity = new ResponseEntity<>(response, headers, HttpStatus.OK);
-		when(rest.exchange(any(RequestEntity.class), eq(String.class))).thenReturn(entity);
-	}
-
-	private <T> T bean(Class<T> beanClass) {
-		return this.spring.getContext().getBean(beanClass);
-	}
-
-	private <T> T verifyBean(Class<T> 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());
-		}
-	}
-
 }

+ 85 - 85
config/src/test/java/org/springframework/security/config/annotation/web/configurers/openid/OpenIDLoginConfigurerTests.java

@@ -83,6 +83,91 @@ public class OpenIDLoginConfigurerTests {
 		verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(OpenIDAuthenticationProvider.class));
 	}
 
+	@Test
+	public void openidLoginWhenInvokedTwiceThenUsesOriginalLoginPage() throws Exception {
+		this.spring.register(InvokeTwiceDoesNotOverrideConfig.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(status().isFound())
+				.andExpect(redirectedUrl("http://localhost/login/custom"));
+	}
+
+	@Test
+	public void requestWhenOpenIdLoginPageInLambdaThenRedirectsToLoginPAge() throws Exception {
+		this.spring.register(OpenIdLoginPageInLambdaConfig.class).autowire();
+
+		this.mvc.perform(get("/")).andExpect(status().isFound())
+				.andExpect(redirectedUrl("http://localhost/login/custom"));
+	}
+
+	@Test
+	public void requestWhenAttributeExchangeConfiguredThenFetchAttributesMatchAttributeList() throws Exception {
+		OpenIdAttributesInLambdaConfig.CONSUMER_MANAGER = mock(ConsumerManager.class);
+		AuthRequest mockAuthRequest = mock(AuthRequest.class);
+		DiscoveryInformation mockDiscoveryInformation = mock(DiscoveryInformation.class);
+		when(mockAuthRequest.getDestinationUrl(anyBoolean())).thenReturn("mockUrl");
+		when(OpenIdAttributesInLambdaConfig.CONSUMER_MANAGER.associate(any())).thenReturn(mockDiscoveryInformation);
+		when(OpenIdAttributesInLambdaConfig.CONSUMER_MANAGER.authenticate(any(DiscoveryInformation.class), any(),
+				any())).thenReturn(mockAuthRequest);
+		this.spring.register(OpenIdAttributesInLambdaConfig.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("<XRDS><XRD><Service><URI>%s</URI></Service></XRD></XRDS>", 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<OpenIDAttribute> attributeList = (List<OpenIDAttribute>) attributeObject;
+			assertThat(
+					attributeList.stream()
+							.anyMatch(attribute -> "nickname".equals(attribute.getName())
+									&& "https://schema.openid.net/namePerson/friendly".equals(attribute.getType())))
+											.isTrue();
+			assertThat(attributeList.stream()
+					.anyMatch(attribute -> "email".equals(attribute.getName())
+							&& "https://schema.openid.net/contact/email".equals(attribute.getType())
+							&& attribute.isRequired() && attribute.getCount() == 2)).isTrue();
+		}
+	}
+
+	@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("<XRDS><XRD><Service><URI>%s</URI></Service></XRD></XRDS>", 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<OpenIDAttribute> attributeList = (List<OpenIDAttribute>) attributeObject;
+			assertThat(attributeList).hasSize(1);
+			assertThat(attributeList.get(0).getName()).isEqualTo("default-attribute");
+		}
+	}
+
 	@EnableWebSecurity
 	static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
 
@@ -112,14 +197,6 @@ public class OpenIDLoginConfigurerTests {
 
 	}
 
-	@Test
-	public void openidLoginWhenInvokedTwiceThenUsesOriginalLoginPage() throws Exception {
-		this.spring.register(InvokeTwiceDoesNotOverrideConfig.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(status().isFound())
-				.andExpect(redirectedUrl("http://localhost/login/custom"));
-	}
-
 	@EnableWebSecurity
 	static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
 
@@ -147,14 +224,6 @@ public class OpenIDLoginConfigurerTests {
 
 	}
 
-	@Test
-	public void requestWhenOpenIdLoginPageInLambdaThenRedirectsToLoginPAge() throws Exception {
-		this.spring.register(OpenIdLoginPageInLambdaConfig.class).autowire();
-
-		this.mvc.perform(get("/")).andExpect(status().isFound())
-				.andExpect(redirectedUrl("http://localhost/login/custom"));
-	}
-
 	@EnableWebSecurity
 	static class OpenIdLoginPageInLambdaConfig extends WebSecurityConfigurerAdapter {
 
@@ -175,44 +244,6 @@ public class OpenIDLoginConfigurerTests {
 
 	}
 
-	@Test
-	public void requestWhenAttributeExchangeConfiguredThenFetchAttributesMatchAttributeList() throws Exception {
-		OpenIdAttributesInLambdaConfig.CONSUMER_MANAGER = mock(ConsumerManager.class);
-		AuthRequest mockAuthRequest = mock(AuthRequest.class);
-		DiscoveryInformation mockDiscoveryInformation = mock(DiscoveryInformation.class);
-		when(mockAuthRequest.getDestinationUrl(anyBoolean())).thenReturn("mockUrl");
-		when(OpenIdAttributesInLambdaConfig.CONSUMER_MANAGER.associate(any())).thenReturn(mockDiscoveryInformation);
-		when(OpenIdAttributesInLambdaConfig.CONSUMER_MANAGER.authenticate(any(DiscoveryInformation.class), any(),
-				any())).thenReturn(mockAuthRequest);
-		this.spring.register(OpenIdAttributesInLambdaConfig.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("<XRDS><XRD><Service><URI>%s</URI></Service></XRD></XRDS>", 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<OpenIDAttribute> attributeList = (List<OpenIDAttribute>) attributeObject;
-			assertThat(
-					attributeList.stream()
-							.anyMatch(attribute -> "nickname".equals(attribute.getName())
-									&& "https://schema.openid.net/namePerson/friendly".equals(attribute.getType())))
-											.isTrue();
-			assertThat(attributeList.stream()
-					.anyMatch(attribute -> "email".equals(attribute.getName())
-							&& "https://schema.openid.net/contact/email".equals(attribute.getType())
-							&& attribute.isRequired() && attribute.getCount() == 2)).isTrue();
-		}
-	}
-
 	@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("<XRDS><XRD><Service><URI>%s</URI></Service></XRD></XRDS>", 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<OpenIDAttribute> attributeList = (List<OpenIDAttribute>) attributeObject;
-			assertThat(attributeList).hasSize(1);
-			assertThat(attributeList.get(0).getName()).isEqualTo("default-attribute");
-		}
-	}
-
 	@EnableWebSecurity
 	static class OpenIdAttributesNullNameConfig extends WebSecurityConfigurerAdapter {
 

+ 38 - 38
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);
-		}
-	}
-
 }

部分文件因为文件数量过多而无法显示