Преглед изворни кода

SEC-2915: More Tabs -> Spaces

Rob Winch пре 10 година
родитељ
комит
4fdfb8caba
100 измењених фајлова са 9031 додато и 9031 уклоњено
  1. 76 76
      acl/src/test/resources/jdbcMutableAclServiceTests-context.xml
  2. 18 18
      cas/src/test/resources/org/springframework/security/cas/web/authentication/defaultserviceauthenticationdetails-explicit.xml
  3. 10 10
      cas/src/test/resources/org/springframework/security/cas/web/authentication/defaultserviceauthenticationdetails-passivity.xml
  4. 170 170
      config/src/integration-test/groovy/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderBuilderSecurityBuilderTests.groovy
  5. 19 19
      config/src/integration-test/groovy/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderConfigurerTests.groovy
  6. 38 38
      config/src/integration-test/groovy/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTests.groovy
  7. 157 157
      config/src/integration-test/groovy/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParserTests.groovy
  8. 111 111
      config/src/test/groovy/org/springframework/security/config/annotation/authentication/AuthenticationManagerBuilderTests.groovy
  9. 7 7
      config/src/test/groovy/org/springframework/security/config/annotation/authentication/BaseAuthenticationConfig.groovy
  10. 69 69
      config/src/test/groovy/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationManagerTests.groovy
  11. 42 42
      config/src/test/groovy/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationProviderTests.groovy
  12. 141 141
      config/src/test/groovy/org/springframework/security/config/annotation/authentication/NamespaceJdbcUserServiceTests.groovy
  13. 64 64
      config/src/test/groovy/org/springframework/security/config/annotation/authentication/NamespacePasswordEncoderTests.groovy
  14. 13 13
      config/src/test/groovy/org/springframework/security/config/annotation/authentication/PasswordEncoderConfigurerTests.groovy
  15. 316 316
      config/src/test/groovy/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationTests.groovy
  16. 96 96
      config/src/test/groovy/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessorTests.groovy
  17. 344 344
      config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.groovy
  18. 20 20
      config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/MethodSecurityService.groovy
  19. 40 40
      config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceImpl.groovy
  20. 46 46
      config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityExpressionHandlerTests.groovy
  21. 383 383
      config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityTests.groovy
  22. 71 71
      config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/SampleEnableGlobalMethodSecurityTests.groovy
  23. 61 61
      config/src/test/groovy/org/springframework/security/config/annotation/provisioning/UserDetailsManagerConfigurerTests.groovy
  24. 139 139
      config/src/test/groovy/org/springframework/security/config/annotation/web/AbstractConfiguredSecurityBuilderTests.groovy
  25. 267 267
      config/src/test/groovy/org/springframework/security/config/annotation/web/SampleWebSecurityConfigurerAdapterTests.groovy
  26. 236 236
      config/src/test/groovy/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterTests.groovy
  27. 70 70
      config/src/test/groovy/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.groovy
  28. 44 44
      config/src/test/groovy/org/springframework/security/config/annotation/web/configuration/EnableWebSecurityTests.groovy
  29. 291 291
      config/src/test/groovy/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.groovy
  30. 12 12
      config/src/test/groovy/org/springframework/security/config/annotation/web/configuration/sec2377/Sec2377Tests.groovy
  31. 33 33
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/AbstractConfigAttributeRequestMatcherRegistryTests.groovy
  32. 17 17
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/AnonymousConfigurerTests.groovy
  33. 38 38
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurerTests.groovy
  34. 424 424
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerTests.groovy
  35. 89 89
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/DefaultFiltersTests.groovy
  36. 249 249
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurerTests.groovy
  37. 149 149
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerTests.groovy
  38. 490 490
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationsTests.groovy
  39. 262 262
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurerTests.groovy
  40. 159 159
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerTests.groovy
  41. 85 85
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurerTests.groovy
  42. 31 31
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/JeeConfigurerTests.groovy
  43. 70 70
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/LogoutConfigurerTests.groovy
  44. 9 9
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceDebugTests.groovy
  45. 36 36
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpAccessDeniedHandlerTests.groovy
  46. 84 84
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpAnonymousTests.groovy
  47. 104 104
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpBasicTests.groovy
  48. 101 101
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpCustomFilterTests.groovy
  49. 21 21
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpExpressionHandlerTests.groovy
  50. 59 59
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFirewallTests.groovy
  51. 120 120
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFormLoginTests.groovy
  52. 203 203
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpHeadersTests.groovy
  53. 118 118
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpInterceptUrlTests.groovy
  54. 54 54
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpJeeTests.groovy
  55. 79 79
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.groovy
  56. 181 181
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpOpenIDLoginTests.groovy
  57. 68 68
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpPortMappingsTests.groovy
  58. 28 28
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpRequestCacheTests.groovy
  59. 197 197
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.groovy
  60. 329 329
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.groovy
  61. 31 31
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/PermitAllSupportTests.groovy
  62. 23 23
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurerTests.groovy
  63. 147 147
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.groovy
  64. 145 145
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.groovy
  65. 28 28
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/RequestMatcherConfigurerTests.groovy
  66. 32 32
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurerTests.groovy
  67. 112 112
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurerTests.groovy
  68. 39 39
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationsTests.groovy
  69. 25 25
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/X509ConfigurerTests.groovy
  70. 43 43
      config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/openid/OpenIDLoginConfigurerTests.groovy
  71. 14 14
      config/src/test/groovy/org/springframework/security/config/debug/SecurityDebugBeanFactoryPostProcessorTest.groovy
  72. 75 75
      config/src/test/groovy/org/springframework/security/config/http/FormLoginBeanDefinitionParserTests.groovy
  73. 97 97
      config/src/test/groovy/org/springframework/security/config/http/SecurityContextHolderAwareRequestConfigTests.groovy
  74. 17 17
      config/src/test/resources/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessorTests-aopconfig.xml
  75. 36 36
      core/src/test/resources/org/springframework/security/authentication/jaas/DefaultJaasAuthenticationProviderTests.xml
  76. 4 4
      itest/context/src/integration-test/resources/logback-test.xml
  77. 23 23
      itest/context/src/integration-test/resources/sec-933-app-context.xml
  78. 46 46
      itest/context/src/integration-test/resources/sec-936-app-context.xml
  79. 180 180
      itest/misc/src/integration-test/java/org/springframework/security/concurrent/SessionRegistryImplMTTests.java
  80. 197 197
      itest/misc/src/integration-test/java/org/springframework/security/context/SecurityContextHolderMTTests.java
  81. 4 4
      itest/web/src/integration-test/resources/logback-test.xml
  82. 8 8
      itest/web/src/main/webapp/WEB-INF/http-security-basic.xml
  83. 22 22
      itest/web/src/main/webapp/WEB-INF/http-security-concurrency.xml
  84. 51 51
      itest/web/src/main/webapp/WEB-INF/http-security-custom-concurrency.xml
  85. 15 15
      itest/web/src/main/webapp/WEB-INF/in-memory-provider.xml
  86. 37 37
      samples/aspectj-xml/src/main/resources/aspectj-context.xml
  87. 4 4
      samples/aspectj-xml/src/test/resources/logback-test.xml
  88. 77 77
      samples/cas/sample-xml/src/integration-test/groovy/org/springframework/security/samples/cas/CasSampleProxyTests.groovy
  89. 98 98
      samples/cas/sample-xml/src/integration-test/groovy/org/springframework/security/samples/cas/CasSampleTests.groovy
  90. 77 77
      samples/cas/sample-xml/src/integration-test/groovy/org/springframework/security/samples/cas/JettyCasService.groovy
  91. 4 4
      samples/cas/sample-xml/src/integration-test/groovy/org/springframework/security/samples/cas/modules/NavModule.groovy
  92. 1 1
      samples/cas/sample-xml/src/integration-test/groovy/org/springframework/security/samples/cas/pages/AccessDeniedPage.groovy
  93. 5 5
      samples/cas/sample-xml/src/integration-test/groovy/org/springframework/security/samples/cas/pages/ExtremelySecurePage.groovy
  94. 6 6
      samples/cas/sample-xml/src/integration-test/groovy/org/springframework/security/samples/cas/pages/HomePage.groovy
  95. 5 5
      samples/cas/sample-xml/src/integration-test/groovy/org/springframework/security/samples/cas/pages/LocalLogoutPage.groovy
  96. 19 19
      samples/cas/sample-xml/src/integration-test/groovy/org/springframework/security/samples/cas/pages/LoginPage.groovy
  97. 5 5
      samples/cas/sample-xml/src/integration-test/groovy/org/springframework/security/samples/cas/pages/ProxyTicketSamplePage.groovy
  98. 5 5
      samples/cas/sample-xml/src/integration-test/groovy/org/springframework/security/samples/cas/pages/SecurePage.groovy
  99. 4 4
      samples/cas/sample-xml/src/integration-test/resources/logback-test.xml
  100. 12 12
      samples/cas/server/src/main/webapp/WEB-INF/classes/log4j.xml

+ 76 - 76
acl/src/test/resources/jdbcMutableAclServiceTests-context.xml

@@ -9,94 +9,94 @@
   -->
 
 <beans>
-    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
-        <property name="dataSource" ref="dataSource"/>
-    </bean>
+	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
+		<property name="dataSource" ref="dataSource"/>
+	</bean>
 
-    <bean id="aclCache" class="org.springframework.security.acls.domain.EhCacheBasedAclCache">
-        <constructor-arg>
-           <bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
-              <property name="cacheManager">
-                <bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
-              </property>
-              <property name="cacheName" value="aclCache"/>
-           </bean>
-        </constructor-arg>
-        <constructor-arg>
-            <bean class="org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy">
-                <constructor-arg>
-                    <bean class="org.springframework.security.acls.domain.ConsoleAuditLogger"/>
-                </constructor-arg>
-            </bean>
-        </constructor-arg>
-        <constructor-arg>
-            <bean class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
-                <constructor-arg>
-                    <list>
-                        <bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
-                            <constructor-arg value="ROLE_USER"/>
-                        </bean>
-                    </list>
-                </constructor-arg>
-            </bean>
-        </constructor-arg>
+	<bean id="aclCache" class="org.springframework.security.acls.domain.EhCacheBasedAclCache">
+		<constructor-arg>
+		   <bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
+			  <property name="cacheManager">
+				<bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
+			  </property>
+			  <property name="cacheName" value="aclCache"/>
+		   </bean>
+		</constructor-arg>
+		<constructor-arg>
+			<bean class="org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy">
+				<constructor-arg>
+					<bean class="org.springframework.security.acls.domain.ConsoleAuditLogger"/>
+				</constructor-arg>
+			</bean>
+		</constructor-arg>
+		<constructor-arg>
+			<bean class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
+				<constructor-arg>
+					<list>
+						<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
+							<constructor-arg value="ROLE_USER"/>
+						</bean>
+					</list>
+				</constructor-arg>
+			</bean>
+		</constructor-arg>
 
-    </bean>
+	</bean>
 
-    <bean id="lookupStrategy" class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
-        <constructor-arg ref="dataSource"/>
-        <constructor-arg ref="aclCache"/>
-        <constructor-arg ref="aclAuthorizationStrategy"/>
-        <constructor-arg>
-            <bean class="org.springframework.security.acls.domain.ConsoleAuditLogger"/>
-        </constructor-arg>
-    </bean>
+	<bean id="lookupStrategy" class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
+		<constructor-arg ref="dataSource"/>
+		<constructor-arg ref="aclCache"/>
+		<constructor-arg ref="aclAuthorizationStrategy"/>
+		<constructor-arg>
+			<bean class="org.springframework.security.acls.domain.ConsoleAuditLogger"/>
+		</constructor-arg>
+	</bean>
 
-    <bean id="aclAuthorizationStrategy" class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
-        <constructor-arg>
-            <list>
-                <bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
-                    <constructor-arg value="ROLE_ADMINISTRATOR"/>
-                </bean>
-                <bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
-                    <constructor-arg value="ROLE_ADMINISTRATOR"/>
-                </bean>
-                <bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
-                    <constructor-arg value="ROLE_ADMINISTRATOR"/>
-                </bean>
-            </list>
-        </constructor-arg>
-    </bean>
+	<bean id="aclAuthorizationStrategy" class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
+		<constructor-arg>
+			<list>
+				<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
+					<constructor-arg value="ROLE_ADMINISTRATOR"/>
+				</bean>
+				<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
+					<constructor-arg value="ROLE_ADMINISTRATOR"/>
+				</bean>
+				<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
+					<constructor-arg value="ROLE_ADMINISTRATOR"/>
+				</bean>
+			</list>
+		</constructor-arg>
+	</bean>
 
-    <bean id="aclService" class="org.springframework.security.acls.jdbc.JdbcMutableAclService">
-        <constructor-arg ref="dataSource"/>
-        <constructor-arg ref="lookupStrategy"/>
-        <constructor-arg ref="aclCache"/>
+	<bean id="aclService" class="org.springframework.security.acls.jdbc.JdbcMutableAclService">
+		<constructor-arg ref="dataSource"/>
+		<constructor-arg ref="lookupStrategy"/>
+		<constructor-arg ref="aclCache"/>
 
 <!-- Uncomment to use PostgreSQL
-        <property name="classIdentityQuery" value="select currval(pg_get_serial_sequence('acl_class', 'id'))"/>
-        <property name="sidIdentityQuery" value="select currval(pg_get_serial_sequence('acl_sid', 'id'))"/>
+		<property name="classIdentityQuery" value="select currval(pg_get_serial_sequence('acl_class', 'id'))"/>
+		<property name="sidIdentityQuery" value="select currval(pg_get_serial_sequence('acl_sid', 'id'))"/>
  -->
-    </bean>
+	</bean>
 
 <!-- PostgreSQL DataSource configuration
 
-    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
-        <property name="driverClassName" value="org.postgresql.Driver"/>
-        <property name="url" value="jdbc:postgresql://localhost:5432/acltest"/>
-        <property name="username" value="acltest"/>
-        <property name="password" value="acltest"/>
-    </bean>
+	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
+		<property name="driverClassName" value="org.postgresql.Driver"/>
+		<property name="url" value="jdbc:postgresql://localhost:5432/acltest"/>
+		<property name="username" value="acltest"/>
+		<property name="password" value="acltest"/>
+	</bean>
  -->
-    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
-        <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
-        <property name="url" value="jdbc:hsqldb:mem:acltest"/>
-        <property name="username" value="sa"/>
-        <property name="password" value=""/>
-    </bean>
+	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
+		<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
+		<property name="url" value="jdbc:hsqldb:mem:acltest"/>
+		<property name="username" value="sa"/>
+		<property name="password" value=""/>
+	</bean>
 
-    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
-        <property name="dataSource" ref="dataSource"/>
-    </bean>
+	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
+		<property name="dataSource" ref="dataSource"/>
+	</bean>
 
 </beans>

+ 18 - 18
cas/src/test/resources/org/springframework/security/cas/web/authentication/defaultserviceauthenticationdetails-explicit.xml

@@ -1,23 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
-       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
-       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
+	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	   xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
+	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
 
-    <bean id="serviceProperties"
-          class="org.springframework.security.cas.ServiceProperties">
-        <property name="service"
-                  value="https://example.com/j_spring_security_cas"/>
-        <property name="sendRenew" value="false"/>
-    </bean>
-    <bean id="serviceProperties2"
-          class="org.springframework.security.cas.ServiceProperties">
-        <property name="service"
-                  value="https://example2.com/j_spring_security_cas"/>
-        <property name="sendRenew" value="false"/>
-    </bean>
+	<bean id="serviceProperties"
+		  class="org.springframework.security.cas.ServiceProperties">
+		<property name="service"
+				  value="https://example.com/j_spring_security_cas"/>
+		<property name="sendRenew" value="false"/>
+	</bean>
+	<bean id="serviceProperties2"
+		  class="org.springframework.security.cas.ServiceProperties">
+		<property name="service"
+				  value="https://example2.com/j_spring_security_cas"/>
+		<property name="sendRenew" value="false"/>
+	</bean>
 
-    <bean class="org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource">
-        <constructor-arg ref="serviceProperties"/>
-    </bean>
+	<bean class="org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource">
+		<constructor-arg ref="serviceProperties"/>
+	</bean>
 </beans>

+ 10 - 10
cas/src/test/resources/org/springframework/security/cas/web/authentication/defaultserviceauthenticationdetails-passivity.xml

@@ -1,15 +1,15 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
-       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
-       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
+	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	   xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
+	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
 
-    <bean id="serviceProperties"
-          class="org.springframework.security.cas.ServiceProperties">
-        <property name="service"
-                  value="https://example.com/j_spring_security_cas"/>
-        <property name="sendRenew" value="false"/>
-    </bean>
+	<bean id="serviceProperties"
+		  class="org.springframework.security.cas.ServiceProperties">
+		<property name="service"
+				  value="https://example.com/j_spring_security_cas"/>
+		<property name="sendRenew" value="false"/>
+	</bean>
 
-    <bean class="org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource"/>
+	<bean class="org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource"/>
 </beans>

+ 170 - 170
config/src/integration-test/groovy/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderBuilderSecurityBuilderTests.groovy

@@ -47,174 +47,174 @@ import org.springframework.test.util.ReflectionTestUtils;
  *
  */
 class LdapAuthenticationProviderBuilderSecurityBuilderTests extends BaseSpringSpec {
-    def "default configuration"() {
-        when:
-        loadConfig(DefaultLdapConfig)
-        LdapAuthenticationProvider provider = ldapProvider()
-        then:
-        provider.authoritiesPopulator.groupRoleAttribute == "cn"
-        provider.authoritiesPopulator.groupSearchBase == ""
-        provider.authoritiesPopulator.groupSearchFilter == "(uniqueMember={0})"
-        ReflectionTestUtils.getField(provider,"authoritiesMapper").prefix == "ROLE_"
-
-    }
-
-    @Configuration
-    static class DefaultLdapConfig extends BaseLdapProviderConfig {
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .ldapAuthentication()
-                    .contextSource(contextSource())
-                    .userDnPatterns("uid={0},ou=people")
-        }
-    }
-
-    def "group roles custom"() {
-        when:
-        loadConfig(GroupRolesConfig)
-        LdapAuthenticationProvider provider = ldapProvider()
-        then:
-        provider.authoritiesPopulator.groupRoleAttribute == "group"
-    }
-
-    @Configuration
-    static class GroupRolesConfig extends BaseLdapProviderConfig {
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .ldapAuthentication()
-                    .contextSource(contextSource())
-                    .userDnPatterns("uid={0},ou=people")
-                    .groupRoleAttribute("group")
-        }
-    }
-
-    def "group search custom"() {
-        when:
-        loadConfig(GroupSearchConfig)
-        LdapAuthenticationProvider provider = ldapProvider()
-        then:
-        provider.authoritiesPopulator.groupSearchFilter == "ou=groupName"
-    }
-
-    @Configuration
-    static class GroupSearchConfig extends BaseLdapProviderConfig {
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .ldapAuthentication()
-                    .contextSource(contextSource())
-                    .userDnPatterns("uid={0},ou=people")
-                    .groupSearchFilter("ou=groupName");
-        }
-    }
-
-    def "role prefix custom"() {
-        when:
-        loadConfig(RolePrefixConfig)
-        LdapAuthenticationProvider provider = ldapProvider()
-        then:
-        ReflectionTestUtils.getField(provider,"authoritiesMapper").prefix == "role_"
-    }
-
-    @Configuration
-    static class RolePrefixConfig extends BaseLdapProviderConfig {
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .ldapAuthentication()
-                    .contextSource(contextSource())
-                    .userDnPatterns("uid={0},ou=people")
-                    .rolePrefix("role_")
-        }
-    }
-
-    def "bind authentication"() {
-        when:
-        loadConfig(BindAuthenticationConfig)
-        AuthenticationManager auth = context.getBean(AuthenticationManager)
-        then:
-        auth
-        auth.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword")).authorities.collect { it.authority }.sort() == ["ROLE_DEVELOPERS"]
-    }
-
-    @Configuration
-    static class BindAuthenticationConfig extends BaseLdapServerConfig {
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .ldapAuthentication()
-                    .contextSource(contextSource())
-                    .groupSearchBase("ou=groups")
-                    .groupSearchFilter("(member={0})")
-                    .userDnPatterns("uid={0},ou=people");
-        }
-    }
-
-    def "SEC-2472: Can use crypto PasswordEncoder"() {
-        setup:
-        loadConfig(PasswordEncoderConfig)
-        when:
-        AuthenticationManager auth = context.getBean(AuthenticationManager)
-        then:
-        auth.authenticate(new UsernamePasswordAuthenticationToken("bcrypt","password")).authorities.collect { it.authority }.sort() == ["ROLE_DEVELOPERS"]
-    }
-
-    @Configuration
-    static class PasswordEncoderConfig extends BaseLdapServerConfig {
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .ldapAuthentication()
-                    .contextSource(contextSource())
-                    .passwordEncoder(new BCryptPasswordEncoder())
-                    .groupSearchBase("ou=groups")
-                    .groupSearchFilter("(member={0})")
-                    .userDnPatterns("uid={0},ou=people");
-        }
-    }
-
-    def ldapProvider() {
-        context.getBean(AuthenticationManager).providers[0]
-    }
-
-    @Configuration
-    static abstract class BaseLdapServerConfig extends BaseLdapProviderConfig {
-        @Bean
-        public ApacheDSContainer ldapServer() throws Exception {
-            ApacheDSContainer apacheDSContainer = new ApacheDSContainer("dc=springframework,dc=org", "classpath:/test-server.ldif");
-            apacheDSContainer.setPort(getPort());
-            return apacheDSContainer;
-        }
-    }
-
-    @Configuration
-    @EnableGlobalAuthentication
-    @Import(ObjectPostProcessorConfiguration)
-    static abstract class BaseLdapProviderConfig {
-
-        @Bean
-        public BaseLdapPathContextSource contextSource() throws Exception {
-            DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(
-                    "ldap://127.0.0.1:"+ getPort() + "/dc=springframework,dc=org")
-            contextSource.userDn = "uid=admin,ou=system"
-            contextSource.password = "secret"
-            contextSource.afterPropertiesSet()
-            return contextSource;
-        }
-
-        @Bean
-        public AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth) {
-            configure(auth)
-            auth.build()
-        }
-
-        abstract protected void configure(AuthenticationManagerBuilder auth) throws Exception
-    }
-
-    static Integer port;
-
-    static int getPort() {
-        if(port == null) {
-            ServerSocket socket = new ServerSocket(0)
-            port = socket.localPort
-            socket.close()
-        }
-        port
-    }
+	def "default configuration"() {
+		when:
+		loadConfig(DefaultLdapConfig)
+		LdapAuthenticationProvider provider = ldapProvider()
+		then:
+		provider.authoritiesPopulator.groupRoleAttribute == "cn"
+		provider.authoritiesPopulator.groupSearchBase == ""
+		provider.authoritiesPopulator.groupSearchFilter == "(uniqueMember={0})"
+		ReflectionTestUtils.getField(provider,"authoritiesMapper").prefix == "ROLE_"
+
+	}
+
+	@Configuration
+	static class DefaultLdapConfig extends BaseLdapProviderConfig {
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.ldapAuthentication()
+					.contextSource(contextSource())
+					.userDnPatterns("uid={0},ou=people")
+		}
+	}
+
+	def "group roles custom"() {
+		when:
+		loadConfig(GroupRolesConfig)
+		LdapAuthenticationProvider provider = ldapProvider()
+		then:
+		provider.authoritiesPopulator.groupRoleAttribute == "group"
+	}
+
+	@Configuration
+	static class GroupRolesConfig extends BaseLdapProviderConfig {
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.ldapAuthentication()
+					.contextSource(contextSource())
+					.userDnPatterns("uid={0},ou=people")
+					.groupRoleAttribute("group")
+		}
+	}
+
+	def "group search custom"() {
+		when:
+		loadConfig(GroupSearchConfig)
+		LdapAuthenticationProvider provider = ldapProvider()
+		then:
+		provider.authoritiesPopulator.groupSearchFilter == "ou=groupName"
+	}
+
+	@Configuration
+	static class GroupSearchConfig extends BaseLdapProviderConfig {
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.ldapAuthentication()
+					.contextSource(contextSource())
+					.userDnPatterns("uid={0},ou=people")
+					.groupSearchFilter("ou=groupName");
+		}
+	}
+
+	def "role prefix custom"() {
+		when:
+		loadConfig(RolePrefixConfig)
+		LdapAuthenticationProvider provider = ldapProvider()
+		then:
+		ReflectionTestUtils.getField(provider,"authoritiesMapper").prefix == "role_"
+	}
+
+	@Configuration
+	static class RolePrefixConfig extends BaseLdapProviderConfig {
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.ldapAuthentication()
+					.contextSource(contextSource())
+					.userDnPatterns("uid={0},ou=people")
+					.rolePrefix("role_")
+		}
+	}
+
+	def "bind authentication"() {
+		when:
+		loadConfig(BindAuthenticationConfig)
+		AuthenticationManager auth = context.getBean(AuthenticationManager)
+		then:
+		auth
+		auth.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword")).authorities.collect { it.authority }.sort() == ["ROLE_DEVELOPERS"]
+	}
+
+	@Configuration
+	static class BindAuthenticationConfig extends BaseLdapServerConfig {
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.ldapAuthentication()
+					.contextSource(contextSource())
+					.groupSearchBase("ou=groups")
+					.groupSearchFilter("(member={0})")
+					.userDnPatterns("uid={0},ou=people");
+		}
+	}
+
+	def "SEC-2472: Can use crypto PasswordEncoder"() {
+		setup:
+		loadConfig(PasswordEncoderConfig)
+		when:
+		AuthenticationManager auth = context.getBean(AuthenticationManager)
+		then:
+		auth.authenticate(new UsernamePasswordAuthenticationToken("bcrypt","password")).authorities.collect { it.authority }.sort() == ["ROLE_DEVELOPERS"]
+	}
+
+	@Configuration
+	static class PasswordEncoderConfig extends BaseLdapServerConfig {
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.ldapAuthentication()
+					.contextSource(contextSource())
+					.passwordEncoder(new BCryptPasswordEncoder())
+					.groupSearchBase("ou=groups")
+					.groupSearchFilter("(member={0})")
+					.userDnPatterns("uid={0},ou=people");
+		}
+	}
+
+	def ldapProvider() {
+		context.getBean(AuthenticationManager).providers[0]
+	}
+
+	@Configuration
+	static abstract class BaseLdapServerConfig extends BaseLdapProviderConfig {
+		@Bean
+		public ApacheDSContainer ldapServer() throws Exception {
+			ApacheDSContainer apacheDSContainer = new ApacheDSContainer("dc=springframework,dc=org", "classpath:/test-server.ldif");
+			apacheDSContainer.setPort(getPort());
+			return apacheDSContainer;
+		}
+	}
+
+	@Configuration
+	@EnableGlobalAuthentication
+	@Import(ObjectPostProcessorConfiguration)
+	static abstract class BaseLdapProviderConfig {
+
+		@Bean
+		public BaseLdapPathContextSource contextSource() throws Exception {
+			DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(
+					"ldap://127.0.0.1:"+ getPort() + "/dc=springframework,dc=org")
+			contextSource.userDn = "uid=admin,ou=system"
+			contextSource.password = "secret"
+			contextSource.afterPropertiesSet()
+			return contextSource;
+		}
+
+		@Bean
+		public AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth) {
+			configure(auth)
+			auth.build()
+		}
+
+		abstract protected void configure(AuthenticationManagerBuilder auth) throws Exception
+	}
+
+	static Integer port;
+
+	static int getPort() {
+		if(port == null) {
+			ServerSocket socket = new ServerSocket(0)
+			port = socket.localPort
+			socket.close()
+		}
+		port
+	}
 }

+ 19 - 19
config/src/integration-test/groovy/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderConfigurerTests.groovy

@@ -37,24 +37,24 @@ import static org.springframework.security.config.annotation.authentication.ldap
  */
 class LdapAuthenticationProviderConfigurerTests extends BaseSpringSpec {
 
-    def "authentication-manager support multiple default ldap contexts (ports dynamically allocated)"() {
-        when:
-            loadConfig(MultiLdapAuthenticationProvidersConfig)
-        then:
-            authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword"))
-    }
+	def "authentication-manager support multiple default ldap contexts (ports dynamically allocated)"() {
+		when:
+			loadConfig(MultiLdapAuthenticationProvidersConfig)
+		then:
+			authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword"))
+	}
 
-    @EnableWebSecurity
-    static class MultiLdapAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter {
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .ldapAuthentication()
-                    .groupSearchBase("ou=groups")
-                    .userDnPatterns("uid={0},ou=people")
-                    .and()
-                .ldapAuthentication()
-                    .groupSearchBase("ou=groups")
-                    .userDnPatterns("uid={0},ou=people")
-        }
-    }
+	@EnableWebSecurity
+	static class MultiLdapAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter {
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.ldapAuthentication()
+					.groupSearchBase("ou=groups")
+					.userDnPatterns("uid={0},ou=people")
+					.and()
+				.ldapAuthentication()
+					.groupSearchBase("ou=groups")
+					.userDnPatterns("uid={0},ou=people")
+		}
+	}
 }

+ 38 - 38
config/src/integration-test/groovy/org/springframework/security/config/annotation/authentication/ldap/NamespaceLdapAuthenticationProviderTests.groovy

@@ -36,45 +36,45 @@ import org.springframework.test.util.ReflectionTestUtils;
  *
  */
 class NamespaceLdapAuthenticationProviderTests extends BaseSpringSpec {
-    def "ldap-authentication-provider"() {
-        when:
-            loadConfig(LdapAuthenticationProviderConfig)
-        then:
-            authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword"))
-    }
+	def "ldap-authentication-provider"() {
+		when:
+			loadConfig(LdapAuthenticationProviderConfig)
+		then:
+			authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword"))
+	}
 
-    def "ldap-authentication-provider custom"() {
-        when:
-            loadConfig(CustomLdapAuthenticationProviderConfig)
-            LdapAuthenticationProvider provider = findAuthenticationProvider(LdapAuthenticationProvider)
-        then:
-            provider.authoritiesPopulator.groupRoleAttribute == "cn"
-            provider.authoritiesPopulator.groupSearchBase == "ou=groups"
-            provider.authoritiesPopulator.groupSearchFilter == "(member={0})"
-            ReflectionTestUtils.getField(provider,"authoritiesMapper").prefix == "PREFIX_"
-            provider.userDetailsContextMapper instanceof PersonContextMapper
-            provider.authenticator.getUserDns("user") == ["uid=user,ou=people"]
-            provider.authenticator.userSearch.searchBase == "ou=users"
-            provider.authenticator.userSearch.searchFilter == "(uid={0})"
-    }
+	def "ldap-authentication-provider custom"() {
+		when:
+			loadConfig(CustomLdapAuthenticationProviderConfig)
+			LdapAuthenticationProvider provider = findAuthenticationProvider(LdapAuthenticationProvider)
+		then:
+			provider.authoritiesPopulator.groupRoleAttribute == "cn"
+			provider.authoritiesPopulator.groupSearchBase == "ou=groups"
+			provider.authoritiesPopulator.groupSearchFilter == "(member={0})"
+			ReflectionTestUtils.getField(provider,"authoritiesMapper").prefix == "PREFIX_"
+			provider.userDetailsContextMapper instanceof PersonContextMapper
+			provider.authenticator.getUserDns("user") == ["uid=user,ou=people"]
+			provider.authenticator.userSearch.searchBase == "ou=users"
+			provider.authenticator.userSearch.searchFilter == "(uid={0})"
+	}
 
-    def "SEC-2490: ldap-authentication-provider custom LdapAuthoritiesPopulator"() {
-        setup:
-            LdapAuthoritiesPopulator LAP = Mock()
-            CustomAuthoritiesPopulatorConfig.LAP = LAP
-        when:
-            loadConfig(CustomAuthoritiesPopulatorConfig)
-            LdapAuthenticationProvider provider = findAuthenticationProvider(LdapAuthenticationProvider)
-        then:
-            provider.authoritiesPopulator == LAP
-    }
+	def "SEC-2490: ldap-authentication-provider custom LdapAuthoritiesPopulator"() {
+		setup:
+			LdapAuthoritiesPopulator LAP = Mock()
+			CustomAuthoritiesPopulatorConfig.LAP = LAP
+		when:
+			loadConfig(CustomAuthoritiesPopulatorConfig)
+			LdapAuthenticationProvider provider = findAuthenticationProvider(LdapAuthenticationProvider)
+		then:
+			provider.authoritiesPopulator == LAP
+	}
 
-    def "ldap-authentication-provider password compare"() {
-        when:
-            loadConfig(PasswordCompareLdapConfig)
-            LdapAuthenticationProvider provider = findAuthenticationProvider(LdapAuthenticationProvider)
-        then:
-            provider.authenticator instanceof PasswordComparisonAuthenticator
-            authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword"))
-    }
+	def "ldap-authentication-provider password compare"() {
+		when:
+			loadConfig(PasswordCompareLdapConfig)
+			LdapAuthenticationProvider provider = findAuthenticationProvider(LdapAuthenticationProvider)
+		then:
+			provider.authenticator instanceof PasswordComparisonAuthenticator
+			authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("bob","bobspassword"))
+	}
 }

+ 157 - 157
config/src/integration-test/groovy/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParserTests.groovy

@@ -21,161 +21,161 @@ import org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper
  */
 class LdapProviderBeanDefinitionParserTests extends AbstractXmlConfigTests {
 
-    // SEC-1182
-    def multipleProvidersAreSupported() {
-        xml.'ldap-server'(url: 'ldap://blah:389/dc=blah')
-        xml.'authentication-manager'() {
-            'ldap-authentication-provider'('group-search-filter': 'member={0}')
-            'ldap-authentication-provider'('group-search-filter': 'uniqueMember={0}')
-        }
-
-        createAppContext('')
-
-        def providers = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER).providers
-
-        expect:
-
-        providers.size() == 2
-        providers[0].authoritiesPopulator.groupSearchFilter == "member={0}"
-        providers[1].authoritiesPopulator.groupSearchFilter == "uniqueMember={0}"
-    }
-
-
-    def simpleProviderAuthenticatesCorrectly() {
-        xml.'ldap-server'(ldif:'test-server.ldif')
-        xml.'authentication-manager'{
-            'ldap-authentication-provider'('group-search-filter':'member={0}')
-        }
-
-        createAppContext('')
-
-        def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
-
-        when:
-        def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword"))
-        def ben =  auth.principal;
-
-        then:
-        ben.authorities.size() == 3
-    }
-
-    def missingServerEltCausesConfigException() {
-        xml.'authentication-manager'{
-            'ldap-authentication-provider'()
-        }
-
-        when:
-        createAppContext('')
-
-        then:
-        thrown(ApplicationContextException)
-    }
-
-    def supportsPasswordComparisonAuthentication() {
-        xml.'ldap-server'(ldif:'test-server.ldif')
-        xml.'authentication-manager'{
-            'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people')
-            'password-compare'
-        }
-        createAppContext('')
-        def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
-
-        when:
-        def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword"))
-
-        then:
-        auth != null
-        notThrown(AuthenticationException)
-    }
-
-    def supportsPasswordComparisonAuthenticationWithHashAttribute() {
-        xml.'ldap-server'(ldif:'test-server.ldif')
-        xml.'authentication-manager'{
-            'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') {
-                'password-compare'('password-attribute': 'uid', hash: 'plaintext')
-            }
-        }
-        createAppContext('')
-        def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
-
-        when:
-        def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben"))
-
-        then:
-        auth != null
-        notThrown(AuthenticationException)
-
-    }
-
-    def supportsPasswordComparisonAuthenticationWithPasswordEncoder() {
-        xml.'ldap-server'(ldif:'test-server.ldif')
-        xml.'authentication-manager'{
-            'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') {
-                'password-compare'('password-attribute': 'uid') {
-                    'password-encoder'(hash: 'plaintext')
-                }
-            }
-        }
-
-        createAppContext('')
-        def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
-
-        when:
-        def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben"))
-
-        then:
-        auth != null
-        notThrown(AuthenticationException)
-    }
-
-    def 'SEC-2472: Supports Crypto PasswordEncoder'() {
-        setup:
-        xml.'ldap-server'(ldif:'test-server.ldif')
-        xml.'authentication-manager'{
-            'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') {
-                'password-compare'() {
-                    'password-encoder'(ref: 'pe')
-                }
-            }
-        }
-        xml.'b:bean'(id:'pe','class':BCryptPasswordEncoder.class.name)
-
-        createAppContext('')
-        def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
-
-        when:
-        def auth = am.authenticate(new UsernamePasswordAuthenticationToken("bcrypt", 'password'))
-
-        then:
-        auth != null
-    }
-
-    def inetOrgContextMapperIsSupported()  {
-        xml.'ldap-server'(url: 'ldap://127.0.0.1:343/dc=springframework,dc=org')
-        xml.'authentication-manager'{
-            'ldap-authentication-provider'('user-details-class' :'inetOrgPerson')
-        }
-        createAppContext('')
-
-        expect:
-        appContext.getBean(BeanIds.AUTHENTICATION_MANAGER).providers[0].userDetailsContextMapper instanceof InetOrgPersonContextMapper
-    }
-
-    def ldapAuthenticationProviderWorksWithPlaceholders() {
-        System.setProperty('udp','people')
-        System.setProperty('gsf','member')
-
-        xml.'ldap-server'()
-        xml.'authentication-manager'{
-            'ldap-authentication-provider'('user-dn-pattern':'uid={0},ou=${udp}','group-search-filter':'${gsf}={0}')
-        }
-        bean(PropertyPlaceholderConfigurer.class.name, PropertyPlaceholderConfigurer.class)
-
-        createAppContext('')
-        def provider = this.appContext.getBean(BeanIds.AUTHENTICATION_MANAGER).providers[0]
-
-        expect:
-        [new MessageFormat("uid={0},ou=people")] == FieldUtils.getFieldValue(provider,"authenticator.userDnFormat")
-        "member={0}" == FieldUtils.getFieldValue(provider, "authoritiesPopulator.groupSearchFilter")
-    }
+	// SEC-1182
+	def multipleProvidersAreSupported() {
+		xml.'ldap-server'(url: 'ldap://blah:389/dc=blah')
+		xml.'authentication-manager'() {
+			'ldap-authentication-provider'('group-search-filter': 'member={0}')
+			'ldap-authentication-provider'('group-search-filter': 'uniqueMember={0}')
+		}
+
+		createAppContext('')
+
+		def providers = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER).providers
+
+		expect:
+
+		providers.size() == 2
+		providers[0].authoritiesPopulator.groupSearchFilter == "member={0}"
+		providers[1].authoritiesPopulator.groupSearchFilter == "uniqueMember={0}"
+	}
+
+
+	def simpleProviderAuthenticatesCorrectly() {
+		xml.'ldap-server'(ldif:'test-server.ldif')
+		xml.'authentication-manager'{
+			'ldap-authentication-provider'('group-search-filter':'member={0}')
+		}
+
+		createAppContext('')
+
+		def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
+
+		when:
+		def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword"))
+		def ben =  auth.principal;
+
+		then:
+		ben.authorities.size() == 3
+	}
+
+	def missingServerEltCausesConfigException() {
+		xml.'authentication-manager'{
+			'ldap-authentication-provider'()
+		}
+
+		when:
+		createAppContext('')
+
+		then:
+		thrown(ApplicationContextException)
+	}
+
+	def supportsPasswordComparisonAuthentication() {
+		xml.'ldap-server'(ldif:'test-server.ldif')
+		xml.'authentication-manager'{
+			'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people')
+			'password-compare'
+		}
+		createAppContext('')
+		def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
+
+		when:
+		def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword"))
+
+		then:
+		auth != null
+		notThrown(AuthenticationException)
+	}
+
+	def supportsPasswordComparisonAuthenticationWithHashAttribute() {
+		xml.'ldap-server'(ldif:'test-server.ldif')
+		xml.'authentication-manager'{
+			'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') {
+				'password-compare'('password-attribute': 'uid', hash: 'plaintext')
+			}
+		}
+		createAppContext('')
+		def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
+
+		when:
+		def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben"))
+
+		then:
+		auth != null
+		notThrown(AuthenticationException)
+
+	}
+
+	def supportsPasswordComparisonAuthenticationWithPasswordEncoder() {
+		xml.'ldap-server'(ldif:'test-server.ldif')
+		xml.'authentication-manager'{
+			'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') {
+				'password-compare'('password-attribute': 'uid') {
+					'password-encoder'(hash: 'plaintext')
+				}
+			}
+		}
+
+		createAppContext('')
+		def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
+
+		when:
+		def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben"))
+
+		then:
+		auth != null
+		notThrown(AuthenticationException)
+	}
+
+	def 'SEC-2472: Supports Crypto PasswordEncoder'() {
+		setup:
+		xml.'ldap-server'(ldif:'test-server.ldif')
+		xml.'authentication-manager'{
+			'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') {
+				'password-compare'() {
+					'password-encoder'(ref: 'pe')
+				}
+			}
+		}
+		xml.'b:bean'(id:'pe','class':BCryptPasswordEncoder.class.name)
+
+		createAppContext('')
+		def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER)
+
+		when:
+		def auth = am.authenticate(new UsernamePasswordAuthenticationToken("bcrypt", 'password'))
+
+		then:
+		auth != null
+	}
+
+	def inetOrgContextMapperIsSupported()  {
+		xml.'ldap-server'(url: 'ldap://127.0.0.1:343/dc=springframework,dc=org')
+		xml.'authentication-manager'{
+			'ldap-authentication-provider'('user-details-class' :'inetOrgPerson')
+		}
+		createAppContext('')
+
+		expect:
+		appContext.getBean(BeanIds.AUTHENTICATION_MANAGER).providers[0].userDetailsContextMapper instanceof InetOrgPersonContextMapper
+	}
+
+	def ldapAuthenticationProviderWorksWithPlaceholders() {
+		System.setProperty('udp','people')
+		System.setProperty('gsf','member')
+
+		xml.'ldap-server'()
+		xml.'authentication-manager'{
+			'ldap-authentication-provider'('user-dn-pattern':'uid={0},ou=${udp}','group-search-filter':'${gsf}={0}')
+		}
+		bean(PropertyPlaceholderConfigurer.class.name, PropertyPlaceholderConfigurer.class)
+
+		createAppContext('')
+		def provider = this.appContext.getBean(BeanIds.AUTHENTICATION_MANAGER).providers[0]
+
+		expect:
+		[new MessageFormat("uid={0},ou=people")] == FieldUtils.getFieldValue(provider,"authenticator.userDnFormat")
+		"member={0}" == FieldUtils.getFieldValue(provider, "authoritiesPopulator.groupSearchFilter")
+	}
 }

+ 111 - 111
config/src/test/groovy/org/springframework/security/config/annotation/authentication/AuthenticationManagerBuilderTests.groovy

@@ -44,127 +44,127 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager;
  *
  */
 class AuthenticationManagerBuilderTests extends BaseSpringSpec {
-    def "add(AuthenticationProvider) does not perform registration"() {
-        setup:
-            ObjectPostProcessor opp = Mock()
-            AuthenticationProvider provider = Mock()
-            AuthenticationManagerBuilder builder = new AuthenticationManagerBuilder(objectPostProcessor).objectPostProcessor(opp)
-        when: "Adding an AuthenticationProvider"
-            builder.authenticationProvider(provider)
-            builder.build()
-        then: "AuthenticationProvider is not passed into LifecycleManager (it should be managed externally)"
-            0 * opp._(_ as AuthenticationProvider)
-    }
+	def "add(AuthenticationProvider) does not perform registration"() {
+		setup:
+			ObjectPostProcessor opp = Mock()
+			AuthenticationProvider provider = Mock()
+			AuthenticationManagerBuilder builder = new AuthenticationManagerBuilder(objectPostProcessor).objectPostProcessor(opp)
+		when: "Adding an AuthenticationProvider"
+			builder.authenticationProvider(provider)
+			builder.build()
+		then: "AuthenticationProvider is not passed into LifecycleManager (it should be managed externally)"
+			0 * opp._(_ as AuthenticationProvider)
+	}
 
-    // https://github.com/SpringSource/spring-security-javaconfig/issues/132
-    def "#132 Custom AuthenticationEventPublisher with Web configure(AuthenticationManagerBuilder)"() {
-        setup:
-            AuthenticationEventPublisher aep = Mock()
-        when:
-            AuthenticationManager am = new AuthenticationManagerBuilder(objectPostProcessor)
-                .authenticationEventPublisher(aep)
-                .inMemoryAuthentication()
-                    .and()
-                .build()
-        then:
-            am.eventPublisher == aep
-    }
+	// https://github.com/SpringSource/spring-security-javaconfig/issues/132
+	def "#132 Custom AuthenticationEventPublisher with Web configure(AuthenticationManagerBuilder)"() {
+		setup:
+			AuthenticationEventPublisher aep = Mock()
+		when:
+			AuthenticationManager am = new AuthenticationManagerBuilder(objectPostProcessor)
+				.authenticationEventPublisher(aep)
+				.inMemoryAuthentication()
+					.and()
+				.build()
+		then:
+			am.eventPublisher == aep
+	}
 
-    def "authentication-manager support multiple DaoAuthenticationProvider's"() {
-        setup:
-            loadConfig(MultiAuthenticationProvidersConfig)
-        when:
-            Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
-        then:
-            auth.name == "user"
-            auth.authorities*.authority == ['ROLE_USER']
-        when:
-            auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("admin","password"))
-        then:
-            auth.name == "admin"
-            auth.authorities*.authority.sort() == ['ROLE_ADMIN','ROLE_USER']
-    }
+	def "authentication-manager support multiple DaoAuthenticationProvider's"() {
+		setup:
+			loadConfig(MultiAuthenticationProvidersConfig)
+		when:
+			Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
+		then:
+			auth.name == "user"
+			auth.authorities*.authority == ['ROLE_USER']
+		when:
+			auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("admin","password"))
+		then:
+			auth.name == "admin"
+			auth.authorities*.authority.sort() == ['ROLE_ADMIN','ROLE_USER']
+	}
 
-    @EnableWebSecurity
-    static class MultiAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter {
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER").and()
-                    .and()
-                .inMemoryAuthentication()
-                    .withUser("admin").password("password").roles("USER","ADMIN")
-        }
-    }
+	@EnableWebSecurity
+	static class MultiAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter {
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER").and()
+					.and()
+				.inMemoryAuthentication()
+					.withUser("admin").password("password").roles("USER","ADMIN")
+		}
+	}
 
-    def "isConfigured with AuthenticationProvider"() {
-        setup:
-            ObjectPostProcessor opp = Mock()
-            AuthenticationProvider provider = Mock()
-            AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(opp)
-        when:
-            auth
-                .authenticationProvider(provider)
-        then:
-            auth.isConfigured()
-    }
+	def "isConfigured with AuthenticationProvider"() {
+		setup:
+			ObjectPostProcessor opp = Mock()
+			AuthenticationProvider provider = Mock()
+			AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(opp)
+		when:
+			auth
+				.authenticationProvider(provider)
+		then:
+			auth.isConfigured()
+	}
 
-    def "isConfigured with parent"() {
-        setup:
-            ObjectPostProcessor opp = Mock()
-            AuthenticationManager parent = Mock()
-            AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(opp)
-        when:
-            auth
-                .parentAuthenticationManager(parent)
-        then:
-            auth.isConfigured()
-    }
+	def "isConfigured with parent"() {
+		setup:
+			ObjectPostProcessor opp = Mock()
+			AuthenticationManager parent = Mock()
+			AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(opp)
+		when:
+			auth
+				.parentAuthenticationManager(parent)
+		then:
+			auth.isConfigured()
+	}
 
-    def "isConfigured not configured"() {
-        setup:
-            ObjectPostProcessor opp = Mock()
-        when:
-            AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(opp)
-        then:
-            auth.isConfigured() == false
-    }
+	def "isConfigured not configured"() {
+		setup:
+			ObjectPostProcessor opp = Mock()
+		when:
+			AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(opp)
+		then:
+			auth.isConfigured() == false
+	}
 
-    def "user from properties"() {
-        setup:
-        loadConfig(UserFromPropertiesConfig)
-        AuthenticationManager manager = context.getBean(AuthenticationConfiguration).authenticationManager
-        when:
-        manager.authenticate(new UsernamePasswordAuthenticationToken("joe","joespassword"))
-        then:
-        noExceptionThrown()
-    }
+	def "user from properties"() {
+		setup:
+		loadConfig(UserFromPropertiesConfig)
+		AuthenticationManager manager = context.getBean(AuthenticationConfiguration).authenticationManager
+		when:
+		manager.authenticate(new UsernamePasswordAuthenticationToken("joe","joespassword"))
+		then:
+		noExceptionThrown()
+	}
 
-    @Configuration
-    @EnableGlobalAuthentication
-    @Import(ObjectPostProcessorConfiguration.class)
-    static class UserFromPropertiesConfig {
+	@Configuration
+	@EnableGlobalAuthentication
+	@Import(ObjectPostProcessorConfiguration.class)
+	static class UserFromPropertiesConfig {
 
-        @Value("classpath:org/springframework/security/config/users.properties")
-        Resource users;
+		@Value("classpath:org/springframework/security/config/users.properties")
+		Resource users;
 
-        @Bean
-        public AuthenticationManager authenticationManager() {
-            return new ProviderManager(Arrays.asList(authenticationProvider()));
-        }
+		@Bean
+		public AuthenticationManager authenticationManager() {
+			return new ProviderManager(Arrays.asList(authenticationProvider()));
+		}
 
-        @Bean
-        public AuthenticationProvider authenticationProvider() {
-            DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
-            provider.setUserDetailsService(userDetailsService())
-            return provider;
-        }
+		@Bean
+		public AuthenticationProvider authenticationProvider() {
+			DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
+			provider.setUserDetailsService(userDetailsService())
+			return provider;
+		}
 
-        @Bean
-        public UserDetailsService userDetailsService() {
-            Properties properties = new Properties();
-            properties.load(users.getInputStream());
-            return new InMemoryUserDetailsManager(properties);
-        }
-    }
+		@Bean
+		public UserDetailsService userDetailsService() {
+			Properties properties = new Properties();
+			properties.load(users.getInputStream());
+			return new InMemoryUserDetailsManager(properties);
+		}
+	}
 }

+ 7 - 7
config/src/test/groovy/org/springframework/security/config/annotation/authentication/BaseAuthenticationConfig.groovy

@@ -34,11 +34,11 @@ import org.springframework.security.core.userdetails.UserDetailsService;
  */
 @Configuration
 class BaseAuthenticationConfig {
-    @Autowired
-    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-        auth
-            .inMemoryAuthentication()
-                .withUser("user").password("password").roles("USER").and()
-                .withUser("admin").password("password").roles("USER", "ADMIN").and()
-    }
+	@Autowired
+	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+		auth
+			.inMemoryAuthentication()
+				.withUser("user").password("password").roles("USER").and()
+				.withUser("admin").password("password").roles("USER", "ADMIN").and()
+	}
 }

+ 69 - 69
config/src/test/groovy/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationManagerTests.groovy

@@ -32,80 +32,80 @@ import org.springframework.security.core.Authentication
  *
  */
 class NamespaceAuthenticationManagerTests extends BaseSpringSpec {
-    def "authentication-manager@erase-credentials=true (default)"() {
-        when:
-            loadConfig(EraseCredentialsTrueDefaultConfig)
-            Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
-        then:
-            auth.principal.password == null
-            auth.credentials == null
-        when: "authenticate the same user"
-            auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
-        then: "successfully authenticate again"
-            noExceptionThrown()
-    }
+	def "authentication-manager@erase-credentials=true (default)"() {
+		when:
+			loadConfig(EraseCredentialsTrueDefaultConfig)
+			Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
+		then:
+			auth.principal.password == null
+			auth.credentials == null
+		when: "authenticate the same user"
+			auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
+		then: "successfully authenticate again"
+			noExceptionThrown()
+	}
 
-    @EnableWebSecurity
-    static class EraseCredentialsTrueDefaultConfig extends WebSecurityConfigurerAdapter {
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER")
-        }
+	@EnableWebSecurity
+	static class EraseCredentialsTrueDefaultConfig extends WebSecurityConfigurerAdapter {
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER")
+		}
 
-        // Only necessary to have access to verify the AuthenticationManager
-        @Bean
-        @Override
-        public AuthenticationManager authenticationManagerBean()
-                throws Exception {
-            return super.authenticationManagerBean();
-        }
-    }
+		// Only necessary to have access to verify the AuthenticationManager
+		@Bean
+		@Override
+		public AuthenticationManager authenticationManagerBean()
+				throws Exception {
+			return super.authenticationManagerBean();
+		}
+	}
 
-    def "authentication-manager@erase-credentials=false"() {
-        when:
-            loadConfig(EraseCredentialsFalseConfig)
-            Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
-        then:
-            auth.credentials == "password"
-            auth.principal.password == "password"
-    }
+	def "authentication-manager@erase-credentials=false"() {
+		when:
+			loadConfig(EraseCredentialsFalseConfig)
+			Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
+		then:
+			auth.credentials == "password"
+			auth.principal.password == "password"
+	}
 
-    @EnableWebSecurity
-    static class EraseCredentialsFalseConfig extends WebSecurityConfigurerAdapter {
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .eraseCredentials(false)
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER")
-        }
+	@EnableWebSecurity
+	static class EraseCredentialsFalseConfig extends WebSecurityConfigurerAdapter {
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.eraseCredentials(false)
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER")
+		}
 
-        // Only necessary to have access to verify the AuthenticationManager
-        @Bean
-        @Override
-        public AuthenticationManager authenticationManagerBean()
-                throws Exception {
-            return super.authenticationManagerBean();
-        }
-    }
+		// Only necessary to have access to verify the AuthenticationManager
+		@Bean
+		@Override
+		public AuthenticationManager authenticationManagerBean()
+				throws Exception {
+			return super.authenticationManagerBean();
+		}
+	}
 
-    def "SEC-2533: global authentication-manager@erase-credentials=false"() {
-        when:
-            loadConfig(GlobalEraseCredentialsFalseConfig)
-            Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
-        then:
-            auth.credentials == "password"
-            auth.principal.password == "password"
-    }
+	def "SEC-2533: global authentication-manager@erase-credentials=false"() {
+		when:
+			loadConfig(GlobalEraseCredentialsFalseConfig)
+			Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
+		then:
+			auth.credentials == "password"
+			auth.principal.password == "password"
+	}
 
-    @EnableWebSecurity
-    static class GlobalEraseCredentialsFalseConfig extends WebSecurityConfigurerAdapter {
-        @Autowired
-        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .eraseCredentials(false)
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER")
-        }
-    }
+	@EnableWebSecurity
+	static class GlobalEraseCredentialsFalseConfig extends WebSecurityConfigurerAdapter {
+		@Autowired
+		public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.eraseCredentials(false)
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER")
+		}
+	}
 }

+ 42 - 42
config/src/test/groovy/org/springframework/security/config/annotation/authentication/NamespaceAuthenticationProviderTests.groovy

@@ -31,51 +31,51 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager
  *
  */
 class NamespaceAuthenticationProviderTests extends BaseSpringSpec {
-    def "authentication-provider@ref"() {
-        when:
-            loadConfig(AuthenticationProviderRefConfig)
-        then:
-            authenticationProviders()[1] == AuthenticationProviderRefConfig.expected
-    }
+	def "authentication-provider@ref"() {
+		when:
+			loadConfig(AuthenticationProviderRefConfig)
+		then:
+			authenticationProviders()[1] == AuthenticationProviderRefConfig.expected
+	}
 
-    @EnableWebSecurity
-    static class AuthenticationProviderRefConfig extends WebSecurityConfigurerAdapter {
-        static DaoAuthenticationProvider expected = new DaoAuthenticationProvider()
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .authenticationProvider(expected)
-        }
+	@EnableWebSecurity
+	static class AuthenticationProviderRefConfig extends WebSecurityConfigurerAdapter {
+		static DaoAuthenticationProvider expected = new DaoAuthenticationProvider()
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.authenticationProvider(expected)
+		}
 
-        // Only necessary to have access to verify the AuthenticationManager
-        @Bean
-        @Override
-        public AuthenticationManager authenticationManagerBean()
-                throws Exception {
-            return super.authenticationManagerBean();
-        }
-    }
+		// Only necessary to have access to verify the AuthenticationManager
+		@Bean
+		@Override
+		public AuthenticationManager authenticationManagerBean()
+				throws Exception {
+			return super.authenticationManagerBean();
+		}
+	}
 
-    def "authentication-provider@user-service-ref"() {
-        when:
-            loadConfig(UserServiceRefConfig)
-        then:
-            findAuthenticationProvider(DaoAuthenticationProvider).userDetailsService == UserServiceRefConfig.expected
-    }
+	def "authentication-provider@user-service-ref"() {
+		when:
+			loadConfig(UserServiceRefConfig)
+		then:
+			findAuthenticationProvider(DaoAuthenticationProvider).userDetailsService == UserServiceRefConfig.expected
+	}
 
-    @EnableWebSecurity
-    static class UserServiceRefConfig extends WebSecurityConfigurerAdapter {
-        static InMemoryUserDetailsManager expected = new InMemoryUserDetailsManager([] as Collection)
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .userDetailsService(expected)
-        }
+	@EnableWebSecurity
+	static class UserServiceRefConfig extends WebSecurityConfigurerAdapter {
+		static InMemoryUserDetailsManager expected = new InMemoryUserDetailsManager([] as Collection)
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.userDetailsService(expected)
+		}
 
-        // Only necessary to have access to verify the AuthenticationManager
-        @Bean
-        @Override
-        public AuthenticationManager authenticationManagerBean()
-                throws Exception {
-            return super.authenticationManagerBean();
-        }
-    }
+		// Only necessary to have access to verify the AuthenticationManager
+		@Bean
+		@Override
+		public AuthenticationManager authenticationManagerBean()
+				throws Exception {
+			return super.authenticationManagerBean();
+		}
+	}
 }

+ 141 - 141
config/src/test/groovy/org/springframework/security/config/annotation/authentication/NamespaceJdbcUserServiceTests.groovy

@@ -41,145 +41,145 @@ import org.springframework.security.provisioning.JdbcUserDetailsManager
  *
  */
 class NamespaceJdbcUserServiceTests extends BaseSpringSpec {
-    def "jdbc-user-service"() {
-        when:
-            loadConfig(DataSourceConfig,JdbcUserServiceConfig)
-        then:
-            findAuthenticationProvider(DaoAuthenticationProvider).userDetailsService instanceof JdbcUserDetailsManager
-    }
-
-    @EnableWebSecurity
-    static class JdbcUserServiceConfig extends WebSecurityConfigurerAdapter {
-        @Autowired
-        private DataSource dataSource;
-
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .jdbcAuthentication()
-                    .dataSource(dataSource) // jdbc-user-service@data-source-ref
-        }
-
-        // Only necessary to have access to verify the AuthenticationManager
-        @Bean
-        @Override
-        public AuthenticationManager authenticationManagerBean()
-                throws Exception {
-            return super.authenticationManagerBean();
-        }
-    }
-
-    def "jdbc-user-service in memory testing sample"() {
-        when:
-            loadConfig(DataSourceConfig,JdbcUserServiceInMemorySampleConfig)
-        then:
-           Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
-            auth.authorities.collect {it.authority} == ['ROLE_USER']
-            auth.name == "user"
-    }
-
-    @EnableWebSecurity
-    static class JdbcUserServiceInMemorySampleConfig extends WebSecurityConfigurerAdapter {
-        @Autowired
-        private DataSource dataSource;
-
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .jdbcAuthentication()
-                    .dataSource(dataSource)
-                    // imports the default schema (will fail if already exists)
-                    .withDefaultSchema()
-                    // adds this user automatically (will fail if already exists)
-                    .withUser("user")
-                        .password("password")
-                        .roles("USER")
-        }
-
-        // Only necessary to have access to verify the AuthenticationManager
-        @Bean
-        @Override
-        public AuthenticationManager authenticationManagerBean()
-                throws Exception {
-            return super.authenticationManagerBean();
-        }
-    }
-
-    @Configuration
-    static class DataSourceConfig {
-        @Bean
-        public DataSource dataSource() {
-            EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
-            return builder.setType(EmbeddedDatabaseType.HSQL).build();
-        }
-    }
-
-    def "jdbc-user-service custom"() {
-        when:
-            loadConfig(CustomDataSourceConfig,CustomJdbcUserServiceSampleConfig)
-        then:
-            findAuthenticationProvider(DaoAuthenticationProvider).userDetailsService.userCache instanceof CustomUserCache
-        when:
-            Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
-        then:
-            auth.authorities.collect {it.authority}.sort() == ['ROLE_DBA','ROLE_USER']
-            auth.name == 'user'
-    }
-
-    @EnableWebSecurity
-    static class CustomJdbcUserServiceSampleConfig extends WebSecurityConfigurerAdapter {
-        @Autowired
-        private DataSource dataSource;
-
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .jdbcAuthentication()
-                    // jdbc-user-service@dataSource
-                    .dataSource(dataSource)
-                    // jdbc-user-service@cache-ref
-                    .userCache(new CustomUserCache())
-                    // jdbc-user-service@users-byusername-query
-                    .usersByUsernameQuery("select principal,credentials,true from users where principal = ?")
-                    // jdbc-user-service@authorities-by-username-query
-                    .authoritiesByUsernameQuery("select principal,role from roles where principal = ?")
-                    // jdbc-user-service@group-authorities-by-username-query
-                    .groupAuthoritiesByUsername(JdbcUserDetailsManager.DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY)
-                    // jdbc-user-service@role-prefix
-                    .rolePrefix("ROLE_")
-
-        }
-
-        // Only necessary to have access to verify the AuthenticationManager
-        @Bean
-        @Override
-        public AuthenticationManager authenticationManagerBean()
-                throws Exception {
-            return super.authenticationManagerBean();
-        }
-
-        static class CustomUserCache implements UserCache {
-
-            @Override
-            public UserDetails getUserFromCache(String username) {
-                return null;
-            }
-
-            @Override
-            public void putUserInCache(UserDetails user) {
-            }
-
-            @Override
-            public void removeUserFromCache(String username) {
-            }
-        }
-    }
-
-    @Configuration
-    static class CustomDataSourceConfig {
-        @Bean
-        public DataSource dataSource() {
-            EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
-                // simulate that the DB already has the schema loaded and users in it
-                .addScript("CustomJdbcUserServiceSampleConfig.sql")
-            return builder.setType(EmbeddedDatabaseType.HSQL).build();
-        }
-    }
+	def "jdbc-user-service"() {
+		when:
+			loadConfig(DataSourceConfig,JdbcUserServiceConfig)
+		then:
+			findAuthenticationProvider(DaoAuthenticationProvider).userDetailsService instanceof JdbcUserDetailsManager
+	}
+
+	@EnableWebSecurity
+	static class JdbcUserServiceConfig extends WebSecurityConfigurerAdapter {
+		@Autowired
+		private DataSource dataSource;
+
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.jdbcAuthentication()
+					.dataSource(dataSource) // jdbc-user-service@data-source-ref
+		}
+
+		// Only necessary to have access to verify the AuthenticationManager
+		@Bean
+		@Override
+		public AuthenticationManager authenticationManagerBean()
+				throws Exception {
+			return super.authenticationManagerBean();
+		}
+	}
+
+	def "jdbc-user-service in memory testing sample"() {
+		when:
+			loadConfig(DataSourceConfig,JdbcUserServiceInMemorySampleConfig)
+		then:
+		   Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
+			auth.authorities.collect {it.authority} == ['ROLE_USER']
+			auth.name == "user"
+	}
+
+	@EnableWebSecurity
+	static class JdbcUserServiceInMemorySampleConfig extends WebSecurityConfigurerAdapter {
+		@Autowired
+		private DataSource dataSource;
+
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.jdbcAuthentication()
+					.dataSource(dataSource)
+					// imports the default schema (will fail if already exists)
+					.withDefaultSchema()
+					// adds this user automatically (will fail if already exists)
+					.withUser("user")
+						.password("password")
+						.roles("USER")
+		}
+
+		// Only necessary to have access to verify the AuthenticationManager
+		@Bean
+		@Override
+		public AuthenticationManager authenticationManagerBean()
+				throws Exception {
+			return super.authenticationManagerBean();
+		}
+	}
+
+	@Configuration
+	static class DataSourceConfig {
+		@Bean
+		public DataSource dataSource() {
+			EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
+			return builder.setType(EmbeddedDatabaseType.HSQL).build();
+		}
+	}
+
+	def "jdbc-user-service custom"() {
+		when:
+			loadConfig(CustomDataSourceConfig,CustomJdbcUserServiceSampleConfig)
+		then:
+			findAuthenticationProvider(DaoAuthenticationProvider).userDetailsService.userCache instanceof CustomUserCache
+		when:
+			Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
+		then:
+			auth.authorities.collect {it.authority}.sort() == ['ROLE_DBA','ROLE_USER']
+			auth.name == 'user'
+	}
+
+	@EnableWebSecurity
+	static class CustomJdbcUserServiceSampleConfig extends WebSecurityConfigurerAdapter {
+		@Autowired
+		private DataSource dataSource;
+
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.jdbcAuthentication()
+					// jdbc-user-service@dataSource
+					.dataSource(dataSource)
+					// jdbc-user-service@cache-ref
+					.userCache(new CustomUserCache())
+					// jdbc-user-service@users-byusername-query
+					.usersByUsernameQuery("select principal,credentials,true from users where principal = ?")
+					// jdbc-user-service@authorities-by-username-query
+					.authoritiesByUsernameQuery("select principal,role from roles where principal = ?")
+					// jdbc-user-service@group-authorities-by-username-query
+					.groupAuthoritiesByUsername(JdbcUserDetailsManager.DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY)
+					// jdbc-user-service@role-prefix
+					.rolePrefix("ROLE_")
+
+		}
+
+		// Only necessary to have access to verify the AuthenticationManager
+		@Bean
+		@Override
+		public AuthenticationManager authenticationManagerBean()
+				throws Exception {
+			return super.authenticationManagerBean();
+		}
+
+		static class CustomUserCache implements UserCache {
+
+			@Override
+			public UserDetails getUserFromCache(String username) {
+				return null;
+			}
+
+			@Override
+			public void putUserInCache(UserDetails user) {
+			}
+
+			@Override
+			public void removeUserFromCache(String username) {
+			}
+		}
+	}
+
+	@Configuration
+	static class CustomDataSourceConfig {
+		@Bean
+		public DataSource dataSource() {
+			EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
+				// simulate that the DB already has the schema loaded and users in it
+				.addScript("CustomJdbcUserServiceSampleConfig.sql")
+			return builder.setType(EmbeddedDatabaseType.HSQL).build();
+		}
+	}
 }

+ 64 - 64
config/src/test/groovy/org/springframework/security/config/annotation/authentication/NamespacePasswordEncoderTests.groovy

@@ -43,78 +43,78 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager
  *
  */
 class NamespacePasswordEncoderTests extends BaseSpringSpec {
-    def "password-encoder@ref with in memory"() {
-        when:
-            loadConfig(PasswordEncoderWithInMemoryConfig)
-        then:
-            authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
-    }
+	def "password-encoder@ref with in memory"() {
+		when:
+			loadConfig(PasswordEncoderWithInMemoryConfig)
+		then:
+			authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
+	}
 
-    @EnableWebSecurity
-    static class PasswordEncoderWithInMemoryConfig extends WebSecurityConfigurerAdapter {
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+	@EnableWebSecurity
+	static class PasswordEncoderWithInMemoryConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
 
-            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder()
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password(encoder.encode("password")).roles("USER").and()
-                    .passwordEncoder(encoder)
-        }
-    }
+			BCryptPasswordEncoder encoder = new BCryptPasswordEncoder()
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password(encoder.encode("password")).roles("USER").and()
+					.passwordEncoder(encoder)
+		}
+	}
 
-    def "password-encoder@ref with jdbc"() {
-        when:
-            loadConfig(PasswordEncoderWithJdbcConfig)
-        then:
-            authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
-    }
+	def "password-encoder@ref with jdbc"() {
+		when:
+			loadConfig(PasswordEncoderWithJdbcConfig)
+		then:
+			authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
+	}
 
-    @EnableWebSecurity
-    static class PasswordEncoderWithJdbcConfig extends WebSecurityConfigurerAdapter {
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+	@EnableWebSecurity
+	static class PasswordEncoderWithJdbcConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
 
-            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder()
-            auth
-                .jdbcAuthentication()
-                    .withDefaultSchema()
-                    .dataSource(dataSource())
-                    .withUser("user").password(encoder.encode("password")).roles("USER").and()
-                    .passwordEncoder(encoder)
-        }
+			BCryptPasswordEncoder encoder = new BCryptPasswordEncoder()
+			auth
+				.jdbcAuthentication()
+					.withDefaultSchema()
+					.dataSource(dataSource())
+					.withUser("user").password(encoder.encode("password")).roles("USER").and()
+					.passwordEncoder(encoder)
+		}
 
-        @Bean
-        public DataSource dataSource() {
-            EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
-            return builder.setType(EmbeddedDatabaseType.HSQL).build();
-        }
-    }
+		@Bean
+		public DataSource dataSource() {
+			EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
+			return builder.setType(EmbeddedDatabaseType.HSQL).build();
+		}
+	}
 
-    def "password-encoder@ref with userdetailsservice"() {
-        when:
-            loadConfig(PasswordEncoderWithUserDetailsServiceConfig)
-        then:
-            authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
-    }
+	def "password-encoder@ref with userdetailsservice"() {
+		when:
+			loadConfig(PasswordEncoderWithUserDetailsServiceConfig)
+		then:
+			authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
+	}
 
-    @EnableWebSecurity
-    static class PasswordEncoderWithUserDetailsServiceConfig extends WebSecurityConfigurerAdapter {
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+	@EnableWebSecurity
+	static class PasswordEncoderWithUserDetailsServiceConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
 
-            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder()
-            User user = new User("user",encoder.encode("password"), AuthorityUtils.createAuthorityList("ROLE_USER"))
-            InMemoryUserDetailsManager uds = new InMemoryUserDetailsManager([user])
-            auth
-                .userDetailsService(uds)
-                    .passwordEncoder(encoder)
-        }
+			BCryptPasswordEncoder encoder = new BCryptPasswordEncoder()
+			User user = new User("user",encoder.encode("password"), AuthorityUtils.createAuthorityList("ROLE_USER"))
+			InMemoryUserDetailsManager uds = new InMemoryUserDetailsManager([user])
+			auth
+				.userDetailsService(uds)
+					.passwordEncoder(encoder)
+		}
 
-        @Bean
-        public DataSource dataSource() {
-            EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
-            return builder.setType(EmbeddedDatabaseType.HSQL).build();
-        }
-    }
+		@Bean
+		public DataSource dataSource() {
+			EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
+			return builder.setType(EmbeddedDatabaseType.HSQL).build();
+		}
+	}
 }

+ 13 - 13
config/src/test/groovy/org/springframework/security/config/annotation/authentication/PasswordEncoderConfigurerTests.groovy

@@ -44,18 +44,18 @@ import org.springframework.test.util.ReflectionTestUtils;
  *
  */
 class PasswordEncoderConfigurerTests extends BaseSpringSpec {
-    def "password-encoder@ref with No AuthenticationManager Bean"() {
-        when:
-            loadConfig(PasswordEncoderNoAuthManagerLoadsConfig)
-        then:
-            noExceptionThrown()
-    }
+	def "password-encoder@ref with No AuthenticationManager Bean"() {
+		when:
+			loadConfig(PasswordEncoderNoAuthManagerLoadsConfig)
+		then:
+			noExceptionThrown()
+	}
 
-    def "password-encoder@ref with AuthenticationManagerBuilder"() {
-        when:
-            loadConfig(PasswordEncoderConfig)
-            AuthenticationManager authMgr = authenticationManager()
-        then:
-            authMgr.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
-    }
+	def "password-encoder@ref with AuthenticationManagerBuilder"() {
+		when:
+			loadConfig(PasswordEncoderConfig)
+			AuthenticationManager authMgr = authenticationManager()
+		then:
+			authMgr.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
+	}
 }

+ 316 - 316
config/src/test/groovy/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationTests.groovy

@@ -50,320 +50,320 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager
 
 class AuthenticationConfigurationTests extends BaseSpringSpec {
 
-    def "Ordering Autowired on EnableGlobalMethodSecurity"() {
-        setup:
-            SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password","ROLE_USER"))
-        when:
-            loadConfig(GlobalMethodSecurityAutowiredConfigAndServicesConfig)
-        then:
-            context.getBean(Service).run()
-    }
-
-    @Configuration
-    @Import([GlobalMethodSecurityAutowiredConfig,ServicesConfig])
-    static class GlobalMethodSecurityAutowiredConfigAndServicesConfig {}
-
-    @EnableGlobalMethodSecurity(securedEnabled = true)
-    static class GlobalMethodSecurityAutowiredConfig {
-        @Autowired
-        public void configureGlobal(AuthenticationManagerBuilder auth) {
-            auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
-        }
-    }
-
-    def "Ordering Autowired on EnableWebSecurity"() {
-        setup:
-            SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password","ROLE_USER"))
-        when:
-            loadConfig(GlobalMethodSecurityConfigAndServicesConfig)
-        then:
-            context.getBean(Service).run()
-    }
-
-    @Configuration
-    @Import([GlobalMethodSecurityConfig,WebSecurityConfig,ServicesConfig])
-    static class GlobalMethodSecurityConfigAndServicesConfig {}
-
-    @EnableGlobalMethodSecurity(securedEnabled = true)
-    static class GlobalMethodSecurityConfig {}
-
-    @EnableWebSecurity
-    static class WebSecurityConfig extends WebSecurityConfigurerAdapter {
-        @Autowired
-        public void configureGlobal(AuthenticationManagerBuilder auth) {
-            auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
-        }
-    }
-
-    //
-
-    def "Ordering Autowired on EnableWebMvcSecurity"() {
-        setup:
-            SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password","ROLE_USER"))
-        when:
-            loadConfig(GlobalMethodSecurityMvcSecurityAndServicesConfig)
-        then:
-            context.getBean(Service).run()
-    }
-
-    @Configuration
-    @Import([GlobalMethodSecurityConfig,WebMvcSecurityConfig,ServicesConfig])
-    static class GlobalMethodSecurityMvcSecurityAndServicesConfig {}
-
-    @EnableWebSecurity
-    static class WebMvcSecurityConfig extends WebSecurityConfigurerAdapter {
-        @Autowired
-        public void configureGlobal(AuthenticationManagerBuilder auth) {
-            auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
-        }
-    }
-
-    //
-
-    def "no authentication getAuthenticationManager falls back to null"() {
-        when:
-            loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
-        then:
-            context.getBean(AuthenticationConfiguration).authenticationManager == null
-    }
-
-    def "QuiesentGlobalAuthenticationConfiguererAdapter falls back to null"() {
-        when:
-            loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration,QuiesentGlobalAuthenticationConfiguererAdapter)
-        then:
-            context.getBean(AuthenticationConfiguration).authenticationManager == null
-    }
-
-    @Configuration
-    static class QuiesentGlobalAuthenticationConfiguererAdapter extends GlobalAuthenticationConfigurerAdapter {}
-
-    //
-
-    def "GlobalAuthenticationConfiguererAdapterImpl configures authentication successfully"() {
-        setup:
-            def token = new UsernamePasswordAuthenticationToken("user", "password")
-        when:
-            loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration,GlobalAuthenticationConfiguererAdapterImpl)
-        then:
-            context.getBean(AuthenticationConfiguration).authenticationManager.authenticate(token)?.name == "user"
-    }
-
-    @Configuration
-    static class GlobalAuthenticationConfiguererAdapterImpl extends GlobalAuthenticationConfigurerAdapter {
-        public void init(AuthenticationManagerBuilder auth) throws Exception {
-            auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
-        }
-    }
-
-    //
-
-    def "AuthenticationManagerBean configures authentication successfully"() {
-        setup:
-            def token = new UsernamePasswordAuthenticationToken("user", "password")
-            def auth = new UsernamePasswordAuthenticationToken("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"))
-            AuthenticationManagerBeanConfig.AM = Mock(AuthenticationManager)
-            1 * AuthenticationManagerBeanConfig.AM.authenticate(token) >> auth
-        when:
-            loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration,AuthenticationManagerBeanConfig)
-        then:
-            context.getBean(AuthenticationConfiguration).authenticationManager.authenticate(token).name == auth.name
-    }
-
-    @Configuration
-    static class AuthenticationManagerBeanConfig {
-        static AuthenticationManager AM
-        @Bean
-        public AuthenticationManager authenticationManager() {
-            AM
-        }
-    }
-
-    //
-
-    @Configuration
-    static class ServicesConfig {
-        @Bean
-        public Service service() {
-            return new ServiceImpl()
-        }
-    }
-
-    static interface Service {
-        public void run();
-    }
-
-    static class ServiceImpl implements Service {
-        @Secured("ROLE_USER")
-        public void run() {}
-    }
-
-    //
-
-    def "GlobalAuthenticationConfigurerAdapter are ordered"() {
-        setup:
-            loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
-            AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
-            config.setGlobalAuthenticationConfigurers([new LowestOrderGlobalAuthenticationConfigurerAdapter(), new HighestOrderGlobalAuthenticationConfigurerAdapter(), new DefaultOrderGlobalAuthenticationConfigurerAdapter()])
-        when:
-            config.getAuthenticationManager()
-        then:
-            DefaultOrderGlobalAuthenticationConfigurerAdapter.inits == [HighestOrderGlobalAuthenticationConfigurerAdapter,DefaultOrderGlobalAuthenticationConfigurerAdapter,LowestOrderGlobalAuthenticationConfigurerAdapter]
-            DefaultOrderGlobalAuthenticationConfigurerAdapter.configs == [HighestOrderGlobalAuthenticationConfigurerAdapter,DefaultOrderGlobalAuthenticationConfigurerAdapter,LowestOrderGlobalAuthenticationConfigurerAdapter]
-
-    }
-
-    static class DefaultOrderGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter {
-        static List inits = []
-        static List configs = []
-
-        public void init(AuthenticationManagerBuilder auth) throws Exception {
-            inits.add(getClass())
-        }
-
-        public void configure(AuthenticationManagerBuilder auth) throws Exception {
-            configs.add(getClass())
-        }
-    }
-
-    @Order(Ordered.LOWEST_PRECEDENCE)
-    static class LowestOrderGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {}
-
-    @Order(Ordered.HIGHEST_PRECEDENCE)
-    static class HighestOrderGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {}
-
-    //
-
-    def "Spring Boot not triggered when already configured"() {
-        setup:
-            loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
-            AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
-            config.setGlobalAuthenticationConfigurers([new ConfiguresInMemoryConfigurerAdapter(), new BootGlobalAuthenticationConfigurerAdapter()])
-            AuthenticationManager authenticationManager = config.authenticationManager
-        when:
-            authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
-        then:
-            noExceptionThrown()
-        when:
-            authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("boot","password"))
-        then:
-            thrown(AuthenticationException)
-    }
-
-
-    def "Spring Boot is triggered when not already configured"() {
-        setup:
-            loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
-            AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
-            config.setGlobalAuthenticationConfigurers([new BootGlobalAuthenticationConfigurerAdapter()])
-            AuthenticationManager authenticationManager = config.authenticationManager
-        when:
-            authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("boot","password"))
-        then:
-            noExceptionThrown()
-    }
-
-    static class ConfiguresInMemoryConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter {
-
-        public void init(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER")
-        }
-    }
-
-    @Order(Ordered.LOWEST_PRECEDENCE)
-    static class BootGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {
-        public void init(AuthenticationManagerBuilder auth) throws Exception {
-            auth.apply(new DefaultBootGlobalAuthenticationConfigurerAdapter())
-        }
-    }
-
-    static class DefaultBootGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {
-        @Override
-        public void configure(AuthenticationManagerBuilder auth) throws Exception {
-            if(auth.isConfigured()) {
-                return;
-            }
-
-            User user = new User("boot","password", AuthorityUtils.createAuthorityList("ROLE_USER"))
-
-            List<User> users = Arrays.asList(user);
-            InMemoryUserDetailsManager inMemory = new InMemoryUserDetailsManager(users);
-
-            DaoAuthenticationProvider provider = new DaoAuthenticationProvider()
-            provider.userDetailsService = inMemory
-
-            auth.authenticationProvider(provider)
-        }
-    }
-
-    def "SEC-2531: AuthenticationConfiguration#lazyBean should use BeanClassLoader on ProxyFactoryBean"() {
-        setup:
-            ObjectPostProcessor opp = Mock()
-            Sec2531Config. opp = opp
-            loadConfig(Sec2531Config)
-        when:
-            AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
-            config.getAuthenticationManager()
-        then:
-            1 * opp.postProcess(_ as ProxyFactoryBean) >> { args ->
-                args[0]
-            }
-    }
-
-    @Configuration
-    @Import(AuthenticationConfiguration)
-    static class Sec2531Config {
-        static ObjectPostProcessor opp
-
-        @Bean
-        public ObjectPostProcessor objectPostProcessor() {
-            opp
-        }
-
-        @Bean
-        public AuthenticationManager manager() {
-            null
-        }
-    }
-
-    def "SEC-2822: Cannot Force Authentication already built"() {
-        setup:
-        loadConfig(Sec2822WebSecurity,Sec2822UseAuth,Sec2822Config)
-        when:
-        AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
-        config.getAuthenticationManager()
-        then:
-        noExceptionThrown()
-    }
-
-    @Configuration
-    @Import(AuthenticationConfiguration)
-    static class Sec2822Config {}
-
-    @Configuration
-    @EnableWebSecurity
-    static class Sec2822WebSecurity extends WebSecurityConfigurerAdapter {
-        @Autowired
-        public void configureGlobal(AuthenticationManagerBuilder auth) {
-            auth.inMemoryAuthentication()
-        }
-    }
-
-    @Configuration
-    static class Sec2822UseAuth {
-        @Autowired
-        public void useAuthenticationManager(AuthenticationConfiguration auth) {
-            auth.authenticationManager
-        }
-
-        // Ensures that Sec2822UseAuth is initialized before Sec2822WebSecurity
-        // must have additional GlobalAuthenticationConfigurerAdapter to trigger SEC-2822
-        @Bean
-        public static GlobalAuthenticationConfigurerAdapter bootGlobalAuthenticationConfigurerAdapter() {
-            new BootGlobalAuthenticationConfigurerAdapter()
-        }
-
-        static class BootGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { }
-    }
+	def "Ordering Autowired on EnableGlobalMethodSecurity"() {
+		setup:
+			SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password","ROLE_USER"))
+		when:
+			loadConfig(GlobalMethodSecurityAutowiredConfigAndServicesConfig)
+		then:
+			context.getBean(Service).run()
+	}
+
+	@Configuration
+	@Import([GlobalMethodSecurityAutowiredConfig,ServicesConfig])
+	static class GlobalMethodSecurityAutowiredConfigAndServicesConfig {}
+
+	@EnableGlobalMethodSecurity(securedEnabled = true)
+	static class GlobalMethodSecurityAutowiredConfig {
+		@Autowired
+		public void configureGlobal(AuthenticationManagerBuilder auth) {
+			auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
+		}
+	}
+
+	def "Ordering Autowired on EnableWebSecurity"() {
+		setup:
+			SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password","ROLE_USER"))
+		when:
+			loadConfig(GlobalMethodSecurityConfigAndServicesConfig)
+		then:
+			context.getBean(Service).run()
+	}
+
+	@Configuration
+	@Import([GlobalMethodSecurityConfig,WebSecurityConfig,ServicesConfig])
+	static class GlobalMethodSecurityConfigAndServicesConfig {}
+
+	@EnableGlobalMethodSecurity(securedEnabled = true)
+	static class GlobalMethodSecurityConfig {}
+
+	@EnableWebSecurity
+	static class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+		@Autowired
+		public void configureGlobal(AuthenticationManagerBuilder auth) {
+			auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
+		}
+	}
+
+	//
+
+	def "Ordering Autowired on EnableWebMvcSecurity"() {
+		setup:
+			SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password","ROLE_USER"))
+		when:
+			loadConfig(GlobalMethodSecurityMvcSecurityAndServicesConfig)
+		then:
+			context.getBean(Service).run()
+	}
+
+	@Configuration
+	@Import([GlobalMethodSecurityConfig,WebMvcSecurityConfig,ServicesConfig])
+	static class GlobalMethodSecurityMvcSecurityAndServicesConfig {}
+
+	@EnableWebSecurity
+	static class WebMvcSecurityConfig extends WebSecurityConfigurerAdapter {
+		@Autowired
+		public void configureGlobal(AuthenticationManagerBuilder auth) {
+			auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
+		}
+	}
+
+	//
+
+	def "no authentication getAuthenticationManager falls back to null"() {
+		when:
+			loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
+		then:
+			context.getBean(AuthenticationConfiguration).authenticationManager == null
+	}
+
+	def "QuiesentGlobalAuthenticationConfiguererAdapter falls back to null"() {
+		when:
+			loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration,QuiesentGlobalAuthenticationConfiguererAdapter)
+		then:
+			context.getBean(AuthenticationConfiguration).authenticationManager == null
+	}
+
+	@Configuration
+	static class QuiesentGlobalAuthenticationConfiguererAdapter extends GlobalAuthenticationConfigurerAdapter {}
+
+	//
+
+	def "GlobalAuthenticationConfiguererAdapterImpl configures authentication successfully"() {
+		setup:
+			def token = new UsernamePasswordAuthenticationToken("user", "password")
+		when:
+			loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration,GlobalAuthenticationConfiguererAdapterImpl)
+		then:
+			context.getBean(AuthenticationConfiguration).authenticationManager.authenticate(token)?.name == "user"
+	}
+
+	@Configuration
+	static class GlobalAuthenticationConfiguererAdapterImpl extends GlobalAuthenticationConfigurerAdapter {
+		public void init(AuthenticationManagerBuilder auth) throws Exception {
+			auth.inMemoryAuthentication().withUser("user").password("password").roles("USER")
+		}
+	}
+
+	//
+
+	def "AuthenticationManagerBean configures authentication successfully"() {
+		setup:
+			def token = new UsernamePasswordAuthenticationToken("user", "password")
+			def auth = new UsernamePasswordAuthenticationToken("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"))
+			AuthenticationManagerBeanConfig.AM = Mock(AuthenticationManager)
+			1 * AuthenticationManagerBeanConfig.AM.authenticate(token) >> auth
+		when:
+			loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration,AuthenticationManagerBeanConfig)
+		then:
+			context.getBean(AuthenticationConfiguration).authenticationManager.authenticate(token).name == auth.name
+	}
+
+	@Configuration
+	static class AuthenticationManagerBeanConfig {
+		static AuthenticationManager AM
+		@Bean
+		public AuthenticationManager authenticationManager() {
+			AM
+		}
+	}
+
+	//
+
+	@Configuration
+	static class ServicesConfig {
+		@Bean
+		public Service service() {
+			return new ServiceImpl()
+		}
+	}
+
+	static interface Service {
+		public void run();
+	}
+
+	static class ServiceImpl implements Service {
+		@Secured("ROLE_USER")
+		public void run() {}
+	}
+
+	//
+
+	def "GlobalAuthenticationConfigurerAdapter are ordered"() {
+		setup:
+			loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
+			AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
+			config.setGlobalAuthenticationConfigurers([new LowestOrderGlobalAuthenticationConfigurerAdapter(), new HighestOrderGlobalAuthenticationConfigurerAdapter(), new DefaultOrderGlobalAuthenticationConfigurerAdapter()])
+		when:
+			config.getAuthenticationManager()
+		then:
+			DefaultOrderGlobalAuthenticationConfigurerAdapter.inits == [HighestOrderGlobalAuthenticationConfigurerAdapter,DefaultOrderGlobalAuthenticationConfigurerAdapter,LowestOrderGlobalAuthenticationConfigurerAdapter]
+			DefaultOrderGlobalAuthenticationConfigurerAdapter.configs == [HighestOrderGlobalAuthenticationConfigurerAdapter,DefaultOrderGlobalAuthenticationConfigurerAdapter,LowestOrderGlobalAuthenticationConfigurerAdapter]
+
+	}
+
+	static class DefaultOrderGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter {
+		static List inits = []
+		static List configs = []
+
+		public void init(AuthenticationManagerBuilder auth) throws Exception {
+			inits.add(getClass())
+		}
+
+		public void configure(AuthenticationManagerBuilder auth) throws Exception {
+			configs.add(getClass())
+		}
+	}
+
+	@Order(Ordered.LOWEST_PRECEDENCE)
+	static class LowestOrderGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {}
+
+	@Order(Ordered.HIGHEST_PRECEDENCE)
+	static class HighestOrderGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {}
+
+	//
+
+	def "Spring Boot not triggered when already configured"() {
+		setup:
+			loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
+			AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
+			config.setGlobalAuthenticationConfigurers([new ConfiguresInMemoryConfigurerAdapter(), new BootGlobalAuthenticationConfigurerAdapter()])
+			AuthenticationManager authenticationManager = config.authenticationManager
+		when:
+			authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
+		then:
+			noExceptionThrown()
+		when:
+			authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("boot","password"))
+		then:
+			thrown(AuthenticationException)
+	}
+
+
+	def "Spring Boot is triggered when not already configured"() {
+		setup:
+			loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
+			AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
+			config.setGlobalAuthenticationConfigurers([new BootGlobalAuthenticationConfigurerAdapter()])
+			AuthenticationManager authenticationManager = config.authenticationManager
+		when:
+			authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("boot","password"))
+		then:
+			noExceptionThrown()
+	}
+
+	static class ConfiguresInMemoryConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter {
+
+		public void init(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER")
+		}
+	}
+
+	@Order(Ordered.LOWEST_PRECEDENCE)
+	static class BootGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {
+		public void init(AuthenticationManagerBuilder auth) throws Exception {
+			auth.apply(new DefaultBootGlobalAuthenticationConfigurerAdapter())
+		}
+	}
+
+	static class DefaultBootGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {
+		@Override
+		public void configure(AuthenticationManagerBuilder auth) throws Exception {
+			if(auth.isConfigured()) {
+				return;
+			}
+
+			User user = new User("boot","password", AuthorityUtils.createAuthorityList("ROLE_USER"))
+
+			List<User> users = Arrays.asList(user);
+			InMemoryUserDetailsManager inMemory = new InMemoryUserDetailsManager(users);
+
+			DaoAuthenticationProvider provider = new DaoAuthenticationProvider()
+			provider.userDetailsService = inMemory
+
+			auth.authenticationProvider(provider)
+		}
+	}
+
+	def "SEC-2531: AuthenticationConfiguration#lazyBean should use BeanClassLoader on ProxyFactoryBean"() {
+		setup:
+			ObjectPostProcessor opp = Mock()
+			Sec2531Config. opp = opp
+			loadConfig(Sec2531Config)
+		when:
+			AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
+			config.getAuthenticationManager()
+		then:
+			1 * opp.postProcess(_ as ProxyFactoryBean) >> { args ->
+				args[0]
+			}
+	}
+
+	@Configuration
+	@Import(AuthenticationConfiguration)
+	static class Sec2531Config {
+		static ObjectPostProcessor opp
+
+		@Bean
+		public ObjectPostProcessor objectPostProcessor() {
+			opp
+		}
+
+		@Bean
+		public AuthenticationManager manager() {
+			null
+		}
+	}
+
+	def "SEC-2822: Cannot Force Authentication already built"() {
+		setup:
+		loadConfig(Sec2822WebSecurity,Sec2822UseAuth,Sec2822Config)
+		when:
+		AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
+		config.getAuthenticationManager()
+		then:
+		noExceptionThrown()
+	}
+
+	@Configuration
+	@Import(AuthenticationConfiguration)
+	static class Sec2822Config {}
+
+	@Configuration
+	@EnableWebSecurity
+	static class Sec2822WebSecurity extends WebSecurityConfigurerAdapter {
+		@Autowired
+		public void configureGlobal(AuthenticationManagerBuilder auth) {
+			auth.inMemoryAuthentication()
+		}
+	}
+
+	@Configuration
+	static class Sec2822UseAuth {
+		@Autowired
+		public void useAuthenticationManager(AuthenticationConfiguration auth) {
+			auth.authenticationManager
+		}
+
+		// Ensures that Sec2822UseAuth is initialized before Sec2822WebSecurity
+		// must have additional GlobalAuthenticationConfigurerAdapter to trigger SEC-2822
+		@Bean
+		public static GlobalAuthenticationConfigurerAdapter bootGlobalAuthenticationConfigurerAdapter() {
+			new BootGlobalAuthenticationConfigurerAdapter()
+		}
+
+		static class BootGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { }
+	}
 }

+ 96 - 96
config/src/test/groovy/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessorTests.groovy

@@ -42,100 +42,100 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationCon
  */
 class AutowireBeanFactoryObjectPostProcessorTests extends BaseSpringSpec {
 
-    def "Verify All Aware methods are invoked"() {
-        setup:
-            ApplicationContextAware contextAware = Mock(ApplicationContextAware)
-            ApplicationEventPublisherAware publisher = Mock(ApplicationEventPublisherAware)
-            BeanClassLoaderAware classloader = Mock(BeanClassLoaderAware)
-            BeanFactoryAware beanFactory = Mock(BeanFactoryAware)
-            EnvironmentAware environment = Mock(EnvironmentAware)
-            MessageSourceAware messageSource = Mock(MessageSourceAware)
-            ServletConfigAware servletConfig = Mock(ServletConfigAware)
-            ServletContextAware servletContext = Mock(ServletContextAware)
-            DisposableBean disposable = Mock(DisposableBean)
-
-            context = new AnnotationConfigWebApplicationContext([servletConfig:new MockServletConfig(),servletContext:new MockServletContext()])
-            context.register(Config)
-            context.refresh()
-            context.start()
-
-            ObjectPostProcessor opp = context.getBean(ObjectPostProcessor)
-        when:
-            opp.postProcess(contextAware)
-        then:
-            1 * contextAware.setApplicationContext(!null)
-
-        when:
-            opp.postProcess(publisher)
-        then:
-            1 * publisher.setApplicationEventPublisher(!null)
-
-        when:
-            opp.postProcess(classloader)
-        then:
-            1 * classloader.setBeanClassLoader(!null)
-
-        when:
-            opp.postProcess(beanFactory)
-        then:
-            1 * beanFactory.setBeanFactory(!null)
-
-        when:
-            opp.postProcess(environment)
-        then:
-            1 * environment.setEnvironment(!null)
-
-        when:
-            opp.postProcess(messageSource)
-        then:
-            1 * messageSource.setMessageSource(!null)
-
-        when:
-            opp.postProcess(servletConfig)
-        then:
-            1 * servletConfig.setServletConfig(!null)
-
-        when:
-            opp.postProcess(servletContext)
-        then:
-            1 * servletContext.setServletContext(!null)
-
-        when:
-            opp.postProcess(disposable)
-            context.close()
-            context = null
-        then:
-            1 * disposable.destroy()
-    }
-
-    @Configuration
-    static class Config {
-        @Bean
-        public ObjectPostProcessor objectPostProcessor(AutowireCapableBeanFactory beanFactory) {
-            return new AutowireBeanFactoryObjectPostProcessor(beanFactory);
-        }
-    }
-
-    def "SEC-2382: AutowireBeanFactoryObjectPostProcessor works with BeanNameAutoProxyCreator"() {
-        when:
-            // must load with XML for BeanPostProcessors to work
-            context = new ClassPathXmlApplicationContext("AutowireBeanFactoryObjectPostProcessorTests-aopconfig.xml", getClass());
-        then:
-            noExceptionThrown()
-        and: "make sure autoproxying was actually enabled"
-            context.getBean(MyAdvisedBean).doStuff() == "null"
-    }
-
-    @Configuration
-    static class WithBanNameAutoProxyCreatorConfig {
-        @Bean
-        public ObjectPostProcessor objectPostProcessor(AutowireCapableBeanFactory beanFactory) {
-            return new AutowireBeanFactoryObjectPostProcessor(beanFactory)
-        }
-
-        @Autowired
-        public void configure(ObjectPostProcessor<Object> p) {
-            p.postProcess(new Object())
-        }
-    }
+	def "Verify All Aware methods are invoked"() {
+		setup:
+			ApplicationContextAware contextAware = Mock(ApplicationContextAware)
+			ApplicationEventPublisherAware publisher = Mock(ApplicationEventPublisherAware)
+			BeanClassLoaderAware classloader = Mock(BeanClassLoaderAware)
+			BeanFactoryAware beanFactory = Mock(BeanFactoryAware)
+			EnvironmentAware environment = Mock(EnvironmentAware)
+			MessageSourceAware messageSource = Mock(MessageSourceAware)
+			ServletConfigAware servletConfig = Mock(ServletConfigAware)
+			ServletContextAware servletContext = Mock(ServletContextAware)
+			DisposableBean disposable = Mock(DisposableBean)
+
+			context = new AnnotationConfigWebApplicationContext([servletConfig:new MockServletConfig(),servletContext:new MockServletContext()])
+			context.register(Config)
+			context.refresh()
+			context.start()
+
+			ObjectPostProcessor opp = context.getBean(ObjectPostProcessor)
+		when:
+			opp.postProcess(contextAware)
+		then:
+			1 * contextAware.setApplicationContext(!null)
+
+		when:
+			opp.postProcess(publisher)
+		then:
+			1 * publisher.setApplicationEventPublisher(!null)
+
+		when:
+			opp.postProcess(classloader)
+		then:
+			1 * classloader.setBeanClassLoader(!null)
+
+		when:
+			opp.postProcess(beanFactory)
+		then:
+			1 * beanFactory.setBeanFactory(!null)
+
+		when:
+			opp.postProcess(environment)
+		then:
+			1 * environment.setEnvironment(!null)
+
+		when:
+			opp.postProcess(messageSource)
+		then:
+			1 * messageSource.setMessageSource(!null)
+
+		when:
+			opp.postProcess(servletConfig)
+		then:
+			1 * servletConfig.setServletConfig(!null)
+
+		when:
+			opp.postProcess(servletContext)
+		then:
+			1 * servletContext.setServletContext(!null)
+
+		when:
+			opp.postProcess(disposable)
+			context.close()
+			context = null
+		then:
+			1 * disposable.destroy()
+	}
+
+	@Configuration
+	static class Config {
+		@Bean
+		public ObjectPostProcessor objectPostProcessor(AutowireCapableBeanFactory beanFactory) {
+			return new AutowireBeanFactoryObjectPostProcessor(beanFactory);
+		}
+	}
+
+	def "SEC-2382: AutowireBeanFactoryObjectPostProcessor works with BeanNameAutoProxyCreator"() {
+		when:
+			// must load with XML for BeanPostProcessors to work
+			context = new ClassPathXmlApplicationContext("AutowireBeanFactoryObjectPostProcessorTests-aopconfig.xml", getClass());
+		then:
+			noExceptionThrown()
+		and: "make sure autoproxying was actually enabled"
+			context.getBean(MyAdvisedBean).doStuff() == "null"
+	}
+
+	@Configuration
+	static class WithBanNameAutoProxyCreatorConfig {
+		@Bean
+		public ObjectPostProcessor objectPostProcessor(AutowireCapableBeanFactory beanFactory) {
+			return new AutowireBeanFactoryObjectPostProcessor(beanFactory)
+		}
+
+		@Autowired
+		public void configure(ObjectPostProcessor<Object> p) {
+			p.postProcess(new Object())
+		}
+	}
 }

+ 344 - 344
config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.groovy

@@ -53,348 +53,348 @@ import org.springframework.security.core.context.SecurityContextHolder
  * @author Rob Winch
  */
 public class GlobalMethodSecurityConfigurationTests extends BaseSpringSpec {
-    def "messages set when using GlobalMethodSecurityConfiguration"() {
-        when:
-            loadConfig(InMemoryAuthWithGlobalMethodSecurityConfig)
-        then:
-            authenticationManager.messages.messageSource instanceof ApplicationContext
-    }
-
-    def "AuthenticationEventPublisher is registered GlobalMethodSecurityConfiguration"() {
-        when:
-            loadConfig(InMemoryAuthWithGlobalMethodSecurityConfig)
-        then:
-            authenticationManager.eventPublisher instanceof DefaultAuthenticationEventPublisher
-        when:
-            Authentication auth = new UsernamePasswordAuthenticationToken("user",null,AuthorityUtils.createAuthorityList("ROLE_USER"))
-            authenticationManager.eventPublisher.publishAuthenticationSuccess(auth)
-        then:
-            InMemoryAuthWithGlobalMethodSecurityConfig.EVENT.authentication == auth
-    }
-
-    @EnableGlobalMethodSecurity(prePostEnabled = true)
-    public static class InMemoryAuthWithGlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration implements ApplicationListener<AuthenticationSuccessEvent> {
-        static AuthenticationSuccessEvent EVENT
-
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-        }
-
-        @Override
-        public void onApplicationEvent(AuthenticationSuccessEvent e) {
-            EVENT = e
-        }
-    }
-
-    AuthenticationManager getAuthenticationManager() {
-        context.getBean(MethodInterceptor).authenticationManager
-    }
-
-    def "AuthenticationTrustResolver autowires"() {
-        setup:
-            CustomTrustResolverConfig.TR = Mock(AuthenticationTrustResolver)
-        when:
-            loadConfig(CustomTrustResolverConfig)
-            def preAdviceVoter = context.getBean(MethodInterceptor).accessDecisionManager.decisionVoters.find { it instanceof PreInvocationAuthorizationAdviceVoter}
-        then:
-            preAdviceVoter.preAdvice.expressionHandler.trustResolver == CustomTrustResolverConfig.TR
-    }
-
-    @EnableGlobalMethodSecurity(prePostEnabled = true)
-    static class CustomTrustResolverConfig extends GlobalMethodSecurityConfiguration {
-        static AuthenticationTrustResolver TR
-
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-        }
-
-        @Bean
-        public AuthenticationTrustResolver tr() {
-            return TR
-        }
-    }
-
-    def "SEC-2301: DefaultWebSecurityExpressionHandler has BeanResolver set"() {
-        setup:
-            SecurityContextHolder.getContext().setAuthentication(
-                new TestingAuthenticationToken("user", "password","ROLE_USER"))
-            loadConfig(ExpressionHandlerHasBeanResolverSetConfig)
-            def service = context.getBean(ServiceImpl)
-        when: "service with bean reference on PreAuthorize invoked"
-            service.message()
-        then: "properly throws AccessDeniedException"
-            thrown(AccessDeniedException)
-        when: "service with bean reference on PreAuthorize invoked"
-            context.getBean(CustomAuthzService).grantAccess = true
-            service.message()
-        then: "grants access too"
-            noExceptionThrown()
-    }
-
-    @EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
-    static class ExpressionHandlerHasBeanResolverSetConfig extends GlobalMethodSecurityConfiguration {
-
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-        }
-
-        @Bean
-        public ServiceImpl service() {
-            return new ServiceImpl()
-        }
-
-        @Bean
-        public CustomAuthzService authz() {
-            return new CustomAuthzService()
-        }
-    }
-
-    static class ServiceImpl {
-        @PreAuthorize("@authz.authorize()")
-        public String message() {
-            null
-        }
-    }
-
-    static class CustomAuthzService {
-        boolean grantAccess
-
-        public boolean authorize() {
-            grantAccess
-        }
-    }
-
-    def "Method Security supports annotations on interface parameter names"() {
-        setup:
-            SecurityContextHolder.getContext().setAuthentication(
-                new TestingAuthenticationToken("user", "password","ROLE_USER"))
-            loadConfig(MethodSecurityServiceConfig)
-            MethodSecurityService service = context.getBean(MethodSecurityService)
-        when: "service with annotated argument"
-            service.postAnnotation('deny')
-        then: "properly throws AccessDeniedException"
-            thrown(AccessDeniedException)
-        when: "service with annotated argument"
-            service.postAnnotation('grant')
-        then: "properly throws AccessDeniedException"
-            noExceptionThrown()
-    }
-
-    @EnableGlobalMethodSecurity(prePostEnabled = true)
-    static class MethodSecurityServiceConfig extends GlobalMethodSecurityConfiguration {
-
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-        }
-
-        @Bean
-        public MethodSecurityService service() {
-            new MethodSecurityServiceImpl()
-        }
-    }
-
-    def "GlobalMethodSecurityConfiguration autowires PermissionEvaluator"() {
-        setup:
-            SecurityContextHolder.getContext().setAuthentication(
-                new TestingAuthenticationToken("user", "password","ROLE_USER"))
-            PermissionEvaluator evaluator = Mock()
-            AutowirePermissionEvaluatorConfig.PE = evaluator
-            loadConfig(AutowirePermissionEvaluatorConfig)
-            MethodSecurityService service = context.getBean(MethodSecurityService)
-        when:
-            service.hasPermission("something")
-        then:
-            1 * evaluator.hasPermission(_, "something", "read") >> true
-        when:
-            service.hasPermission("something")
-        then:
-            1 * evaluator.hasPermission(_, "something", "read") >> false
-            thrown(AccessDeniedException)
-    }
-
-    @EnableGlobalMethodSecurity(prePostEnabled = true)
-    public static class AutowirePermissionEvaluatorConfig extends GlobalMethodSecurityConfiguration {
-        static PermissionEvaluator PE
-
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-        }
-
-        @Bean
-        public PermissionEvaluator pe() {
-            PE
-        }
-
-        @Bean
-        public MethodSecurityService service() {
-            new MethodSecurityServiceImpl()
-        }
-    }
-
-    def "GlobalMethodSecurityConfiguration does not failw with multiple PermissionEvaluator"() {
-        when:
-            loadConfig(MultiPermissionEvaluatorConfig)
-        then:
-            noExceptionThrown()
-    }
-
-    @EnableGlobalMethodSecurity(prePostEnabled = true)
-    public static class MultiPermissionEvaluatorConfig extends GlobalMethodSecurityConfiguration {
-        static PermissionEvaluator PE
-
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-        }
-
-        @Bean
-        public PermissionEvaluator pe() {
-            PE
-        }
-
-        @Bean
-        public PermissionEvaluator pe2() {
-            PE
-        }
-
-        @Bean
-        public MethodSecurityService service() {
-            new MethodSecurityServiceImpl()
-        }
-    }
-
-    def "SEC-2425: EnableGlobalMethodSecurity works on superclass"() {
-        setup:
-            SecurityContextHolder.getContext().setAuthentication(
-                new TestingAuthenticationToken("user", "password","ROLE_USER"))
-            loadConfig(ParentConfig)
-            MethodSecurityService service = context.getBean(MethodSecurityService)
-        when:
-            service.preAuthorize()
-        then:
-            thrown(AccessDeniedException)
-    }
-
-    static class ChildConfig extends ParentConfig {}
-
-    @EnableGlobalMethodSecurity(prePostEnabled = true)
-    static class ParentConfig {
-
-        @Autowired
-        protected void configurGlobal(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-        }
-
-        @Bean
-        public MethodSecurityService service() {
-            new MethodSecurityServiceImpl()
-        }
-    }
-
-    def "SEC-2479: Support AuthenticationManager in parent"() {
-        setup:
-            SecurityContextHolder.getContext().setAuthentication(
-                new TestingAuthenticationToken("user", "password","ROLE_USER"))
-            loadConfig(Sec2479ParentConfig)
-            def child = new AnnotationConfigApplicationContext()
-            child.register(Sec2479ChildConfig)
-            child.parent = context
-            child.refresh()
-            MethodSecurityService service = child.getBean(MethodSecurityService)
-        when:
-            service.preAuthorize()
-        then:
-            thrown(AccessDeniedException)
-        cleanup:
-            child?.close()
-    }
-
-    @Configuration
-    static class Sec2479ParentConfig {
-        static AuthenticationManager AM
-
-        @Bean
-        public AuthenticationManager am() {
-            AM
-        }
-    }
-
-    @EnableGlobalMethodSecurity(prePostEnabled = true)
-    static class Sec2479ChildConfig {
-        @Bean
-        public MethodSecurityService service() {
-            new MethodSecurityServiceImpl()
-        }
-    }
-
-    def "SEC-2815: @EnableGlobalMethodSecurity does not trigger eager initialization of Beans in GlobalAuthenticationConfigurer"() {
-        setup:
-        Sec2815Config.dataSource = Mock(DataSource)
-        when: 'load a Configuration that uses a Bean (DataSource) in a GlobalAuthenticationConfigurerAdapter'
-        loadConfig(Sec2815Config)
-        then: 'The Bean (DataSource) is still properly post processed with all BeanPostProcessor'
-        context.getBean(MockBeanPostProcessor).beforeInit['dataSource']
-        context.getBean(MockBeanPostProcessor).afterInit['dataSource']
-    }
-
-    @EnableGlobalMethodSecurity(prePostEnabled = true)
-    static class Sec2815Config {
-        static DataSource dataSource;
-
-        @Bean
-        public MethodSecurityService service() {
-            new MethodSecurityServiceImpl()
-        }
-
-        @Bean
-        public MockBeanPostProcessor mockBeanPostProcessor() {
-            new MockBeanPostProcessor()
-        }
-
-        @Bean
-        public DataSource dataSource() {
-            dataSource
-        }
-
-        @Configuration
-        static class AuthConfig extends GlobalAuthenticationConfigurerAdapter {
-            @Autowired
-            DataSource dataSource
-
-            @Override
-            void init(AuthenticationManagerBuilder auth) throws Exception {
-                auth.inMemoryAuthentication()
-            }
-        }
-    }
-
-
-    static class MockBeanPostProcessor implements BeanPostProcessor {
-        Map<String,Object> beforeInit = new HashMap<String,Object>()
-        Map<String,Object> afterInit = new HashMap<String,Object>()
-
-        @Override
-        Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
-            beforeInit[beanName] = bean
-            bean
-        }
-
-        @Override
-        Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
-            afterInit[beanName] = bean
-            bean
-        }
-    }
+	def "messages set when using GlobalMethodSecurityConfiguration"() {
+		when:
+			loadConfig(InMemoryAuthWithGlobalMethodSecurityConfig)
+		then:
+			authenticationManager.messages.messageSource instanceof ApplicationContext
+	}
+
+	def "AuthenticationEventPublisher is registered GlobalMethodSecurityConfiguration"() {
+		when:
+			loadConfig(InMemoryAuthWithGlobalMethodSecurityConfig)
+		then:
+			authenticationManager.eventPublisher instanceof DefaultAuthenticationEventPublisher
+		when:
+			Authentication auth = new UsernamePasswordAuthenticationToken("user",null,AuthorityUtils.createAuthorityList("ROLE_USER"))
+			authenticationManager.eventPublisher.publishAuthenticationSuccess(auth)
+		then:
+			InMemoryAuthWithGlobalMethodSecurityConfig.EVENT.authentication == auth
+	}
+
+	@EnableGlobalMethodSecurity(prePostEnabled = true)
+	public static class InMemoryAuthWithGlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration implements ApplicationListener<AuthenticationSuccessEvent> {
+		static AuthenticationSuccessEvent EVENT
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+		}
+
+		@Override
+		public void onApplicationEvent(AuthenticationSuccessEvent e) {
+			EVENT = e
+		}
+	}
+
+	AuthenticationManager getAuthenticationManager() {
+		context.getBean(MethodInterceptor).authenticationManager
+	}
+
+	def "AuthenticationTrustResolver autowires"() {
+		setup:
+			CustomTrustResolverConfig.TR = Mock(AuthenticationTrustResolver)
+		when:
+			loadConfig(CustomTrustResolverConfig)
+			def preAdviceVoter = context.getBean(MethodInterceptor).accessDecisionManager.decisionVoters.find { it instanceof PreInvocationAuthorizationAdviceVoter}
+		then:
+			preAdviceVoter.preAdvice.expressionHandler.trustResolver == CustomTrustResolverConfig.TR
+	}
+
+	@EnableGlobalMethodSecurity(prePostEnabled = true)
+	static class CustomTrustResolverConfig extends GlobalMethodSecurityConfiguration {
+		static AuthenticationTrustResolver TR
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+		}
+
+		@Bean
+		public AuthenticationTrustResolver tr() {
+			return TR
+		}
+	}
+
+	def "SEC-2301: DefaultWebSecurityExpressionHandler has BeanResolver set"() {
+		setup:
+			SecurityContextHolder.getContext().setAuthentication(
+				new TestingAuthenticationToken("user", "password","ROLE_USER"))
+			loadConfig(ExpressionHandlerHasBeanResolverSetConfig)
+			def service = context.getBean(ServiceImpl)
+		when: "service with bean reference on PreAuthorize invoked"
+			service.message()
+		then: "properly throws AccessDeniedException"
+			thrown(AccessDeniedException)
+		when: "service with bean reference on PreAuthorize invoked"
+			context.getBean(CustomAuthzService).grantAccess = true
+			service.message()
+		then: "grants access too"
+			noExceptionThrown()
+	}
+
+	@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
+	static class ExpressionHandlerHasBeanResolverSetConfig extends GlobalMethodSecurityConfiguration {
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+		}
+
+		@Bean
+		public ServiceImpl service() {
+			return new ServiceImpl()
+		}
+
+		@Bean
+		public CustomAuthzService authz() {
+			return new CustomAuthzService()
+		}
+	}
+
+	static class ServiceImpl {
+		@PreAuthorize("@authz.authorize()")
+		public String message() {
+			null
+		}
+	}
+
+	static class CustomAuthzService {
+		boolean grantAccess
+
+		public boolean authorize() {
+			grantAccess
+		}
+	}
+
+	def "Method Security supports annotations on interface parameter names"() {
+		setup:
+			SecurityContextHolder.getContext().setAuthentication(
+				new TestingAuthenticationToken("user", "password","ROLE_USER"))
+			loadConfig(MethodSecurityServiceConfig)
+			MethodSecurityService service = context.getBean(MethodSecurityService)
+		when: "service with annotated argument"
+			service.postAnnotation('deny')
+		then: "properly throws AccessDeniedException"
+			thrown(AccessDeniedException)
+		when: "service with annotated argument"
+			service.postAnnotation('grant')
+		then: "properly throws AccessDeniedException"
+			noExceptionThrown()
+	}
+
+	@EnableGlobalMethodSecurity(prePostEnabled = true)
+	static class MethodSecurityServiceConfig extends GlobalMethodSecurityConfiguration {
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+		}
+
+		@Bean
+		public MethodSecurityService service() {
+			new MethodSecurityServiceImpl()
+		}
+	}
+
+	def "GlobalMethodSecurityConfiguration autowires PermissionEvaluator"() {
+		setup:
+			SecurityContextHolder.getContext().setAuthentication(
+				new TestingAuthenticationToken("user", "password","ROLE_USER"))
+			PermissionEvaluator evaluator = Mock()
+			AutowirePermissionEvaluatorConfig.PE = evaluator
+			loadConfig(AutowirePermissionEvaluatorConfig)
+			MethodSecurityService service = context.getBean(MethodSecurityService)
+		when:
+			service.hasPermission("something")
+		then:
+			1 * evaluator.hasPermission(_, "something", "read") >> true
+		when:
+			service.hasPermission("something")
+		then:
+			1 * evaluator.hasPermission(_, "something", "read") >> false
+			thrown(AccessDeniedException)
+	}
+
+	@EnableGlobalMethodSecurity(prePostEnabled = true)
+	public static class AutowirePermissionEvaluatorConfig extends GlobalMethodSecurityConfiguration {
+		static PermissionEvaluator PE
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+		}
+
+		@Bean
+		public PermissionEvaluator pe() {
+			PE
+		}
+
+		@Bean
+		public MethodSecurityService service() {
+			new MethodSecurityServiceImpl()
+		}
+	}
+
+	def "GlobalMethodSecurityConfiguration does not failw with multiple PermissionEvaluator"() {
+		when:
+			loadConfig(MultiPermissionEvaluatorConfig)
+		then:
+			noExceptionThrown()
+	}
+
+	@EnableGlobalMethodSecurity(prePostEnabled = true)
+	public static class MultiPermissionEvaluatorConfig extends GlobalMethodSecurityConfiguration {
+		static PermissionEvaluator PE
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+		}
+
+		@Bean
+		public PermissionEvaluator pe() {
+			PE
+		}
+
+		@Bean
+		public PermissionEvaluator pe2() {
+			PE
+		}
+
+		@Bean
+		public MethodSecurityService service() {
+			new MethodSecurityServiceImpl()
+		}
+	}
+
+	def "SEC-2425: EnableGlobalMethodSecurity works on superclass"() {
+		setup:
+			SecurityContextHolder.getContext().setAuthentication(
+				new TestingAuthenticationToken("user", "password","ROLE_USER"))
+			loadConfig(ParentConfig)
+			MethodSecurityService service = context.getBean(MethodSecurityService)
+		when:
+			service.preAuthorize()
+		then:
+			thrown(AccessDeniedException)
+	}
+
+	static class ChildConfig extends ParentConfig {}
+
+	@EnableGlobalMethodSecurity(prePostEnabled = true)
+	static class ParentConfig {
+
+		@Autowired
+		protected void configurGlobal(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+		}
+
+		@Bean
+		public MethodSecurityService service() {
+			new MethodSecurityServiceImpl()
+		}
+	}
+
+	def "SEC-2479: Support AuthenticationManager in parent"() {
+		setup:
+			SecurityContextHolder.getContext().setAuthentication(
+				new TestingAuthenticationToken("user", "password","ROLE_USER"))
+			loadConfig(Sec2479ParentConfig)
+			def child = new AnnotationConfigApplicationContext()
+			child.register(Sec2479ChildConfig)
+			child.parent = context
+			child.refresh()
+			MethodSecurityService service = child.getBean(MethodSecurityService)
+		when:
+			service.preAuthorize()
+		then:
+			thrown(AccessDeniedException)
+		cleanup:
+			child?.close()
+	}
+
+	@Configuration
+	static class Sec2479ParentConfig {
+		static AuthenticationManager AM
+
+		@Bean
+		public AuthenticationManager am() {
+			AM
+		}
+	}
+
+	@EnableGlobalMethodSecurity(prePostEnabled = true)
+	static class Sec2479ChildConfig {
+		@Bean
+		public MethodSecurityService service() {
+			new MethodSecurityServiceImpl()
+		}
+	}
+
+	def "SEC-2815: @EnableGlobalMethodSecurity does not trigger eager initialization of Beans in GlobalAuthenticationConfigurer"() {
+		setup:
+		Sec2815Config.dataSource = Mock(DataSource)
+		when: 'load a Configuration that uses a Bean (DataSource) in a GlobalAuthenticationConfigurerAdapter'
+		loadConfig(Sec2815Config)
+		then: 'The Bean (DataSource) is still properly post processed with all BeanPostProcessor'
+		context.getBean(MockBeanPostProcessor).beforeInit['dataSource']
+		context.getBean(MockBeanPostProcessor).afterInit['dataSource']
+	}
+
+	@EnableGlobalMethodSecurity(prePostEnabled = true)
+	static class Sec2815Config {
+		static DataSource dataSource;
+
+		@Bean
+		public MethodSecurityService service() {
+			new MethodSecurityServiceImpl()
+		}
+
+		@Bean
+		public MockBeanPostProcessor mockBeanPostProcessor() {
+			new MockBeanPostProcessor()
+		}
+
+		@Bean
+		public DataSource dataSource() {
+			dataSource
+		}
+
+		@Configuration
+		static class AuthConfig extends GlobalAuthenticationConfigurerAdapter {
+			@Autowired
+			DataSource dataSource
+
+			@Override
+			void init(AuthenticationManagerBuilder auth) throws Exception {
+				auth.inMemoryAuthentication()
+			}
+		}
+	}
+
+
+	static class MockBeanPostProcessor implements BeanPostProcessor {
+		Map<String,Object> beforeInit = new HashMap<String,Object>()
+		Map<String,Object> afterInit = new HashMap<String,Object>()
+
+		@Override
+		Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+			beforeInit[beanName] = bean
+			bean
+		}
+
+		@Override
+		Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+			afterInit[beanName] = bean
+			bean
+		}
+	}
 }

+ 20 - 20
config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/MethodSecurityService.groovy

@@ -30,33 +30,33 @@ import org.springframework.security.core.Authentication
  * @author Rob Winch
  */
 public interface MethodSecurityService {
-    @PreAuthorize("denyAll")
-    public String preAuthorize();
+	@PreAuthorize("denyAll")
+	public String preAuthorize();
 
-    @Secured("ROLE_ADMIN")
-    public String secured();
+	@Secured("ROLE_ADMIN")
+	public String secured();
 
-    @Secured("ROLE_USER")
-    public String securedUser();
+	@Secured("ROLE_USER")
+	public String securedUser();
 
-    @DenyAll
-    public String jsr250();
+	@DenyAll
+	public String jsr250();
 
-    @PermitAll
-    public String jsr250PermitAll();
+	@PermitAll
+	public String jsr250PermitAll();
 
-    @Secured(["ROLE_USER","RUN_AS_SUPER"])
-    public Authentication runAs();
+	@Secured(["ROLE_USER","RUN_AS_SUPER"])
+	public Authentication runAs();
 
-    @PreAuthorize("permitAll")
-    public String preAuthorizePermitAll();
+	@PreAuthorize("permitAll")
+	public String preAuthorizePermitAll();
 
-    @PreAuthorize("hasPermission(#object,'read')")
-    public String hasPermission(String object);
+	@PreAuthorize("hasPermission(#object,'read')")
+	public String hasPermission(String object);
 
-    @PostAuthorize("hasPermission(#object,'read')")
-    public String postHasPermission(String object);
+	@PostAuthorize("hasPermission(#object,'read')")
+	public String postHasPermission(String object);
 
-    @PostAuthorize("#o?.contains('grant')")
-    public String postAnnotation(@P("o") String object);
+	@PostAuthorize("#o?.contains('grant')")
+	public String postAnnotation(@P("o") String object);
 }

+ 40 - 40
config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/MethodSecurityServiceImpl.groovy

@@ -25,53 +25,53 @@ import org.springframework.security.core.context.SecurityContextHolder
  */
 public class MethodSecurityServiceImpl implements MethodSecurityService {
 
-    @Override
-    public String preAuthorize() {
-        return null;
-    }
+	@Override
+	public String preAuthorize() {
+		return null;
+	}
 
-    @Override
-    public String secured() {
-        return null;
-    }
+	@Override
+	public String secured() {
+		return null;
+	}
 
-    @Override
-    public String securedUser() {
-        return null;
-    }
+	@Override
+	public String securedUser() {
+		return null;
+	}
 
-    @Override
-    public String jsr250() {
-        return null;
-    }
+	@Override
+	public String jsr250() {
+		return null;
+	}
 
-    @Override
-    public String jsr250PermitAll() {
-        return null;
-    }
+	@Override
+	public String jsr250PermitAll() {
+		return null;
+	}
 
-    @Override
-    public Authentication runAs() {
-        return SecurityContextHolder.getContext().getAuthentication();
-    }
+	@Override
+	public Authentication runAs() {
+		return SecurityContextHolder.getContext().getAuthentication();
+	}
 
-    @Override
-    public String preAuthorizePermitAll() {
-        return null;
-    }
+	@Override
+	public String preAuthorizePermitAll() {
+		return null;
+	}
 
-    @Override
-    public String hasPermission(String object) {
-        return null;
-    }
+	@Override
+	public String hasPermission(String object) {
+		return null;
+	}
 
-    @Override
-    public String postHasPermission(String object) {
-        return null;
-    }
+	@Override
+	public String postHasPermission(String object) {
+		return null;
+	}
 
-    @Override
-    public String postAnnotation(String object) {
-        return null;
-    }
+	@Override
+	public String postAnnotation(String object) {
+		return null;
+	}
 }

+ 46 - 46
config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityExpressionHandlerTests.groovy

@@ -40,53 +40,53 @@ import org.springframework.security.core.context.SecurityContextHolder
  * @author Rob Winch
  */
 public class NamespaceGlobalMethodSecurityExpressionHandlerTests extends BaseSpringSpec {
-    def setup() {
-        SecurityContextHolder.getContext().setAuthentication(
-                        new TestingAuthenticationToken("user", "password","ROLE_USER"))
-    }
+	def setup() {
+		SecurityContextHolder.getContext().setAuthentication(
+						new TestingAuthenticationToken("user", "password","ROLE_USER"))
+	}
 
-    def "global-method-security/expression-handler @PreAuthorize"() {
-        setup:
-        context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomAccessDecisionManagerConfig)
-        MethodSecurityService service = context.getBean(MethodSecurityService)
-        when:
-        service.hasPermission("granted")
-        then:
-        noExceptionThrown()
-        when:
-        service.hasPermission("denied")
-        then:
-        thrown(AccessDeniedException)
-    }
+	def "global-method-security/expression-handler @PreAuthorize"() {
+		setup:
+		context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomAccessDecisionManagerConfig)
+		MethodSecurityService service = context.getBean(MethodSecurityService)
+		when:
+		service.hasPermission("granted")
+		then:
+		noExceptionThrown()
+		when:
+		service.hasPermission("denied")
+		then:
+		thrown(AccessDeniedException)
+	}
 
-    def "global-method-security/expression-handler @PostAuthorize"() {
-        setup:
-        context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomAccessDecisionManagerConfig)
-        MethodSecurityService service = context.getBean(MethodSecurityService)
-        when:
-        service.postHasPermission("granted")
-        then:
-        noExceptionThrown()
-        when:
-        service.postHasPermission("denied")
-        then:
-        thrown(AccessDeniedException)
-    }
+	def "global-method-security/expression-handler @PostAuthorize"() {
+		setup:
+		context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomAccessDecisionManagerConfig)
+		MethodSecurityService service = context.getBean(MethodSecurityService)
+		when:
+		service.postHasPermission("granted")
+		then:
+		noExceptionThrown()
+		when:
+		service.postHasPermission("denied")
+		then:
+		thrown(AccessDeniedException)
+	}
 
-    @EnableGlobalMethodSecurity(prePostEnabled = true)
-    public static class CustomAccessDecisionManagerConfig extends GlobalMethodSecurityConfiguration {
-        @Override
-        protected MethodSecurityExpressionHandler createExpressionHandler() {
-            DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler()
-            expressionHandler.permissionEvaluator = new PermissionEvaluator() {
-                boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
-                    "granted" == targetDomainObject
-                }
-                boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
-                    throw new UnsupportedOperationException()
-                }
-            }
-            return expressionHandler
-        }
-    }
+	@EnableGlobalMethodSecurity(prePostEnabled = true)
+	public static class CustomAccessDecisionManagerConfig extends GlobalMethodSecurityConfiguration {
+		@Override
+		protected MethodSecurityExpressionHandler createExpressionHandler() {
+			DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler()
+			expressionHandler.permissionEvaluator = new PermissionEvaluator() {
+				boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
+					"granted" == targetDomainObject
+				}
+				boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
+					throw new UnsupportedOperationException()
+				}
+			}
+			return expressionHandler
+		}
+	}
 }

+ 383 - 383
config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityTests.groovy

@@ -57,387 +57,387 @@ import org.springframework.security.core.context.SecurityContextHolder
  * @author Rob Winch
  */
 public class NamespaceGlobalMethodSecurityTests extends BaseSpringSpec {
-    def setup() {
-        SecurityContextHolder.getContext().setAuthentication(
-                        new TestingAuthenticationToken("user", "password","ROLE_USER"))
-    }
-
-    // --- access-decision-manager-ref ---
-
-    def "custom AccessDecisionManager can be used"() {
-        setup: "Create an instance with an AccessDecisionManager that always denies access"
-            context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomAccessDecisionManagerConfig)
-            MethodSecurityService service = context.getBean(MethodSecurityService)
-        when:
-            service.preAuthorize()
-        then:
-            thrown(AccessDeniedException)
-        when:
-            service.secured()
-        then:
-            thrown(AccessDeniedException)
-    }
-
-    @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
-    public static class CustomAccessDecisionManagerConfig extends GlobalMethodSecurityConfiguration {
-        @Override
-        protected AccessDecisionManager accessDecisionManager() {
-            return new DenyAllAccessDecisionManager()
-        }
-
-        public static class DenyAllAccessDecisionManager implements AccessDecisionManager {
-            public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) {
-                throw new AccessDeniedException("Always Denied")
-            }
-            public boolean supports(ConfigAttribute attribute) {
-                return true
-            }
-            public boolean supports(Class<?> clazz) {
-                return true
-            }
-        }
-    }
-
-    // --- authentication-manager-ref ---
-
-    def "custom AuthenticationManager can be used"() {
-        when:
-            context = new AnnotationConfigApplicationContext(CustomAuthenticationConfig)
-        MethodSecurityInterceptor interceptor = context.getBean(MethodSecurityInterceptor)
-            interceptor.authenticationManager.authenticate(SecurityContextHolder.context.authentication)
-        then:
-            thrown(UnsupportedOperationException)
-    }
-
-    @EnableGlobalMethodSecurity
-    public static class CustomAuthenticationConfig extends GlobalMethodSecurityConfiguration {
-        @Override
-        protected AuthenticationManager authenticationManager() {
-            return new AuthenticationManager() {
-                Authentication authenticate(Authentication authentication) {
-                    throw new UnsupportedOperationException()
-                }
-            }
-        }
-    }
-
-    // --- jsr250-annotations ---
-
-    def "enable jsr250"() {
-        when:
-            context = new AnnotationConfigApplicationContext(Jsr250Config)
-            MethodSecurityService service = context.getBean(MethodSecurityService)
-        then: "@Secured and @PreAuthorize are ignored"
-            service.secured() == null
-            service.preAuthorize() ==  null
-
-        when: "@DenyAll method invoked"
-            service.jsr250()
-        then: "access is denied"
-            thrown(AccessDeniedException)
-        when: "@PermitAll method invoked"
-            String jsr250PermitAll = service.jsr250PermitAll()
-        then: "access is allowed"
-            jsr250PermitAll == null
-    }
-
-    @EnableGlobalMethodSecurity(jsr250Enabled = true)
-    @Configuration
-    public static class Jsr250Config extends BaseMethodConfig {
-    }
-
-    // --- metadata-source-ref ---
-
-    def "custom MethodSecurityMetadataSource can be used with higher priority than other sources"() {
-        setup:
-            context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomMethodSecurityMetadataSourceConfig)
-            MethodSecurityService service = context.getBean(MethodSecurityService)
-        when:
-            service.preAuthorize()
-        then:
-            thrown(AccessDeniedException)
-        when:
-            service.secured()
-        then:
-            thrown(AccessDeniedException)
-        when:
-            service.jsr250()
-        then:
-            thrown(AccessDeniedException)
-    }
-
-    @EnableGlobalMethodSecurity
-    public static class CustomMethodSecurityMetadataSourceConfig extends GlobalMethodSecurityConfiguration {
-        @Override
-        protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() {
-            return new AbstractMethodSecurityMetadataSource() {
-                public Collection<ConfigAttribute> getAttributes(Method method, Class<?> targetClass) {
-                    // require ROLE_NOBODY for any method on MethodSecurityService class
-                    return MethodSecurityService.isAssignableFrom(targetClass) ? [new SecurityConfig("ROLE_NOBODY")] : []
-                }
-                public Collection<ConfigAttribute> getAllConfigAttributes() {
-                    return null
-                }
-            }
-        }
-    }
-
-    // --- mode ---
-
-    def "aspectj mode works"() {
-        when:
-            context = new AnnotationConfigApplicationContext(AspectJModeConfig)
-        then:
-            context.getBean(AnnotationSecurityAspect)
-            context.getBean(AspectJMethodSecurityInterceptor)
-    }
-
-    @EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ, proxyTargetClass = true)
-    public static class AspectJModeConfig extends BaseMethodConfig {
-    }
-
-    def "aspectj mode works extending GlobalMethodSecurityConfiguration"() {
-        when:
-            context = new AnnotationConfigApplicationContext(BaseMethodConfig,AspectJModeExtendsGMSCConfig)
-        then:
-            context.getBean(AnnotationSecurityAspect)
-            context.getBean(AspectJMethodSecurityInterceptor)
-    }
-
-    @EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ)
-    public static class AspectJModeExtendsGMSCConfig extends GlobalMethodSecurityConfiguration {
-    }
-
-    // --- order ---
-
-    def order() {
-        when:
-            context = new AnnotationConfigApplicationContext(CustomOrderConfig)
-            MethodSecurityMetadataSourceAdvisor advisor = context.getBean(MethodSecurityMetadataSourceAdvisor)
-        then:
-            advisor.order == 135
-    }
-
-    @EnableGlobalMethodSecurity(order = 135)
-    public static class CustomOrderConfig extends BaseMethodConfig {
-    }
-
-    def "order is defaulted to Ordered.LOWEST_PRECEDENCE when using @EnableGlobalMethodSecurity"() {
-        when:
-            context = new AnnotationConfigApplicationContext(DefaultOrderConfig)
-            MethodSecurityMetadataSourceAdvisor advisor = context.getBean(MethodSecurityMetadataSourceAdvisor)
-        then:
-            advisor.order == Ordered.LOWEST_PRECEDENCE
-    }
-
-    @EnableGlobalMethodSecurity
-    public static class DefaultOrderConfig extends BaseMethodConfig {
-    }
-
-    def "order is defaulted to Ordered.LOWEST_PRECEDENCE when extending GlobalMethodSecurityConfiguration"() {
-        when:
-            context = new AnnotationConfigApplicationContext(BaseMethodConfig,DefaultOrderExtendsMethodSecurityConfig)
-            MethodSecurityMetadataSourceAdvisor advisor = context.getBean(MethodSecurityMetadataSourceAdvisor)
-        then:
-            advisor.order == Ordered.LOWEST_PRECEDENCE
-    }
-
-    @EnableGlobalMethodSecurity
-    public static class DefaultOrderExtendsMethodSecurityConfig extends GlobalMethodSecurityConfiguration {
-    }
-
-    // --- pre-post-annotations ---
-
-    def preAuthorize() {
-        when:
-            context = new AnnotationConfigApplicationContext(PreAuthorizeConfig)
-            MethodSecurityService service = context.getBean(MethodSecurityService)
-        then:
-            service.secured() == null
-            service.jsr250() == null
-
-        when:
-            service.preAuthorize()
-        then:
-            thrown(AccessDeniedException)
-    }
-
-    @EnableGlobalMethodSecurity(prePostEnabled = true)
-    @Configuration
-    public static class PreAuthorizeConfig extends BaseMethodConfig {
-    }
-
-    def "prePostEnabled extends GlobalMethodSecurityConfiguration"() {
-        when:
-            context = new AnnotationConfigApplicationContext(BaseMethodConfig,PreAuthorizeExtendsGMSCConfig)
-            MethodSecurityService service = context.getBean(MethodSecurityService)
-        then:
-            service.secured() == null
-            service.jsr250() == null
-
-        when:
-            service.preAuthorize()
-        then:
-            thrown(AccessDeniedException)
-    }
-
-    @EnableGlobalMethodSecurity(prePostEnabled = true)
-    @Configuration
-    public static class PreAuthorizeExtendsGMSCConfig extends GlobalMethodSecurityConfiguration {
-    }
-
-    // --- proxy-target-class ---
-
-    def "proxying classes works"() {
-        when:
-            context = new AnnotationConfigApplicationContext(ProxyTargetClass)
-            MethodSecurityServiceImpl service = context.getBean(MethodSecurityServiceImpl)
-        then:
-            noExceptionThrown()
-    }
-
-    @EnableGlobalMethodSecurity(proxyTargetClass = true)
-    @Configuration
-    public static class ProxyTargetClass extends BaseMethodConfig {
-    }
-
-    def "proxying interfaces works"() {
-        when:
-            context = new AnnotationConfigApplicationContext(PreAuthorizeConfig)
-            MethodSecurityService service = context.getBean(MethodSecurityService)
-        then: "we get an instance of the interface"
-            noExceptionThrown()
-        when: "try to cast to the class"
-            MethodSecurityServiceImpl serviceImpl = service
-        then: "we get a class cast exception"
-            thrown(ClassCastException)
-    }
-
-    // --- run-as-manager-ref ---
-
-    def "custom RunAsManager"() {
-        when:
-            context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomRunAsManagerConfig)
-            MethodSecurityService service = context.getBean(MethodSecurityService)
-        then:
-            service.runAs().authorities.find { it.authority == "ROLE_RUN_AS_SUPER"}
-    }
-
-    @EnableGlobalMethodSecurity(securedEnabled = true)
-    public static class CustomRunAsManagerConfig extends GlobalMethodSecurityConfiguration {
-        @Override
-        protected RunAsManager runAsManager() {
-            RunAsManagerImpl runAsManager = new RunAsManagerImpl()
-            runAsManager.setKey("some key")
-            return runAsManager
-        }
-    }
-
-    // --- secured-annotation ---
-
-    def "secured enabled"() {
-        setup:
-            context = new AnnotationConfigApplicationContext(SecuredConfig)
-            MethodSecurityService service = context.getBean(MethodSecurityService)
-        when:
-            service.secured()
-        then:
-            thrown(AccessDeniedException)
-        and: "service with ROLE_USER allowed"
-            service.securedUser() == null
-        and:
-            service.preAuthorize() == null
-            service.jsr250() == null
-    }
-
-    @EnableGlobalMethodSecurity(securedEnabled = true)
-    @Configuration
-    public static class SecuredConfig extends BaseMethodConfig {
-    }
-
-    // --- after-invocation-provider
-
-    def "custom AfterInvocationManager"() {
-        setup:
-            context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomAfterInvocationManagerConfig)
-            MethodSecurityService service = context.getBean(MethodSecurityService)
-        when:
-            service.preAuthorizePermitAll()
-        then:
-            AccessDeniedException e = thrown()
-            e.message == "custom AfterInvocationManager"
-    }
-
-    @EnableGlobalMethodSecurity(prePostEnabled = true)
-    public static class CustomAfterInvocationManagerConfig extends GlobalMethodSecurityConfiguration {
-        @Override
-        protected AfterInvocationManager afterInvocationManager() {
-            return new AfterInvocationManagerStub()
-        }
-
-        public static class AfterInvocationManagerStub implements AfterInvocationManager {
-            Object decide(Authentication authentication, Object object, Collection<ConfigAttribute> attributes,
-                Object returnedObject) throws AccessDeniedException {
-                throw new AccessDeniedException("custom AfterInvocationManager")
-            }
-
-            boolean supports(ConfigAttribute attribute) {
-                return true
-            }
-            boolean supports(Class<?> clazz) {
-                return true
-            }
-        }
-    }
-
-    // --- misc ---
-
-    def "good error message when no Enable annotation"() {
-        when:
-            context = new AnnotationConfigApplicationContext(ExtendsNoEnableAnntotationConfig)
-            MethodSecurityInterceptor interceptor = context.getBean(MethodSecurityInterceptor)
-            interceptor.authenticationManager.authenticate(SecurityContextHolder.context.authentication)
-        then:
-            BeanCreationException e = thrown()
-            e.message.contains(EnableGlobalMethodSecurity.class.getName() + " is required")
-    }
-
-    @Configuration
-    public static class ExtendsNoEnableAnntotationConfig extends GlobalMethodSecurityConfiguration {
-        @Override
-        protected AuthenticationManager authenticationManager() {
-            return new AuthenticationManager() {
-                Authentication authenticate(Authentication authentication) {
-                    throw new UnsupportedOperationException()
-                }
-            }
-        }
-    }
-
-    def "import subclass of GlobalMethodSecurityConfiguration"() {
-        when:
-            context = new AnnotationConfigApplicationContext(ImportSubclassGMSCConfig)
-            MethodSecurityService service = context.getBean(MethodSecurityService)
-        then:
-            service.secured() == null
-            service.jsr250() == null
-
-        when:
-            service.preAuthorize()
-        then:
-            thrown(AccessDeniedException)
-    }
-
-    @Configuration
-    @Import(PreAuthorizeExtendsGMSCConfig)
-    public static class ImportSubclassGMSCConfig extends BaseMethodConfig {
-    }
-
-    @Configuration
-    public static class BaseMethodConfig extends BaseAuthenticationConfig {
-        @Bean
-        public MethodSecurityService methodSecurityService() {
-            return new MethodSecurityServiceImpl()
-        }
-    }
+	def setup() {
+		SecurityContextHolder.getContext().setAuthentication(
+						new TestingAuthenticationToken("user", "password","ROLE_USER"))
+	}
+
+	// --- access-decision-manager-ref ---
+
+	def "custom AccessDecisionManager can be used"() {
+		setup: "Create an instance with an AccessDecisionManager that always denies access"
+			context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomAccessDecisionManagerConfig)
+			MethodSecurityService service = context.getBean(MethodSecurityService)
+		when:
+			service.preAuthorize()
+		then:
+			thrown(AccessDeniedException)
+		when:
+			service.secured()
+		then:
+			thrown(AccessDeniedException)
+	}
+
+	@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
+	public static class CustomAccessDecisionManagerConfig extends GlobalMethodSecurityConfiguration {
+		@Override
+		protected AccessDecisionManager accessDecisionManager() {
+			return new DenyAllAccessDecisionManager()
+		}
+
+		public static class DenyAllAccessDecisionManager implements AccessDecisionManager {
+			public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) {
+				throw new AccessDeniedException("Always Denied")
+			}
+			public boolean supports(ConfigAttribute attribute) {
+				return true
+			}
+			public boolean supports(Class<?> clazz) {
+				return true
+			}
+		}
+	}
+
+	// --- authentication-manager-ref ---
+
+	def "custom AuthenticationManager can be used"() {
+		when:
+			context = new AnnotationConfigApplicationContext(CustomAuthenticationConfig)
+		MethodSecurityInterceptor interceptor = context.getBean(MethodSecurityInterceptor)
+			interceptor.authenticationManager.authenticate(SecurityContextHolder.context.authentication)
+		then:
+			thrown(UnsupportedOperationException)
+	}
+
+	@EnableGlobalMethodSecurity
+	public static class CustomAuthenticationConfig extends GlobalMethodSecurityConfiguration {
+		@Override
+		protected AuthenticationManager authenticationManager() {
+			return new AuthenticationManager() {
+				Authentication authenticate(Authentication authentication) {
+					throw new UnsupportedOperationException()
+				}
+			}
+		}
+	}
+
+	// --- jsr250-annotations ---
+
+	def "enable jsr250"() {
+		when:
+			context = new AnnotationConfigApplicationContext(Jsr250Config)
+			MethodSecurityService service = context.getBean(MethodSecurityService)
+		then: "@Secured and @PreAuthorize are ignored"
+			service.secured() == null
+			service.preAuthorize() ==  null
+
+		when: "@DenyAll method invoked"
+			service.jsr250()
+		then: "access is denied"
+			thrown(AccessDeniedException)
+		when: "@PermitAll method invoked"
+			String jsr250PermitAll = service.jsr250PermitAll()
+		then: "access is allowed"
+			jsr250PermitAll == null
+	}
+
+	@EnableGlobalMethodSecurity(jsr250Enabled = true)
+	@Configuration
+	public static class Jsr250Config extends BaseMethodConfig {
+	}
+
+	// --- metadata-source-ref ---
+
+	def "custom MethodSecurityMetadataSource can be used with higher priority than other sources"() {
+		setup:
+			context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomMethodSecurityMetadataSourceConfig)
+			MethodSecurityService service = context.getBean(MethodSecurityService)
+		when:
+			service.preAuthorize()
+		then:
+			thrown(AccessDeniedException)
+		when:
+			service.secured()
+		then:
+			thrown(AccessDeniedException)
+		when:
+			service.jsr250()
+		then:
+			thrown(AccessDeniedException)
+	}
+
+	@EnableGlobalMethodSecurity
+	public static class CustomMethodSecurityMetadataSourceConfig extends GlobalMethodSecurityConfiguration {
+		@Override
+		protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() {
+			return new AbstractMethodSecurityMetadataSource() {
+				public Collection<ConfigAttribute> getAttributes(Method method, Class<?> targetClass) {
+					// require ROLE_NOBODY for any method on MethodSecurityService class
+					return MethodSecurityService.isAssignableFrom(targetClass) ? [new SecurityConfig("ROLE_NOBODY")] : []
+				}
+				public Collection<ConfigAttribute> getAllConfigAttributes() {
+					return null
+				}
+			}
+		}
+	}
+
+	// --- mode ---
+
+	def "aspectj mode works"() {
+		when:
+			context = new AnnotationConfigApplicationContext(AspectJModeConfig)
+		then:
+			context.getBean(AnnotationSecurityAspect)
+			context.getBean(AspectJMethodSecurityInterceptor)
+	}
+
+	@EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ, proxyTargetClass = true)
+	public static class AspectJModeConfig extends BaseMethodConfig {
+	}
+
+	def "aspectj mode works extending GlobalMethodSecurityConfiguration"() {
+		when:
+			context = new AnnotationConfigApplicationContext(BaseMethodConfig,AspectJModeExtendsGMSCConfig)
+		then:
+			context.getBean(AnnotationSecurityAspect)
+			context.getBean(AspectJMethodSecurityInterceptor)
+	}
+
+	@EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ)
+	public static class AspectJModeExtendsGMSCConfig extends GlobalMethodSecurityConfiguration {
+	}
+
+	// --- order ---
+
+	def order() {
+		when:
+			context = new AnnotationConfigApplicationContext(CustomOrderConfig)
+			MethodSecurityMetadataSourceAdvisor advisor = context.getBean(MethodSecurityMetadataSourceAdvisor)
+		then:
+			advisor.order == 135
+	}
+
+	@EnableGlobalMethodSecurity(order = 135)
+	public static class CustomOrderConfig extends BaseMethodConfig {
+	}
+
+	def "order is defaulted to Ordered.LOWEST_PRECEDENCE when using @EnableGlobalMethodSecurity"() {
+		when:
+			context = new AnnotationConfigApplicationContext(DefaultOrderConfig)
+			MethodSecurityMetadataSourceAdvisor advisor = context.getBean(MethodSecurityMetadataSourceAdvisor)
+		then:
+			advisor.order == Ordered.LOWEST_PRECEDENCE
+	}
+
+	@EnableGlobalMethodSecurity
+	public static class DefaultOrderConfig extends BaseMethodConfig {
+	}
+
+	def "order is defaulted to Ordered.LOWEST_PRECEDENCE when extending GlobalMethodSecurityConfiguration"() {
+		when:
+			context = new AnnotationConfigApplicationContext(BaseMethodConfig,DefaultOrderExtendsMethodSecurityConfig)
+			MethodSecurityMetadataSourceAdvisor advisor = context.getBean(MethodSecurityMetadataSourceAdvisor)
+		then:
+			advisor.order == Ordered.LOWEST_PRECEDENCE
+	}
+
+	@EnableGlobalMethodSecurity
+	public static class DefaultOrderExtendsMethodSecurityConfig extends GlobalMethodSecurityConfiguration {
+	}
+
+	// --- pre-post-annotations ---
+
+	def preAuthorize() {
+		when:
+			context = new AnnotationConfigApplicationContext(PreAuthorizeConfig)
+			MethodSecurityService service = context.getBean(MethodSecurityService)
+		then:
+			service.secured() == null
+			service.jsr250() == null
+
+		when:
+			service.preAuthorize()
+		then:
+			thrown(AccessDeniedException)
+	}
+
+	@EnableGlobalMethodSecurity(prePostEnabled = true)
+	@Configuration
+	public static class PreAuthorizeConfig extends BaseMethodConfig {
+	}
+
+	def "prePostEnabled extends GlobalMethodSecurityConfiguration"() {
+		when:
+			context = new AnnotationConfigApplicationContext(BaseMethodConfig,PreAuthorizeExtendsGMSCConfig)
+			MethodSecurityService service = context.getBean(MethodSecurityService)
+		then:
+			service.secured() == null
+			service.jsr250() == null
+
+		when:
+			service.preAuthorize()
+		then:
+			thrown(AccessDeniedException)
+	}
+
+	@EnableGlobalMethodSecurity(prePostEnabled = true)
+	@Configuration
+	public static class PreAuthorizeExtendsGMSCConfig extends GlobalMethodSecurityConfiguration {
+	}
+
+	// --- proxy-target-class ---
+
+	def "proxying classes works"() {
+		when:
+			context = new AnnotationConfigApplicationContext(ProxyTargetClass)
+			MethodSecurityServiceImpl service = context.getBean(MethodSecurityServiceImpl)
+		then:
+			noExceptionThrown()
+	}
+
+	@EnableGlobalMethodSecurity(proxyTargetClass = true)
+	@Configuration
+	public static class ProxyTargetClass extends BaseMethodConfig {
+	}
+
+	def "proxying interfaces works"() {
+		when:
+			context = new AnnotationConfigApplicationContext(PreAuthorizeConfig)
+			MethodSecurityService service = context.getBean(MethodSecurityService)
+		then: "we get an instance of the interface"
+			noExceptionThrown()
+		when: "try to cast to the class"
+			MethodSecurityServiceImpl serviceImpl = service
+		then: "we get a class cast exception"
+			thrown(ClassCastException)
+	}
+
+	// --- run-as-manager-ref ---
+
+	def "custom RunAsManager"() {
+		when:
+			context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomRunAsManagerConfig)
+			MethodSecurityService service = context.getBean(MethodSecurityService)
+		then:
+			service.runAs().authorities.find { it.authority == "ROLE_RUN_AS_SUPER"}
+	}
+
+	@EnableGlobalMethodSecurity(securedEnabled = true)
+	public static class CustomRunAsManagerConfig extends GlobalMethodSecurityConfiguration {
+		@Override
+		protected RunAsManager runAsManager() {
+			RunAsManagerImpl runAsManager = new RunAsManagerImpl()
+			runAsManager.setKey("some key")
+			return runAsManager
+		}
+	}
+
+	// --- secured-annotation ---
+
+	def "secured enabled"() {
+		setup:
+			context = new AnnotationConfigApplicationContext(SecuredConfig)
+			MethodSecurityService service = context.getBean(MethodSecurityService)
+		when:
+			service.secured()
+		then:
+			thrown(AccessDeniedException)
+		and: "service with ROLE_USER allowed"
+			service.securedUser() == null
+		and:
+			service.preAuthorize() == null
+			service.jsr250() == null
+	}
+
+	@EnableGlobalMethodSecurity(securedEnabled = true)
+	@Configuration
+	public static class SecuredConfig extends BaseMethodConfig {
+	}
+
+	// --- after-invocation-provider
+
+	def "custom AfterInvocationManager"() {
+		setup:
+			context = new AnnotationConfigApplicationContext(BaseMethodConfig,CustomAfterInvocationManagerConfig)
+			MethodSecurityService service = context.getBean(MethodSecurityService)
+		when:
+			service.preAuthorizePermitAll()
+		then:
+			AccessDeniedException e = thrown()
+			e.message == "custom AfterInvocationManager"
+	}
+
+	@EnableGlobalMethodSecurity(prePostEnabled = true)
+	public static class CustomAfterInvocationManagerConfig extends GlobalMethodSecurityConfiguration {
+		@Override
+		protected AfterInvocationManager afterInvocationManager() {
+			return new AfterInvocationManagerStub()
+		}
+
+		public static class AfterInvocationManagerStub implements AfterInvocationManager {
+			Object decide(Authentication authentication, Object object, Collection<ConfigAttribute> attributes,
+				Object returnedObject) throws AccessDeniedException {
+				throw new AccessDeniedException("custom AfterInvocationManager")
+			}
+
+			boolean supports(ConfigAttribute attribute) {
+				return true
+			}
+			boolean supports(Class<?> clazz) {
+				return true
+			}
+		}
+	}
+
+	// --- misc ---
+
+	def "good error message when no Enable annotation"() {
+		when:
+			context = new AnnotationConfigApplicationContext(ExtendsNoEnableAnntotationConfig)
+			MethodSecurityInterceptor interceptor = context.getBean(MethodSecurityInterceptor)
+			interceptor.authenticationManager.authenticate(SecurityContextHolder.context.authentication)
+		then:
+			BeanCreationException e = thrown()
+			e.message.contains(EnableGlobalMethodSecurity.class.getName() + " is required")
+	}
+
+	@Configuration
+	public static class ExtendsNoEnableAnntotationConfig extends GlobalMethodSecurityConfiguration {
+		@Override
+		protected AuthenticationManager authenticationManager() {
+			return new AuthenticationManager() {
+				Authentication authenticate(Authentication authentication) {
+					throw new UnsupportedOperationException()
+				}
+			}
+		}
+	}
+
+	def "import subclass of GlobalMethodSecurityConfiguration"() {
+		when:
+			context = new AnnotationConfigApplicationContext(ImportSubclassGMSCConfig)
+			MethodSecurityService service = context.getBean(MethodSecurityService)
+		then:
+			service.secured() == null
+			service.jsr250() == null
+
+		when:
+			service.preAuthorize()
+		then:
+			thrown(AccessDeniedException)
+	}
+
+	@Configuration
+	@Import(PreAuthorizeExtendsGMSCConfig)
+	public static class ImportSubclassGMSCConfig extends BaseMethodConfig {
+	}
+
+	@Configuration
+	public static class BaseMethodConfig extends BaseAuthenticationConfig {
+		@Bean
+		public MethodSecurityService methodSecurityService() {
+			return new MethodSecurityServiceImpl()
+		}
+	}
 }

+ 71 - 71
config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/SampleEnableGlobalMethodSecurityTests.groovy

@@ -39,87 +39,87 @@ import org.springframework.security.core.context.SecurityContextHolder
  *
  */
 public class SampleEnableGlobalMethodSecurityTests extends BaseSpringSpec {
-    def setup() {
-        SecurityContextHolder.getContext().setAuthentication(
-                        new TestingAuthenticationToken("user", "password","ROLE_USER"))
-    }
+	def setup() {
+		SecurityContextHolder.getContext().setAuthentication(
+						new TestingAuthenticationToken("user", "password","ROLE_USER"))
+	}
 
-    def preAuthorize() {
-        when:
-        loadConfig(SampleWebSecurityConfig)
-        MethodSecurityService service = context.getBean(MethodSecurityService)
-        then:
-        service.secured() == null
-        service.jsr250() == null
+	def preAuthorize() {
+		when:
+		loadConfig(SampleWebSecurityConfig)
+		MethodSecurityService service = context.getBean(MethodSecurityService)
+		then:
+		service.secured() == null
+		service.jsr250() == null
 
-        when:
-        service.preAuthorize()
-        then:
-        thrown(AccessDeniedException)
-    }
+		when:
+		service.preAuthorize()
+		then:
+		thrown(AccessDeniedException)
+	}
 
-    @EnableGlobalMethodSecurity(prePostEnabled=true)
-    public static class SampleWebSecurityConfig {
-        @Bean
-        public MethodSecurityService methodSecurityService() {
-            return new MethodSecurityServiceImpl()
-        }
+	@EnableGlobalMethodSecurity(prePostEnabled=true)
+	public static class SampleWebSecurityConfig {
+		@Bean
+		public MethodSecurityService methodSecurityService() {
+			return new MethodSecurityServiceImpl()
+		}
 
-        @Autowired
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER").and()
-                    .withUser("admin").password("password").roles("USER", "ADMIN");
-        }
-    }
+		@Autowired
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER").and()
+					.withUser("admin").password("password").roles("USER", "ADMIN");
+		}
+	}
 
-    def 'custom permission handler'() {
-        when:
-        loadConfig(CustomPermissionEvaluatorWebSecurityConfig)
-        MethodSecurityService service = context.getBean(MethodSecurityService)
-        then:
-        service.hasPermission("allowed") == null
+	def 'custom permission handler'() {
+		when:
+		loadConfig(CustomPermissionEvaluatorWebSecurityConfig)
+		MethodSecurityService service = context.getBean(MethodSecurityService)
+		then:
+		service.hasPermission("allowed") == null
 
-        when:
-        service.hasPermission("denied") == null
-        then:
-        thrown(AccessDeniedException)
-    }
+		when:
+		service.hasPermission("denied") == null
+		then:
+		thrown(AccessDeniedException)
+	}
 
-    @EnableGlobalMethodSecurity(prePostEnabled=true)
-    public static class CustomPermissionEvaluatorWebSecurityConfig extends GlobalMethodSecurityConfiguration {
-        @Bean
-        public MethodSecurityService methodSecurityService() {
-            return new MethodSecurityServiceImpl()
-        }
+	@EnableGlobalMethodSecurity(prePostEnabled=true)
+	public static class CustomPermissionEvaluatorWebSecurityConfig extends GlobalMethodSecurityConfiguration {
+		@Bean
+		public MethodSecurityService methodSecurityService() {
+			return new MethodSecurityServiceImpl()
+		}
 
-        @Override
-        protected MethodSecurityExpressionHandler createExpressionHandler() {
-            DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
-            expressionHandler.setPermissionEvaluator(new CustomPermissionEvaluator());
-            return expressionHandler;
-        }
+		@Override
+		protected MethodSecurityExpressionHandler createExpressionHandler() {
+			DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
+			expressionHandler.setPermissionEvaluator(new CustomPermissionEvaluator());
+			return expressionHandler;
+		}
 
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-                .withUser("user").password("password").roles("USER").and()
-                .withUser("admin").password("password").roles("USER", "ADMIN");
-        }
-    }
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+				.withUser("user").password("password").roles("USER").and()
+				.withUser("admin").password("password").roles("USER", "ADMIN");
+		}
+	}
 
-    static class CustomPermissionEvaluator implements PermissionEvaluator {
-        public boolean hasPermission(Authentication authentication,
-                Object targetDomainObject, Object permission) {
-            return !"denied".equals(targetDomainObject);
-        }
+	static class CustomPermissionEvaluator implements PermissionEvaluator {
+		public boolean hasPermission(Authentication authentication,
+				Object targetDomainObject, Object permission) {
+			return !"denied".equals(targetDomainObject);
+		}
 
-        public boolean hasPermission(Authentication authentication,
-                Serializable targetId, String targetType, Object permission) {
-            return !"denied".equals(targetId);
-        }
+		public boolean hasPermission(Authentication authentication,
+				Serializable targetId, String targetType, Object permission) {
+			return !"denied".equals(targetId);
+		}
 
-    }
+	}
 }

+ 61 - 61
config/src/test/groovy/org/springframework/security/config/annotation/provisioning/UserDetailsManagerConfigurerTests.groovy

@@ -29,69 +29,69 @@ import spock.lang.Specification
  */
 class UserDetailsManagerConfigurerTests extends Specification {
 
-    def "all attributes supported"() {
-        setup:
-            InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager([])
-        when:
-            UserDetails userDetails = new UserDetailsManagerConfigurer<UserDetailsManagerConfigurer<InMemoryUserDetailsManager>>(userDetailsManager)
-                .withUser("user")
-                    .password("password")
-                    .roles("USER")
-                    .disabled(true)
-                    .accountExpired(true)
-                    .accountLocked(true)
-                    .credentialsExpired(true)
-                    .build()
-        then:
-            userDetails.username == 'user'
-            userDetails.password == 'password'
-            userDetails.authorities.collect { it.authority } == ["ROLE_USER"]
-            !userDetails.accountNonExpired
-            !userDetails.accountNonLocked
-            !userDetails.credentialsNonExpired
-            !userDetails.enabled
-    }
+	def "all attributes supported"() {
+		setup:
+			InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager([])
+		when:
+			UserDetails userDetails = new UserDetailsManagerConfigurer<UserDetailsManagerConfigurer<InMemoryUserDetailsManager>>(userDetailsManager)
+				.withUser("user")
+					.password("password")
+					.roles("USER")
+					.disabled(true)
+					.accountExpired(true)
+					.accountLocked(true)
+					.credentialsExpired(true)
+					.build()
+		then:
+			userDetails.username == 'user'
+			userDetails.password == 'password'
+			userDetails.authorities.collect { it.authority } == ["ROLE_USER"]
+			!userDetails.accountNonExpired
+			!userDetails.accountNonLocked
+			!userDetails.credentialsNonExpired
+			!userDetails.enabled
+	}
 
-    def "authorities(GrantedAuthorities...) works"() {
-        setup:
-            InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager([])
-            SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER")
-        when:
-            UserDetails userDetails = new UserDetailsManagerConfigurer<UserDetailsManagerConfigurer<InMemoryUserDetailsManager>>(userDetailsManager)
-                .withUser("user")
-                    .password("password")
-                    .authorities(authority)
-                    .build()
-        then:
-            userDetails.authorities == [authority] as Set
-    }
+	def "authorities(GrantedAuthorities...) works"() {
+		setup:
+			InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager([])
+			SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER")
+		when:
+			UserDetails userDetails = new UserDetailsManagerConfigurer<UserDetailsManagerConfigurer<InMemoryUserDetailsManager>>(userDetailsManager)
+				.withUser("user")
+					.password("password")
+					.authorities(authority)
+					.build()
+		then:
+			userDetails.authorities == [authority] as Set
+	}
 
-    def "authorities(String...) works"() {
-        setup:
-            InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager([])
-            String authority = "ROLE_USER"
-        when:
-            UserDetails userDetails = new UserDetailsManagerConfigurer<UserDetailsManagerConfigurer<InMemoryUserDetailsManager>>(userDetailsManager)
-                .withUser("user")
-                    .password("password")
-                    .authorities(authority)
-                    .build()
-        then:
-            userDetails.authorities.collect { it.authority } == [authority]
-    }
+	def "authorities(String...) works"() {
+		setup:
+			InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager([])
+			String authority = "ROLE_USER"
+		when:
+			UserDetails userDetails = new UserDetailsManagerConfigurer<UserDetailsManagerConfigurer<InMemoryUserDetailsManager>>(userDetailsManager)
+				.withUser("user")
+					.password("password")
+					.authorities(authority)
+					.build()
+		then:
+			userDetails.authorities.collect { it.authority } == [authority]
+	}
 
 
-    def "authorities(List) works"() {
-        setup:
-            InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager([])
-            SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER")
-        when:
-            UserDetails userDetails = new UserDetailsManagerConfigurer<UserDetailsManagerConfigurer<InMemoryUserDetailsManager>>(userDetailsManager)
-                .withUser("user")
-                    .password("password")
-                    .authorities([authority])
-                    .build()
-        then:
-            userDetails.authorities == [authority] as Set
-    }
+	def "authorities(List) works"() {
+		setup:
+			InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager([])
+			SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER")
+		when:
+			UserDetails userDetails = new UserDetailsManagerConfigurer<UserDetailsManagerConfigurer<InMemoryUserDetailsManager>>(userDetailsManager)
+				.withUser("user")
+					.password("password")
+					.authorities([authority])
+					.build()
+		then:
+			userDetails.authorities == [authority] as Set
+	}
 }

+ 139 - 139
config/src/test/groovy/org/springframework/security/config/annotation/web/AbstractConfiguredSecurityBuilderTests.groovy

@@ -30,144 +30,144 @@ import spock.lang.Specification
  */
 class AbstractConfiguredSecurityBuilderTests extends BaseSpringSpec {
 
-    ConcreteAbstractConfiguredBuilder builder
-
-    def setup() {
-        builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor)
-    }
-
-    def "Null ObjectPostProcessor rejected"() {
-        when:
-            new ConcreteAbstractConfiguredBuilder(null)
-        then:
-            thrown(IllegalArgumentException)
-        when:
-            builder.objectPostProcessor(null);
-        then:
-            thrown(IllegalArgumentException)
-    }
-
-    def "apply null is rejected"() {
-        when:
-            builder.apply(null)
-        then:
-            thrown(IllegalArgumentException)
-    }
-
-    def "Duplicate configurer is removed"() {
-        when:
-            builder.apply(new ConcreteConfigurer())
-            builder.apply(new ConcreteConfigurer())
-        then:
-            ReflectionTestUtils.getField(builder,"configurers").size() == 1
-    }
-
-    def "build twice fails"() {
-        setup:
-            builder.build()
-        when:
-            builder.build()
-        then:
-            thrown(IllegalStateException)
-    }
-
-    def "getObject before build fails"() {
-        when:
-            builder.getObject()
-        then:
-            thrown(IllegalStateException)
-    }
-
-    def "Configurer.init can apply another configurer"() {
-        setup:
-            DelegateConfigurer.CONF = Mock(SecurityConfigurerAdapter)
-        when:
-            builder.apply(new DelegateConfigurer())
-            builder.build()
-        then:
-            1 * DelegateConfigurer.CONF.init(builder)
-            1 * DelegateConfigurer.CONF.configure(builder)
-    }
-
-    def "getConfigurer with multi fails"() {
-        setup:
-            ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor, true)
-            builder.apply(new DelegateConfigurer())
-            builder.apply(new DelegateConfigurer())
-        when:
-            builder.getConfigurer(DelegateConfigurer)
-        then: "Fail due to trying to obtain a single DelegateConfigurer and multiple are provided"
-            thrown(IllegalStateException)
-    }
-
-    def "removeConfigurer with multi fails"() {
-        setup:
-            ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor, true)
-            builder.apply(new DelegateConfigurer())
-            builder.apply(new DelegateConfigurer())
-        when:
-            builder.removeConfigurer(DelegateConfigurer)
-        then: "Fail due to trying to remove and obtain a single DelegateConfigurer and multiple are provided"
-            thrown(IllegalStateException)
-    }
-
-    def "removeConfigurers with multi"() {
-        setup:
-            DelegateConfigurer c1 = new DelegateConfigurer()
-            DelegateConfigurer c2 = new DelegateConfigurer()
-            ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor, true)
-            builder.apply(c1)
-            builder.apply(c2)
-        when:
-            def result = builder.removeConfigurers(DelegateConfigurer)
-        then:
-            result.size() == 2
-            result.contains(c1)
-            result.contains(c2)
-            builder.getConfigurers(DelegateConfigurer).empty
-    }
-
-    def "getConfigurers with multi"() {
-        setup:
-            DelegateConfigurer c1 = new DelegateConfigurer()
-            DelegateConfigurer c2 = new DelegateConfigurer()
-            ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor, true)
-            builder.apply(c1)
-            builder.apply(c2)
-        when:
-            def result = builder.getConfigurers(DelegateConfigurer)
-        then:
-            result.size() == 2
-            result.contains(c1)
-            result.contains(c2)
-            builder.getConfigurers(DelegateConfigurer).size() == 2
-    }
-
-    private static class DelegateConfigurer extends SecurityConfigurerAdapter<Object, ConcreteAbstractConfiguredBuilder> {
-        private static SecurityConfigurer<Object, ConcreteAbstractConfiguredBuilder> CONF;
-
-        @Override
-        public void init(ConcreteAbstractConfiguredBuilder builder)
-                throws Exception {
-            builder.apply(CONF);
-        }
-    }
-
-    private static class ConcreteConfigurer extends SecurityConfigurerAdapter<Object, ConcreteAbstractConfiguredBuilder> { }
-
-    private class ConcreteAbstractConfiguredBuilder extends AbstractConfiguredSecurityBuilder<Object, ConcreteAbstractConfiguredBuilder> {
-
-        public ConcreteAbstractConfiguredBuilder(ObjectPostProcessor<Object> objectPostProcessor) {
-            super(objectPostProcessor);
-        }
-
-        public ConcreteAbstractConfiguredBuilder(ObjectPostProcessor<Object> objectPostProcessor, boolean allowMulti) {
-            super(objectPostProcessor,allowMulti);
-        }
-
-        public Object performBuild() throws Exception {
-            return "success";
-        }
-    }
+	ConcreteAbstractConfiguredBuilder builder
+
+	def setup() {
+		builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor)
+	}
+
+	def "Null ObjectPostProcessor rejected"() {
+		when:
+			new ConcreteAbstractConfiguredBuilder(null)
+		then:
+			thrown(IllegalArgumentException)
+		when:
+			builder.objectPostProcessor(null);
+		then:
+			thrown(IllegalArgumentException)
+	}
+
+	def "apply null is rejected"() {
+		when:
+			builder.apply(null)
+		then:
+			thrown(IllegalArgumentException)
+	}
+
+	def "Duplicate configurer is removed"() {
+		when:
+			builder.apply(new ConcreteConfigurer())
+			builder.apply(new ConcreteConfigurer())
+		then:
+			ReflectionTestUtils.getField(builder,"configurers").size() == 1
+	}
+
+	def "build twice fails"() {
+		setup:
+			builder.build()
+		when:
+			builder.build()
+		then:
+			thrown(IllegalStateException)
+	}
+
+	def "getObject before build fails"() {
+		when:
+			builder.getObject()
+		then:
+			thrown(IllegalStateException)
+	}
+
+	def "Configurer.init can apply another configurer"() {
+		setup:
+			DelegateConfigurer.CONF = Mock(SecurityConfigurerAdapter)
+		when:
+			builder.apply(new DelegateConfigurer())
+			builder.build()
+		then:
+			1 * DelegateConfigurer.CONF.init(builder)
+			1 * DelegateConfigurer.CONF.configure(builder)
+	}
+
+	def "getConfigurer with multi fails"() {
+		setup:
+			ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor, true)
+			builder.apply(new DelegateConfigurer())
+			builder.apply(new DelegateConfigurer())
+		when:
+			builder.getConfigurer(DelegateConfigurer)
+		then: "Fail due to trying to obtain a single DelegateConfigurer and multiple are provided"
+			thrown(IllegalStateException)
+	}
+
+	def "removeConfigurer with multi fails"() {
+		setup:
+			ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor, true)
+			builder.apply(new DelegateConfigurer())
+			builder.apply(new DelegateConfigurer())
+		when:
+			builder.removeConfigurer(DelegateConfigurer)
+		then: "Fail due to trying to remove and obtain a single DelegateConfigurer and multiple are provided"
+			thrown(IllegalStateException)
+	}
+
+	def "removeConfigurers with multi"() {
+		setup:
+			DelegateConfigurer c1 = new DelegateConfigurer()
+			DelegateConfigurer c2 = new DelegateConfigurer()
+			ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor, true)
+			builder.apply(c1)
+			builder.apply(c2)
+		when:
+			def result = builder.removeConfigurers(DelegateConfigurer)
+		then:
+			result.size() == 2
+			result.contains(c1)
+			result.contains(c2)
+			builder.getConfigurers(DelegateConfigurer).empty
+	}
+
+	def "getConfigurers with multi"() {
+		setup:
+			DelegateConfigurer c1 = new DelegateConfigurer()
+			DelegateConfigurer c2 = new DelegateConfigurer()
+			ConcreteAbstractConfiguredBuilder builder = new ConcreteAbstractConfiguredBuilder(objectPostProcessor, true)
+			builder.apply(c1)
+			builder.apply(c2)
+		when:
+			def result = builder.getConfigurers(DelegateConfigurer)
+		then:
+			result.size() == 2
+			result.contains(c1)
+			result.contains(c2)
+			builder.getConfigurers(DelegateConfigurer).size() == 2
+	}
+
+	private static class DelegateConfigurer extends SecurityConfigurerAdapter<Object, ConcreteAbstractConfiguredBuilder> {
+		private static SecurityConfigurer<Object, ConcreteAbstractConfiguredBuilder> CONF;
+
+		@Override
+		public void init(ConcreteAbstractConfiguredBuilder builder)
+				throws Exception {
+			builder.apply(CONF);
+		}
+	}
+
+	private static class ConcreteConfigurer extends SecurityConfigurerAdapter<Object, ConcreteAbstractConfiguredBuilder> { }
+
+	private class ConcreteAbstractConfiguredBuilder extends AbstractConfiguredSecurityBuilder<Object, ConcreteAbstractConfiguredBuilder> {
+
+		public ConcreteAbstractConfiguredBuilder(ObjectPostProcessor<Object> objectPostProcessor) {
+			super(objectPostProcessor);
+		}
+
+		public ConcreteAbstractConfiguredBuilder(ObjectPostProcessor<Object> objectPostProcessor, boolean allowMulti) {
+			super(objectPostProcessor,allowMulti);
+		}
+
+		public Object performBuild() throws Exception {
+			return "success";
+		}
+	}
 
 }

+ 267 - 267
config/src/test/groovy/org/springframework/security/config/annotation/web/SampleWebSecurityConfigurerAdapterTests.groovy

@@ -34,286 +34,286 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
  *
  */
 public class SampleWebSecurityConfigurerAdapterTests extends BaseSpringSpec {
-    def "README HelloWorld Sample works"() {
-        setup: "Sample Config is loaded"
-            loadConfig(HelloWorldWebSecurityConfigurerAdapter)
-        when:
-            request.addHeader("Accept", "text/html")
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.getRedirectedUrl() == "http://localhost/login"
-        when: "fail to log in"
-            super.setup()
-            request.addHeader("Accept", "text/html")
-            request.servletPath = "/login"
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to login error page"
-            response.getRedirectedUrl() == "/login?error"
-        when: "login success"
-            super.setup()
-            request.servletPath = "/login"
-            request.method = "POST"
-            request.parameters.username = ["user"] as String[]
-            request.parameters.password = ["password"] as String[]
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to default succes page"
-            response.getRedirectedUrl() == "/"
-    }
+	def "README HelloWorld Sample works"() {
+		setup: "Sample Config is loaded"
+			loadConfig(HelloWorldWebSecurityConfigurerAdapter)
+		when:
+			request.addHeader("Accept", "text/html")
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.getRedirectedUrl() == "http://localhost/login"
+		when: "fail to log in"
+			super.setup()
+			request.addHeader("Accept", "text/html")
+			request.servletPath = "/login"
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to login error page"
+			response.getRedirectedUrl() == "/login?error"
+		when: "login success"
+			super.setup()
+			request.servletPath = "/login"
+			request.method = "POST"
+			request.parameters.username = ["user"] as String[]
+			request.parameters.password = ["password"] as String[]
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to default succes page"
+			response.getRedirectedUrl() == "/"
+	}
 
-    /**
-     * <code>
-     *   <http>
-     *     <intercept-url pattern="/resources/**" access="permitAll"/>
-     *     <intercept-url pattern="/**" access="authenticated"/>
-     *     <logout
-     *         logout-success-url="/login?logout"
-     *         logout-url="/logout"
-     *     <form-login
-     *         authentication-failure-url="/login?error"
-     *         login-page="/login" <!-- Except Spring Security renders the login page -->
-     *         login-processing-url="/login" <!-- but only POST -->
-     *         password-parameter="password"
-     *         username-parameter="username"
-     *     />
-     *   </http>
-     *   <authentication-manager>
-     *     <authentication-provider>
-     *       <user-service>
-     *         <user username="user" password="password" authorities="ROLE_USER"/>
-     *       </user-service>
-     *     </authentication-provider>
-     *   </authentication-manager>
-     * </code>
-     * @author Rob Winch
-     */
-    @EnableWebSecurity
-    public static class HelloWorldWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER");
-        }
-    }
+	/**
+	 * <code>
+	 *   <http>
+	 *     <intercept-url pattern="/resources/**" access="permitAll"/>
+	 *     <intercept-url pattern="/**" access="authenticated"/>
+	 *     <logout
+	 *         logout-success-url="/login?logout"
+	 *         logout-url="/logout"
+	 *     <form-login
+	 *         authentication-failure-url="/login?error"
+	 *         login-page="/login" <!-- Except Spring Security renders the login page -->
+	 *         login-processing-url="/login" <!-- but only POST -->
+	 *         password-parameter="password"
+	 *         username-parameter="username"
+	 *     />
+	 *   </http>
+	 *   <authentication-manager>
+	 *     <authentication-provider>
+	 *       <user-service>
+	 *         <user username="user" password="password" authorities="ROLE_USER"/>
+	 *       </user-service>
+	 *     </authentication-provider>
+	 *   </authentication-manager>
+	 * </code>
+	 * @author Rob Winch
+	 */
+	@EnableWebSecurity
+	public static class HelloWorldWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER");
+		}
+	}
 
-    def "README Sample works"() {
-        setup: "Sample Config is loaded"
-            loadConfig(SampleWebSecurityConfigurerAdapter)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.getRedirectedUrl() == "http://localhost/login"
-        when: "fail to log in"
-            super.setup()
-            request.servletPath = "/login"
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to login error page"
-            response.getRedirectedUrl() == "/login?error"
-        when: "login success"
-            super.setup()
-            request.servletPath = "/login"
-            request.method = "POST"
-            request.parameters.username = ["user"] as String[]
-            request.parameters.password = ["password"] as String[]
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to default succes page"
-            response.getRedirectedUrl() == "/"
-    }
+	def "README Sample works"() {
+		setup: "Sample Config is loaded"
+			loadConfig(SampleWebSecurityConfigurerAdapter)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.getRedirectedUrl() == "http://localhost/login"
+		when: "fail to log in"
+			super.setup()
+			request.servletPath = "/login"
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to login error page"
+			response.getRedirectedUrl() == "/login?error"
+		when: "login success"
+			super.setup()
+			request.servletPath = "/login"
+			request.method = "POST"
+			request.parameters.username = ["user"] as String[]
+			request.parameters.password = ["password"] as String[]
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to default succes page"
+			response.getRedirectedUrl() == "/"
+	}
 
-    /**
-     * <code>
-     *   <http security="none" pattern="/resources/**"/>
-     *   <http>
-     *     <intercept-url pattern="/logout" access="permitAll"/>
-     *     <intercept-url pattern="/login" access="permitAll"/>
-     *     <intercept-url pattern="/signup" access="permitAll"/>
-     *     <intercept-url pattern="/about" access="permitAll"/>
-     *     <intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
-     *     <logout
-     *         logout-success-url="/login?logout"
-     *         logout-url="/logout"
-     *     <form-login
-     *         authentication-failure-url="/login?error"
-     *         login-page="/login"
-     *         login-processing-url="/login" <!-- but only POST -->
-     *         password-parameter="password"
-     *         username-parameter="username"
-     *     />
-     *   </http>
-     *   <authentication-manager>
-     *     <authentication-provider>
-     *       <user-service>
-     *         <user username="user" password="password" authorities="ROLE_USER"/>
-     *         <user username="admin" password="password" authorities="ROLE_USER,ROLE_ADMIN"/>
-     *       </user-service>
-     *     </authentication-provider>
-     *   </authentication-manager>
-     * </code>
-     * @author Rob Winch
-     */
-    @EnableWebSecurity
-    public static class SampleWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
+	/**
+	 * <code>
+	 *   <http security="none" pattern="/resources/**"/>
+	 *   <http>
+	 *     <intercept-url pattern="/logout" access="permitAll"/>
+	 *     <intercept-url pattern="/login" access="permitAll"/>
+	 *     <intercept-url pattern="/signup" access="permitAll"/>
+	 *     <intercept-url pattern="/about" access="permitAll"/>
+	 *     <intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
+	 *     <logout
+	 *         logout-success-url="/login?logout"
+	 *         logout-url="/logout"
+	 *     <form-login
+	 *         authentication-failure-url="/login?error"
+	 *         login-page="/login"
+	 *         login-processing-url="/login" <!-- but only POST -->
+	 *         password-parameter="password"
+	 *         username-parameter="username"
+	 *     />
+	 *   </http>
+	 *   <authentication-manager>
+	 *     <authentication-provider>
+	 *       <user-service>
+	 *         <user username="user" password="password" authorities="ROLE_USER"/>
+	 *         <user username="admin" password="password" authorities="ROLE_USER,ROLE_ADMIN"/>
+	 *       </user-service>
+	 *     </authentication-provider>
+	 *   </authentication-manager>
+	 * </code>
+	 * @author Rob Winch
+	 */
+	@EnableWebSecurity
+	public static class SampleWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
 
-        @Override
-        public void configure(WebSecurity web) throws Exception {
-            web
-                .ignoring()
-                    .antMatchers("/resources/**");
-        }
+		@Override
+		public void configure(WebSecurity web) throws Exception {
+			web
+				.ignoring()
+					.antMatchers("/resources/**");
+		}
 
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .antMatchers("/signup","/about").permitAll()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .formLogin()
-                    .loginPage("/login")
-                    // set permitAll for all URLs associated with Form Login
-                    .permitAll();
-        }
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.antMatchers("/signup","/about").permitAll()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin()
+					.loginPage("/login")
+					// set permitAll for all URLs associated with Form Login
+					.permitAll();
+		}
 
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER").and()
-                    .withUser("admin").password("password").roles("USER", "ADMIN");
-        }
-    }
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER").and()
+					.withUser("admin").password("password").roles("USER", "ADMIN");
+		}
+	}
 
-    def "README Multi http Sample works"() {
-        setup:
-            loadConfig(SampleMultiHttpSecurityConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.getRedirectedUrl() == "http://localhost/login"
-        when: "fail to log in"
-            super.setup()
-            request.servletPath = "/login"
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to login error page"
-            response.getRedirectedUrl() == "/login?error"
-        when: "login success"
-            super.setup()
-            request.servletPath = "/login"
-            request.method = "POST"
-            request.parameters.username = ["user"] as String[]
-            request.parameters.password = ["password"] as String[]
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to default succes page"
-            response.getRedirectedUrl() == "/"
+	def "README Multi http Sample works"() {
+		setup:
+			loadConfig(SampleMultiHttpSecurityConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.getRedirectedUrl() == "http://localhost/login"
+		when: "fail to log in"
+			super.setup()
+			request.servletPath = "/login"
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to login error page"
+			response.getRedirectedUrl() == "/login?error"
+		when: "login success"
+			super.setup()
+			request.servletPath = "/login"
+			request.method = "POST"
+			request.parameters.username = ["user"] as String[]
+			request.parameters.password = ["password"] as String[]
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to default succes page"
+			response.getRedirectedUrl() == "/"
 
-        when: "request protected API URL"
-            super.setup()
-            request.servletPath = "/api/admin/test"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "get 401"
-            response.getStatus() == HttpServletResponse.SC_UNAUTHORIZED
+		when: "request protected API URL"
+			super.setup()
+			request.servletPath = "/api/admin/test"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "get 401"
+			response.getStatus() == HttpServletResponse.SC_UNAUTHORIZED
 
-        when: "request API for admins with user"
-            super.setup()
-            request.servletPath = "/api/admin/test"
-            request.addHeader("Authorization", "Basic " + "user:password".bytes.encodeBase64().toString())
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "get 403"
-            response.getStatus() == HttpServletResponse.SC_FORBIDDEN
+		when: "request API for admins with user"
+			super.setup()
+			request.servletPath = "/api/admin/test"
+			request.addHeader("Authorization", "Basic " + "user:password".bytes.encodeBase64().toString())
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "get 403"
+			response.getStatus() == HttpServletResponse.SC_FORBIDDEN
 
-        when: "request API for admins with admin"
-            super.setup()
-            request.servletPath = "/api/admin/test"
-            request.addHeader("Authorization", "Basic " + "admin:password".bytes.encodeBase64().toString())
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "get 200"
-            response.getStatus() == HttpServletResponse.SC_OK
-    }
+		when: "request API for admins with admin"
+			super.setup()
+			request.servletPath = "/api/admin/test"
+			request.addHeader("Authorization", "Basic " + "admin:password".bytes.encodeBase64().toString())
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "get 200"
+			response.getStatus() == HttpServletResponse.SC_OK
+	}
 
 
-    /**
-     * <code>
-     *   <http security="none" pattern="/resources/**"/>
-     *   <http pattern="/api/**">
-     *     <intercept-url pattern="/api/admin/**" access="hasRole('ROLE_ADMIN')"/>
-     *     <intercept-url pattern="/api/**" access="hasRole('ROLE_USER')"/>
-     *     <http-basic />
-     *   </http>
-     *   <http>
-     *     <intercept-url pattern="/logout" access="permitAll"/>
-     *     <intercept-url pattern="/login" access="permitAll"/>
-     *     <intercept-url pattern="/signup" access="permitAll"/>
-     *     <intercept-url pattern="/about" access="permitAll"/>
-     *     <intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
-     *     <logout
-     *         logout-success-url="/login?logout"
-     *         logout-url="/logout"
-     *     <form-login
-     *         authentication-failure-url="/login?error"
-     *         login-page="/login"
-     *         login-processing-url="/login" <!-- but only POST -->
-     *         password-parameter="password"
-     *         username-parameter="username"
-     *     />
-     *   </http>
-     *   <authentication-manager>
-     *     <authentication-provider>
-     *       <user-service>
-     *         <user username="user" password="password" authorities="ROLE_USER"/>
-     *         <user username="admin" password="password" authorities="ROLE_USER,ROLE_ADMIN"/>
-     *       </user-service>
-     *     </authentication-provider>
-     *   </authentication-manager>
-     * </code>
-     * @author Rob Winch
-     */
-    @EnableWebSecurity
-    public static class SampleMultiHttpSecurityConfig {
-        @Autowired
-        protected void configure(AuthenticationManagerBuilder auth) {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER").and()
-                    .withUser("admin").password("password").roles("USER", "ADMIN");
-        }
+	/**
+	 * <code>
+	 *   <http security="none" pattern="/resources/**"/>
+	 *   <http pattern="/api/**">
+	 *     <intercept-url pattern="/api/admin/**" access="hasRole('ROLE_ADMIN')"/>
+	 *     <intercept-url pattern="/api/**" access="hasRole('ROLE_USER')"/>
+	 *     <http-basic />
+	 *   </http>
+	 *   <http>
+	 *     <intercept-url pattern="/logout" access="permitAll"/>
+	 *     <intercept-url pattern="/login" access="permitAll"/>
+	 *     <intercept-url pattern="/signup" access="permitAll"/>
+	 *     <intercept-url pattern="/about" access="permitAll"/>
+	 *     <intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
+	 *     <logout
+	 *         logout-success-url="/login?logout"
+	 *         logout-url="/logout"
+	 *     <form-login
+	 *         authentication-failure-url="/login?error"
+	 *         login-page="/login"
+	 *         login-processing-url="/login" <!-- but only POST -->
+	 *         password-parameter="password"
+	 *         username-parameter="username"
+	 *     />
+	 *   </http>
+	 *   <authentication-manager>
+	 *     <authentication-provider>
+	 *       <user-service>
+	 *         <user username="user" password="password" authorities="ROLE_USER"/>
+	 *         <user username="admin" password="password" authorities="ROLE_USER,ROLE_ADMIN"/>
+	 *       </user-service>
+	 *     </authentication-provider>
+	 *   </authentication-manager>
+	 * </code>
+	 * @author Rob Winch
+	 */
+	@EnableWebSecurity
+	public static class SampleMultiHttpSecurityConfig {
+		@Autowired
+		protected void configure(AuthenticationManagerBuilder auth) {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER").and()
+					.withUser("admin").password("password").roles("USER", "ADMIN");
+		}
 
-        @Configuration
-        @Order(1)
-        public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
-            protected void configure(HttpSecurity http) throws Exception {
-                http
-                    .antMatcher("/api/**")
-                    .authorizeRequests()
-                        .antMatchers("/api/admin/**").hasRole("ADMIN")
-                        .antMatchers("/api/**").hasRole("USER")
-                        .and()
-                    .httpBasic();
-            }
-        }
+		@Configuration
+		@Order(1)
+		public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
+			protected void configure(HttpSecurity http) throws Exception {
+				http
+					.antMatcher("/api/**")
+					.authorizeRequests()
+						.antMatchers("/api/admin/**").hasRole("ADMIN")
+						.antMatchers("/api/**").hasRole("USER")
+						.and()
+					.httpBasic();
+			}
+		}
 
-        @Configuration
-        public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
-            @Override
-            public void configure(WebSecurity web) throws Exception {
-                web
-                    .ignoring()
-                        .antMatchers("/resources/**");
-            }
+		@Configuration
+		public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
+			@Override
+			public void configure(WebSecurity web) throws Exception {
+				web
+					.ignoring()
+						.antMatchers("/resources/**");
+			}
 
-            @Override
-            protected void configure(HttpSecurity http) throws Exception {
-                http
-                    .authorizeRequests()
-                        .antMatchers("/signup","/about").permitAll()
-                        .anyRequest().hasRole("USER")
-                        .and()
-                    .formLogin()
-                        .loginPage("/login")
-                        .permitAll();
-            }
-        }
-    }
+			@Override
+			protected void configure(HttpSecurity http) throws Exception {
+				http
+					.authorizeRequests()
+						.antMatchers("/signup","/about").permitAll()
+						.anyRequest().hasRole("USER")
+						.and()
+					.formLogin()
+						.loginPage("/login")
+						.permitAll();
+			}
+		}
+	}
 }

+ 236 - 236
config/src/test/groovy/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterTests.groovy

@@ -56,240 +56,240 @@ import org.springframework.web.filter.OncePerRequestFilter
  */
 class WebSecurityConfigurerAdapterTests extends BaseSpringSpec {
 
-    def "MessageSources populated on AuthenticationProviders"() {
-        when:
-            loadConfig(MessageSourcesPopulatedConfig)
-            List<AuthenticationProvider> providers = authenticationProviders()
-        then:
-            providers*.messages*.messageSource == [context,context,context,context]
-    }
-
-    def "messages set when using WebSecurityConfigurerAdapter"() {
-        when:
-            loadConfig(InMemoryAuthWithWebSecurityConfigurerAdapter)
-        then:
-            authenticationManager.messages.messageSource instanceof ApplicationContext
-    }
-
-    def "headers are populated by default"() {
-        setup: "load config that overrides http and accepts defaults"
-            loadConfig(HeadersArePopulatedByDefaultConfig)
-            request.secure = true
-        when: "invoke the springSecurityFilterChain"
-            springSecurityFilterChain.doFilter(request, response, chain)
-        then: "the default headers are added"
-            responseHeaders == ['X-Content-Type-Options':'nosniff',
-                         'X-Frame-Options':'DENY',
-                         'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
-                         'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
-                         'Pragma':'no-cache',
-                         'Expires' : '0',
-                         'X-XSS-Protection' : '1; mode=block']
-    }
-
-    @EnableWebSecurity
-    static class HeadersArePopulatedByDefaultConfig extends WebSecurityConfigurerAdapter {
-
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER")
-        }
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-
-        }
-    }
-
-    def "webasync populated by default"() {
-        when: "load config that overrides http and accepts defaults"
-            loadConfig(WebAsyncPopulatedByDefaultConfig)
-        then: "WebAsyncManagerIntegrationFilter is populated"
-            findFilter(WebAsyncManagerIntegrationFilter)
-    }
-
-    @EnableWebSecurity
-    static class WebAsyncPopulatedByDefaultConfig extends WebSecurityConfigurerAdapter {
-
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER")
-        }
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-
-        }
-    }
-
-    def "AuthenticationEventPublisher is registered for Web configure(AuthenticationManagerBuilder auth)"() {
-        when:
-            loadConfig(InMemoryAuthWithWebSecurityConfigurerAdapter)
-        then:
-            authenticationManager.parent.eventPublisher instanceof DefaultAuthenticationEventPublisher
-        when:
-            Authentication token = new UsernamePasswordAuthenticationToken("user","password")
-            authenticationManager.authenticate(token)
-        then: "We only receive the AuthenticationSuccessEvent once"
-            InMemoryAuthWithWebSecurityConfigurerAdapter.EVENTS.size() == 1
-            InMemoryAuthWithWebSecurityConfigurerAdapter.EVENTS[0].authentication.name == token.principal
-    }
-
-    @EnableWebSecurity
-    static class InMemoryAuthWithWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter implements ApplicationListener<AuthenticationSuccessEvent> {
-        static List<AuthenticationSuccessEvent> EVENTS = []
-        @Bean
-        @Override
-        public AuthenticationManager authenticationManagerBean()
-                throws Exception {
-            return super.authenticationManagerBean();
-        }
-
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER")
-        }
-
-        @Override
-        public void onApplicationEvent(AuthenticationSuccessEvent e) {
-            EVENTS.add(e)
-        }
-    }
-
-    def "Override ContentNegotiationStrategy with @Bean"() {
-        setup:
-            OverrideContentNegotiationStrategySharedObjectConfig.CNS = Mock(ContentNegotiationStrategy)
-        when:
-            loadConfig(OverrideContentNegotiationStrategySharedObjectConfig)
-        then:
-            context.getBean(OverrideContentNegotiationStrategySharedObjectConfig).http.getSharedObject(ContentNegotiationStrategy) == OverrideContentNegotiationStrategySharedObjectConfig.CNS
-    }
-
-    @EnableWebSecurity
-    static class OverrideContentNegotiationStrategySharedObjectConfig extends WebSecurityConfigurerAdapter {
-        static ContentNegotiationStrategy CNS
-
-        @Bean
-        public ContentNegotiationStrategy cns() {
-            return CNS
-        }
-    }
-
-    def "ContentNegotiationStrategy shareObject defaults to Header with no @Bean"() {
-        when:
-            loadConfig(ContentNegotiationStrategyDefaultSharedObjectConfig)
-        then:
-            context.getBean(ContentNegotiationStrategyDefaultSharedObjectConfig).http.getSharedObject(ContentNegotiationStrategy).class == HeaderContentNegotiationStrategy
-    }
-
-    @EnableWebSecurity
-    static class ContentNegotiationStrategyDefaultSharedObjectConfig extends WebSecurityConfigurerAdapter {}
-
-    def "UserDetailsService lazy"() {
-        setup:
-            loadConfig(RequiresUserDetailsServiceConfig,UserDetailsServiceConfig)
-        when:
-            findFilter(MyFilter).userDetailsService.loadUserByUsername("user")
-        then:
-            noExceptionThrown()
-        when:
-            findFilter(MyFilter).userDetailsService.loadUserByUsername("admin")
-        then:
-            thrown(UsernameNotFoundException)
-    }
-
-    @Configuration
-    static class RequiresUserDetailsServiceConfig {
-        @Bean
-        public MyFilter myFilter(UserDetailsService uds) {
-            return new MyFilter(uds)
-        }
-    }
-
-    @EnableWebSecurity
-    static class UserDetailsServiceConfig extends WebSecurityConfigurerAdapter {
-        @Autowired
-        private MyFilter myFilter;
-
-        @Bean
-        @Override
-        public UserDetailsService userDetailsServiceBean() {
-            return super.userDetailsServiceBean()
-        }
-
-        @Override
-        public void configure(HttpSecurity http) {
-            http
-                .addFilterBefore(myFilter,UsernamePasswordAuthenticationFilter)
-        }
-
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER")
-        }
-    }
-
-    def "SEC-2274: WebSecurityConfigurer adds ApplicationContext as a shared object"() {
-        when:
-            loadConfig(ApplicationContextSharedObjectConfig)
-        then:
-            context.getBean(ApplicationContextSharedObjectConfig).http.getSharedObject(ApplicationContext) == context
-    }
-
-    @EnableWebSecurity
-    static class ApplicationContextSharedObjectConfig extends WebSecurityConfigurerAdapter {
-
-    }
-
-    static class MyFilter extends OncePerRequestFilter {
-        private UserDetailsService userDetailsService
-        public MyFilter(UserDetailsService uds) {
-            assert uds != null
-            this.userDetailsService = uds
-        }
-        public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {
-            chain.doFilter(request,response)
-        }
-    }
-
-    def "AuthenticationTrustResolver populated as defaultObject"() {
-        setup:
-            CustomTrustResolverConfig.TR = Mock(AuthenticationTrustResolver)
-        when:
-            loadConfig(CustomTrustResolverConfig)
-        then:
-            context.getBean(CustomTrustResolverConfig).http.getSharedObject(AuthenticationTrustResolver) == CustomTrustResolverConfig.TR
-    }
-
-    @EnableWebSecurity
-    static class CustomTrustResolverConfig extends WebSecurityConfigurerAdapter {
-        static AuthenticationTrustResolver TR
-
-        @Bean
-        public AuthenticationTrustResolver tr() {
-            return TR
-        }
-    }
-
-    def "WebSecurityConfigurerAdapter has Ordered between 0 and lowest priority"() {
-        when:
-            def lowestConfig = new LowestPriorityWebSecurityConfig()
-            def defaultConfig = new DefaultOrderWebSecurityConfig()
-            def compare = new AnnotationAwareOrderComparator()
-        then: "the default ordering is between 0 and lowest priority (Boot adapters)"
-            compare.compare(lowestConfig, defaultConfig) > 0
-    }
-
-    class DefaultOrderWebSecurityConfig extends WebSecurityConfigurerAdapter {}
-
-    @Order(Ordered.LOWEST_PRECEDENCE)
-    class LowestPriorityWebSecurityConfig extends WebSecurityConfigurerAdapter {}
+	def "MessageSources populated on AuthenticationProviders"() {
+		when:
+			loadConfig(MessageSourcesPopulatedConfig)
+			List<AuthenticationProvider> providers = authenticationProviders()
+		then:
+			providers*.messages*.messageSource == [context,context,context,context]
+	}
+
+	def "messages set when using WebSecurityConfigurerAdapter"() {
+		when:
+			loadConfig(InMemoryAuthWithWebSecurityConfigurerAdapter)
+		then:
+			authenticationManager.messages.messageSource instanceof ApplicationContext
+	}
+
+	def "headers are populated by default"() {
+		setup: "load config that overrides http and accepts defaults"
+			loadConfig(HeadersArePopulatedByDefaultConfig)
+			request.secure = true
+		when: "invoke the springSecurityFilterChain"
+			springSecurityFilterChain.doFilter(request, response, chain)
+		then: "the default headers are added"
+			responseHeaders == ['X-Content-Type-Options':'nosniff',
+						 'X-Frame-Options':'DENY',
+						 'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
+						 'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
+						 'Pragma':'no-cache',
+						 'Expires' : '0',
+						 'X-XSS-Protection' : '1; mode=block']
+	}
+
+	@EnableWebSecurity
+	static class HeadersArePopulatedByDefaultConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER")
+		}
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+
+		}
+	}
+
+	def "webasync populated by default"() {
+		when: "load config that overrides http and accepts defaults"
+			loadConfig(WebAsyncPopulatedByDefaultConfig)
+		then: "WebAsyncManagerIntegrationFilter is populated"
+			findFilter(WebAsyncManagerIntegrationFilter)
+	}
+
+	@EnableWebSecurity
+	static class WebAsyncPopulatedByDefaultConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER")
+		}
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+
+		}
+	}
+
+	def "AuthenticationEventPublisher is registered for Web configure(AuthenticationManagerBuilder auth)"() {
+		when:
+			loadConfig(InMemoryAuthWithWebSecurityConfigurerAdapter)
+		then:
+			authenticationManager.parent.eventPublisher instanceof DefaultAuthenticationEventPublisher
+		when:
+			Authentication token = new UsernamePasswordAuthenticationToken("user","password")
+			authenticationManager.authenticate(token)
+		then: "We only receive the AuthenticationSuccessEvent once"
+			InMemoryAuthWithWebSecurityConfigurerAdapter.EVENTS.size() == 1
+			InMemoryAuthWithWebSecurityConfigurerAdapter.EVENTS[0].authentication.name == token.principal
+	}
+
+	@EnableWebSecurity
+	static class InMemoryAuthWithWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter implements ApplicationListener<AuthenticationSuccessEvent> {
+		static List<AuthenticationSuccessEvent> EVENTS = []
+		@Bean
+		@Override
+		public AuthenticationManager authenticationManagerBean()
+				throws Exception {
+			return super.authenticationManagerBean();
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER")
+		}
+
+		@Override
+		public void onApplicationEvent(AuthenticationSuccessEvent e) {
+			EVENTS.add(e)
+		}
+	}
+
+	def "Override ContentNegotiationStrategy with @Bean"() {
+		setup:
+			OverrideContentNegotiationStrategySharedObjectConfig.CNS = Mock(ContentNegotiationStrategy)
+		when:
+			loadConfig(OverrideContentNegotiationStrategySharedObjectConfig)
+		then:
+			context.getBean(OverrideContentNegotiationStrategySharedObjectConfig).http.getSharedObject(ContentNegotiationStrategy) == OverrideContentNegotiationStrategySharedObjectConfig.CNS
+	}
+
+	@EnableWebSecurity
+	static class OverrideContentNegotiationStrategySharedObjectConfig extends WebSecurityConfigurerAdapter {
+		static ContentNegotiationStrategy CNS
+
+		@Bean
+		public ContentNegotiationStrategy cns() {
+			return CNS
+		}
+	}
+
+	def "ContentNegotiationStrategy shareObject defaults to Header with no @Bean"() {
+		when:
+			loadConfig(ContentNegotiationStrategyDefaultSharedObjectConfig)
+		then:
+			context.getBean(ContentNegotiationStrategyDefaultSharedObjectConfig).http.getSharedObject(ContentNegotiationStrategy).class == HeaderContentNegotiationStrategy
+	}
+
+	@EnableWebSecurity
+	static class ContentNegotiationStrategyDefaultSharedObjectConfig extends WebSecurityConfigurerAdapter {}
+
+	def "UserDetailsService lazy"() {
+		setup:
+			loadConfig(RequiresUserDetailsServiceConfig,UserDetailsServiceConfig)
+		when:
+			findFilter(MyFilter).userDetailsService.loadUserByUsername("user")
+		then:
+			noExceptionThrown()
+		when:
+			findFilter(MyFilter).userDetailsService.loadUserByUsername("admin")
+		then:
+			thrown(UsernameNotFoundException)
+	}
+
+	@Configuration
+	static class RequiresUserDetailsServiceConfig {
+		@Bean
+		public MyFilter myFilter(UserDetailsService uds) {
+			return new MyFilter(uds)
+		}
+	}
+
+	@EnableWebSecurity
+	static class UserDetailsServiceConfig extends WebSecurityConfigurerAdapter {
+		@Autowired
+		private MyFilter myFilter;
+
+		@Bean
+		@Override
+		public UserDetailsService userDetailsServiceBean() {
+			return super.userDetailsServiceBean()
+		}
+
+		@Override
+		public void configure(HttpSecurity http) {
+			http
+				.addFilterBefore(myFilter,UsernamePasswordAuthenticationFilter)
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER")
+		}
+	}
+
+	def "SEC-2274: WebSecurityConfigurer adds ApplicationContext as a shared object"() {
+		when:
+			loadConfig(ApplicationContextSharedObjectConfig)
+		then:
+			context.getBean(ApplicationContextSharedObjectConfig).http.getSharedObject(ApplicationContext) == context
+	}
+
+	@EnableWebSecurity
+	static class ApplicationContextSharedObjectConfig extends WebSecurityConfigurerAdapter {
+
+	}
+
+	static class MyFilter extends OncePerRequestFilter {
+		private UserDetailsService userDetailsService
+		public MyFilter(UserDetailsService uds) {
+			assert uds != null
+			this.userDetailsService = uds
+		}
+		public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {
+			chain.doFilter(request,response)
+		}
+	}
+
+	def "AuthenticationTrustResolver populated as defaultObject"() {
+		setup:
+			CustomTrustResolverConfig.TR = Mock(AuthenticationTrustResolver)
+		when:
+			loadConfig(CustomTrustResolverConfig)
+		then:
+			context.getBean(CustomTrustResolverConfig).http.getSharedObject(AuthenticationTrustResolver) == CustomTrustResolverConfig.TR
+	}
+
+	@EnableWebSecurity
+	static class CustomTrustResolverConfig extends WebSecurityConfigurerAdapter {
+		static AuthenticationTrustResolver TR
+
+		@Bean
+		public AuthenticationTrustResolver tr() {
+			return TR
+		}
+	}
+
+	def "WebSecurityConfigurerAdapter has Ordered between 0 and lowest priority"() {
+		when:
+			def lowestConfig = new LowestPriorityWebSecurityConfig()
+			def defaultConfig = new DefaultOrderWebSecurityConfig()
+			def compare = new AnnotationAwareOrderComparator()
+		then: "the default ordering is between 0 and lowest priority (Boot adapters)"
+			compare.compare(lowestConfig, defaultConfig) > 0
+	}
+
+	class DefaultOrderWebSecurityConfig extends WebSecurityConfigurerAdapter {}
+
+	@Order(Ordered.LOWEST_PRECEDENCE)
+	class LowestPriorityWebSecurityConfig extends WebSecurityConfigurerAdapter {}
 }

+ 70 - 70
config/src/test/groovy/org/springframework/security/config/annotation/web/builders/HttpConfigurationTests.groovy

@@ -41,81 +41,81 @@ import spock.lang.Unroll;
  *
  */
 public class HttpSecurityTests extends BaseSpringSpec {
-    def "addFilter with unregistered Filter"() {
-        when:
-            loadConfig(UnregisteredFilterConfig)
-        then:
-            BeanCreationException success = thrown()
-            success.message.contains "The Filter class ${UnregisteredFilter.name} does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead."
-    }
+	def "addFilter with unregistered Filter"() {
+		when:
+			loadConfig(UnregisteredFilterConfig)
+		then:
+			BeanCreationException success = thrown()
+			success.message.contains "The Filter class ${UnregisteredFilter.name} does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead."
+	}
 
-    @Configuration
-    static class UnregisteredFilterConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .addFilter(new UnregisteredFilter())
-        }
-    }
+	@Configuration
+	static class UnregisteredFilterConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.addFilter(new UnregisteredFilter())
+		}
+	}
 
-    static class UnregisteredFilter extends OncePerRequestFilter {
-        @Override
-        protected void doFilterInternal(HttpServletRequest request,
-                HttpServletResponse response, FilterChain filterChain)
-                throws ServletException, IOException {
-            filterChain.doFilter(request, response);
-        }
-    }
+	static class UnregisteredFilter extends OncePerRequestFilter {
+		@Override
+		protected void doFilterInternal(HttpServletRequest request,
+				HttpServletResponse response, FilterChain filterChain)
+				throws ServletException, IOException {
+			filterChain.doFilter(request, response);
+		}
+	}
 
-    // https://github.com/SpringSource/spring-security-javaconfig/issues/104
-    def "#104 addFilter CasAuthenticationFilter"() {
-        when:
-            loadConfig(CasAuthenticationFilterConfig)
-        then:
-            findFilter(CasAuthenticationFilter)
-    }
+	// https://github.com/SpringSource/spring-security-javaconfig/issues/104
+	def "#104 addFilter CasAuthenticationFilter"() {
+		when:
+			loadConfig(CasAuthenticationFilterConfig)
+		then:
+			findFilter(CasAuthenticationFilter)
+	}
 
-    @Configuration
-    static class CasAuthenticationFilterConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .addFilter(new CasAuthenticationFilter())
-        }
-    }
+	@Configuration
+	static class CasAuthenticationFilterConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.addFilter(new CasAuthenticationFilter())
+		}
+	}
 
 
-    @Unroll
-    def "requestMatchers javadoc"() {
-        setup: "load configuration like the config on the requestMatchers() javadoc"
-            loadConfig(RequestMatcherRegistryConfigs)
-        when:
-            super.setup()
-            request.servletPath = "/oauth/a"
-            springSecurityFilterChain.doFilter(request, response, chain)
-        then:
-            response.status == HttpServletResponse.SC_UNAUTHORIZED
-        where:
-            servletPath | _
-            "/oauth/a"  | _
-            "/oauth/b"  | _
-            "/api/a"    | _
-            "/api/b"    | _
-            "/oauth2/b" | _
-            "/api2/b"   | _
-    }
+	@Unroll
+	def "requestMatchers javadoc"() {
+		setup: "load configuration like the config on the requestMatchers() javadoc"
+			loadConfig(RequestMatcherRegistryConfigs)
+		when:
+			super.setup()
+			request.servletPath = "/oauth/a"
+			springSecurityFilterChain.doFilter(request, response, chain)
+		then:
+			response.status == HttpServletResponse.SC_UNAUTHORIZED
+		where:
+			servletPath | _
+			"/oauth/a"  | _
+			"/oauth/b"  | _
+			"/api/a"    | _
+			"/api/b"    | _
+			"/oauth2/b" | _
+			"/api2/b"   | _
+	}
 
-    @EnableWebSecurity
-    static class RequestMatcherRegistryConfigs extends BaseWebConfig {
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-              .requestMatchers()
-                  .antMatchers("/api/**")
-                  .antMatchers("/oauth/**")
-                  .and()
-              .authorizeRequests()
-                  .antMatchers("/**").hasRole("USER")
-                  .and()
-              .httpBasic()
-        }
-    }
+	@EnableWebSecurity
+	static class RequestMatcherRegistryConfigs extends BaseWebConfig {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+			  .requestMatchers()
+				  .antMatchers("/api/**")
+				  .antMatchers("/oauth/**")
+				  .and()
+			  .authorizeRequests()
+				  .antMatchers("/**").hasRole("USER")
+				  .and()
+			  .httpBasic()
+		}
+	}
 }

+ 44 - 44
config/src/test/groovy/org/springframework/security/config/annotation/web/configuration/EnableWebSecurityTests.groovy

@@ -29,57 +29,57 @@ import org.springframework.security.web.debug.DebugFilter;
 
 class EnableWebSecurityTests extends BaseSpringSpec {
 
-    def "@Bean(BeanIds.AUTHENTICATION_MANAGER) includes HttpSecurity's AuthenticationManagerBuilder"() {
-        when:
-            loadConfig(SecurityConfig)
-            AuthenticationManager authenticationManager = context.getBean(AuthenticationManager)
-            AnonymousAuthenticationToken anonymousAuthToken = findFilter(AnonymousAuthenticationFilter).createAuthentication(new MockHttpServletRequest())
-        then:
-            authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
-            authenticationManager.authenticate(anonymousAuthToken)
+	def "@Bean(BeanIds.AUTHENTICATION_MANAGER) includes HttpSecurity's AuthenticationManagerBuilder"() {
+		when:
+			loadConfig(SecurityConfig)
+			AuthenticationManager authenticationManager = context.getBean(AuthenticationManager)
+			AnonymousAuthenticationToken anonymousAuthToken = findFilter(AnonymousAuthenticationFilter).createAuthentication(new MockHttpServletRequest())
+		then:
+			authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
+			authenticationManager.authenticate(anonymousAuthToken)
 
-    }
+	}
 
 
-    @EnableWebSecurity
-    static class SecurityConfig extends WebSecurityConfigurerAdapter {
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER");
-        }
+	@EnableWebSecurity
+	static class SecurityConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER");
+		}
 
-        @Bean
-        @Override
-        public AuthenticationManager authenticationManagerBean()
-                throws Exception {
-            return super.authenticationManagerBean();
-        }
+		@Bean
+		@Override
+		public AuthenticationManager authenticationManagerBean()
+				throws Exception {
+			return super.authenticationManagerBean();
+		}
 
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .antMatchers("/*").hasRole("USER")
-                    .and()
-                .formLogin();
-        }
-    }
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.antMatchers("/*").hasRole("USER")
+					.and()
+				.formLogin();
+		}
+	}
 
-    def "@EnableWebSecurity on superclass"() {
-        when:
-            loadConfig(ChildSecurityConfig)
-        then:
-            context.getBean("springSecurityFilterChain", DebugFilter)
-    }
+	def "@EnableWebSecurity on superclass"() {
+		when:
+			loadConfig(ChildSecurityConfig)
+		then:
+			context.getBean("springSecurityFilterChain", DebugFilter)
+	}
 
-    @Configuration
-    static class ChildSecurityConfig extends DebugSecurityConfig {
-    }
+	@Configuration
+	static class ChildSecurityConfig extends DebugSecurityConfig {
+	}
 
-    @EnableWebSecurity(debug=true)
-    static class DebugSecurityConfig extends WebSecurityConfigurerAdapter {
+	@EnableWebSecurity(debug=true)
+	static class DebugSecurityConfig extends WebSecurityConfigurerAdapter {
 
-    }
+	}
 }

+ 291 - 291
config/src/test/groovy/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.groovy

@@ -47,295 +47,295 @@ import org.springframework.test.util.ReflectionTestUtils
  */
 class WebSecurityConfigurationTests extends BaseSpringSpec {
 
-    def "WebSecurityConfigurers are sorted"() {
-        when:
-            loadConfig(SortedWebSecurityConfigurerAdaptersConfig);
-            List<SecurityFilterChain> filterChains = context.getBean(FilterChainProxy).filterChains
-        then:
-            filterChains[0].requestMatcher.pattern == "/ignore1"
-            filterChains[0].filters.empty
-            filterChains[1].requestMatcher.pattern == "/ignore2"
-            filterChains[1].filters.empty
-
-            filterChains[2].requestMatcher.pattern == "/role1/**"
-            filterChains[3].requestMatcher.pattern == "/role2/**"
-            filterChains[4].requestMatcher.pattern == "/role3/**"
-            filterChains[5].requestMatcher.class == AnyRequestMatcher
-    }
-
-
-    @EnableWebSecurity
-    static class SortedWebSecurityConfigurerAdaptersConfig {
-        public AuthenticationManager authenticationManager() throws Exception {
-            return new AuthenticationManagerBuilder()
-                .inMemoryAuthentication()
-                    .withUser("marissa").password("koala").roles("USER").and()
-                    .withUser("paul").password("emu").roles("USER").and()
-                    .and()
-                .build();
-        }
-
-        @Configuration
-        @Order(1)
-        public static class WebConfigurer1 extends WebSecurityConfigurerAdapter {
-            @Override
-            public void configure(WebSecurity web)	throws Exception {
-                web
-                    .ignoring()
-                        .antMatchers("/ignore1","/ignore2");
-            }
-
-            @Override
-            protected void configure(HttpSecurity http) throws Exception {
-                http
-                    .antMatcher("/role1/**")
-                    .authorizeRequests()
-                        .anyRequest().hasRole("1");
-            }
-        }
-
-        @Configuration
-        @Order(2)
-        public static class WebConfigurer2 extends WebSecurityConfigurerAdapter {
-            @Override
-            protected void configure(HttpSecurity http) throws Exception {
-                http
-                    .antMatcher("/role2/**")
-                        .authorizeRequests()
-                            .anyRequest().hasRole("2");
-            }
-        }
-
-        @Configuration
-        @Order(3)
-        public static class WebConfigurer3 extends WebSecurityConfigurerAdapter {
-            @Override
-            protected void configure(HttpSecurity http) throws Exception {
-                http
-                    .antMatcher("/role3/**")
-                    .authorizeRequests()
-                        .anyRequest().hasRole("3");
-            }
-        }
-
-        @Configuration
-        public static class WebConfigurer4 extends WebSecurityConfigurerAdapter {
-
-            @Override
-            protected void configure(HttpSecurity http) throws Exception {
-                http
-                    .authorizeRequests()
-                        .anyRequest().hasRole("4");
-            }
-        }
-    }
-
-    def "WebSecurityConfigurers fails with duplicate order"() {
-        when:
-            loadConfig(DuplicateOrderConfig);
-        then:
-            BeanCreationException e = thrown()
-            e.message.contains "@Order on WebSecurityConfigurers must be unique"
-    }
-
-
-    @EnableWebSecurity
-    static class DuplicateOrderConfig {
-        public AuthenticationManager authenticationManager() throws Exception {
-            return new AuthenticationManagerBuilder()
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER").and()
-                    .and()
-                .build();
-        }
-
-        @Configuration
-        public static class WebConfigurer1 extends WebSecurityConfigurerAdapter {
-
-            @Override
-            protected void configure(HttpSecurity http) throws Exception {
-                http
-                    .antMatcher("/role1/**")
-                    .authorizeRequests()
-                        .anyRequest().hasRole("1");
-            }
-        }
-
-        @Configuration
-        public static class WebConfigurer2 extends WebSecurityConfigurerAdapter {
-            @Override
-            protected void configure(HttpSecurity http) throws Exception {
-                http
-                    .antMatcher("/role2/**")
-                    .authorizeRequests()
-                        .anyRequest().hasRole("2");
-            }
-        }
-    }
-
-    def "Override privilegeEvaluator"() {
-        setup:
-            WebInvocationPrivilegeEvaluator privilegeEvaluator = Mock()
-            PrivilegeEvaluatorConfigurerAdapterConfig.PE = privilegeEvaluator
-        when:
-            loadConfig(PrivilegeEvaluatorConfigurerAdapterConfig)
-        then:
-            context.getBean(WebInvocationPrivilegeEvaluator) == privilegeEvaluator
-    }
-
-    @EnableWebSecurity
-    static class PrivilegeEvaluatorConfigurerAdapterConfig extends WebSecurityConfigurerAdapter {
-        static WebInvocationPrivilegeEvaluator PE
-
-        @Override
-        public void configure(WebSecurity web) throws Exception {
-            web
-                .privilegeEvaluator(PE)
-        }
-    }
-
-    def "Override webSecurityExpressionHandler"() {
-        setup:
-            SecurityExpressionHandler expressionHandler = Mock()
-            ExpressionParser parser = Mock()
-            WebSecurityExpressionHandlerConfig.EH = expressionHandler
-        when:
-            loadConfig(WebSecurityExpressionHandlerConfig)
-        then:
-            context.getBean(SecurityExpressionHandler) == expressionHandler
-            1 * expressionHandler.getExpressionParser() >> parser
-    }
-
-    @EnableWebSecurity
-    static class WebSecurityExpressionHandlerConfig extends WebSecurityConfigurerAdapter {
-        static SecurityExpressionHandler EH
-
-        @Override
-        public void configure(WebSecurity web) throws Exception {
-            web
-                .expressionHandler(EH)
-        }
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .expressionHandler(EH)
-                    .anyRequest().authenticated()
-        }
-    }
-
-    def "#138 webSecurityExpressionHandler defaults"() {
-        when:
-            loadConfig(WebSecurityExpressionHandlerDefaultsConfig)
-        then:
-            SecurityExpressionHandler wseh = context.getBean(SecurityExpressionHandler)
-            wseh instanceof DefaultWebSecurityExpressionHandler
-    }
-
-    @EnableWebSecurity
-    static class WebSecurityExpressionHandlerDefaultsConfig extends WebSecurityConfigurerAdapter {
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().authenticated()
-        }
-    }
-
-    def "#138 WebInvocationPrivilegeEvaluator defaults"() {
-        when:
-            loadConfig(WebInvocationPrivilegeEvaluatorDefaultsConfig)
-        then:
-            WebInvocationPrivilegeEvaluator wipe = context.getBean(WebInvocationPrivilegeEvaluator)
-            wipe instanceof DefaultWebInvocationPrivilegeEvaluator
-            wipe.securityInterceptor != null
-    }
-
-    @EnableWebSecurity
-    static class WebInvocationPrivilegeEvaluatorDefaultsConfig extends WebSecurityConfigurerAdapter {
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().authenticated()
-        }
-    }
-
-    def "SEC-2303: DefaultExpressionHandler has bean resolver set"() {
-        when:
-            loadConfig(DefaultExpressionHandlerSetsBeanResolverConfig)
-        then: "the exposed bean has a BeanResolver set"
-            ReflectionTestUtils.getField(context.getBean(SecurityExpressionHandler),"br")
-        when:
-            springSecurityFilterChain.doFilter(request, response, chain)
-        then: "we can use the BeanResolver with a grant"
-            noExceptionThrown()
-        when: "we can use the Beanresolver with a deny"
-            springSecurityFilterChain.doFilter(new MockHttpServletRequest(method:'POST'), response, chain)
-        then:
-            noExceptionThrown()
-    }
-
-    @EnableWebSecurity
-    static class DefaultExpressionHandlerSetsBeanResolverConfig extends WebSecurityConfigurerAdapter {
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().access("request.method == 'GET' ? @b.grant() : @b.deny()")
-        }
-
-        @Bean
-        public MyBean b() {
-            new MyBean()
-        }
-
-        static class MyBean {
-            boolean deny() {
-                false
-            }
-
-            boolean grant() {
-                true
-            }
-        }
-    }
-
-    def "SEC-2461: Multiple WebSecurityConfiguration instances cause null springSecurityFilterChain"() {
-        setup:
-            def parent = loadConfig(ParentConfig)
-            def child = new AnnotationConfigApplicationContext()
-            child.register(ChildConfig)
-            child.parent = parent
-        when:
-            child.refresh()
-        then: "springSecurityFilterChain can be found in parent and child"
-            parent.getBean("springSecurityFilterChain")
-            child.getBean("springSecurityFilterChain")
-        and: "springSecurityFilterChain is defined in both parent and child (don't search parent)"
-            parent.containsBeanDefinition("springSecurityFilterChain")
-            child.containsBeanDefinition("springSecurityFilterChain")
-        cleanup:
-            child?.close()
-            // parent.close() is in superclass
-    }
-
-    @EnableWebSecurity
-    static class ParentConfig extends WebSecurityConfigurerAdapter {
-        @Autowired
-        public void configureGlobal(AuthenticationManagerBuilder auth) {
-            auth.inMemoryAuthentication()
-        }
-    }
-
-    @EnableWebSecurity
-    static class ChildConfig extends WebSecurityConfigurerAdapter { }
-
-    def "SEC-2773: delegatingApplicationListener is static method"() {
-        expect: 'delegatingApplicationListener to prevent premature instantiation of WebSecurityConfiguration'
-        Modifier.isStatic(WebSecurityConfiguration.metaClass.methods.find { it.name == 'delegatingApplicationListener'}.modifiers)
-    }
+	def "WebSecurityConfigurers are sorted"() {
+		when:
+			loadConfig(SortedWebSecurityConfigurerAdaptersConfig);
+			List<SecurityFilterChain> filterChains = context.getBean(FilterChainProxy).filterChains
+		then:
+			filterChains[0].requestMatcher.pattern == "/ignore1"
+			filterChains[0].filters.empty
+			filterChains[1].requestMatcher.pattern == "/ignore2"
+			filterChains[1].filters.empty
+
+			filterChains[2].requestMatcher.pattern == "/role1/**"
+			filterChains[3].requestMatcher.pattern == "/role2/**"
+			filterChains[4].requestMatcher.pattern == "/role3/**"
+			filterChains[5].requestMatcher.class == AnyRequestMatcher
+	}
+
+
+	@EnableWebSecurity
+	static class SortedWebSecurityConfigurerAdaptersConfig {
+		public AuthenticationManager authenticationManager() throws Exception {
+			return new AuthenticationManagerBuilder()
+				.inMemoryAuthentication()
+					.withUser("marissa").password("koala").roles("USER").and()
+					.withUser("paul").password("emu").roles("USER").and()
+					.and()
+				.build();
+		}
+
+		@Configuration
+		@Order(1)
+		public static class WebConfigurer1 extends WebSecurityConfigurerAdapter {
+			@Override
+			public void configure(WebSecurity web)	throws Exception {
+				web
+					.ignoring()
+						.antMatchers("/ignore1","/ignore2");
+			}
+
+			@Override
+			protected void configure(HttpSecurity http) throws Exception {
+				http
+					.antMatcher("/role1/**")
+					.authorizeRequests()
+						.anyRequest().hasRole("1");
+			}
+		}
+
+		@Configuration
+		@Order(2)
+		public static class WebConfigurer2 extends WebSecurityConfigurerAdapter {
+			@Override
+			protected void configure(HttpSecurity http) throws Exception {
+				http
+					.antMatcher("/role2/**")
+						.authorizeRequests()
+							.anyRequest().hasRole("2");
+			}
+		}
+
+		@Configuration
+		@Order(3)
+		public static class WebConfigurer3 extends WebSecurityConfigurerAdapter {
+			@Override
+			protected void configure(HttpSecurity http) throws Exception {
+				http
+					.antMatcher("/role3/**")
+					.authorizeRequests()
+						.anyRequest().hasRole("3");
+			}
+		}
+
+		@Configuration
+		public static class WebConfigurer4 extends WebSecurityConfigurerAdapter {
+
+			@Override
+			protected void configure(HttpSecurity http) throws Exception {
+				http
+					.authorizeRequests()
+						.anyRequest().hasRole("4");
+			}
+		}
+	}
+
+	def "WebSecurityConfigurers fails with duplicate order"() {
+		when:
+			loadConfig(DuplicateOrderConfig);
+		then:
+			BeanCreationException e = thrown()
+			e.message.contains "@Order on WebSecurityConfigurers must be unique"
+	}
+
+
+	@EnableWebSecurity
+	static class DuplicateOrderConfig {
+		public AuthenticationManager authenticationManager() throws Exception {
+			return new AuthenticationManagerBuilder()
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER").and()
+					.and()
+				.build();
+		}
+
+		@Configuration
+		public static class WebConfigurer1 extends WebSecurityConfigurerAdapter {
+
+			@Override
+			protected void configure(HttpSecurity http) throws Exception {
+				http
+					.antMatcher("/role1/**")
+					.authorizeRequests()
+						.anyRequest().hasRole("1");
+			}
+		}
+
+		@Configuration
+		public static class WebConfigurer2 extends WebSecurityConfigurerAdapter {
+			@Override
+			protected void configure(HttpSecurity http) throws Exception {
+				http
+					.antMatcher("/role2/**")
+					.authorizeRequests()
+						.anyRequest().hasRole("2");
+			}
+		}
+	}
+
+	def "Override privilegeEvaluator"() {
+		setup:
+			WebInvocationPrivilegeEvaluator privilegeEvaluator = Mock()
+			PrivilegeEvaluatorConfigurerAdapterConfig.PE = privilegeEvaluator
+		when:
+			loadConfig(PrivilegeEvaluatorConfigurerAdapterConfig)
+		then:
+			context.getBean(WebInvocationPrivilegeEvaluator) == privilegeEvaluator
+	}
+
+	@EnableWebSecurity
+	static class PrivilegeEvaluatorConfigurerAdapterConfig extends WebSecurityConfigurerAdapter {
+		static WebInvocationPrivilegeEvaluator PE
+
+		@Override
+		public void configure(WebSecurity web) throws Exception {
+			web
+				.privilegeEvaluator(PE)
+		}
+	}
+
+	def "Override webSecurityExpressionHandler"() {
+		setup:
+			SecurityExpressionHandler expressionHandler = Mock()
+			ExpressionParser parser = Mock()
+			WebSecurityExpressionHandlerConfig.EH = expressionHandler
+		when:
+			loadConfig(WebSecurityExpressionHandlerConfig)
+		then:
+			context.getBean(SecurityExpressionHandler) == expressionHandler
+			1 * expressionHandler.getExpressionParser() >> parser
+	}
+
+	@EnableWebSecurity
+	static class WebSecurityExpressionHandlerConfig extends WebSecurityConfigurerAdapter {
+		static SecurityExpressionHandler EH
+
+		@Override
+		public void configure(WebSecurity web) throws Exception {
+			web
+				.expressionHandler(EH)
+		}
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.expressionHandler(EH)
+					.anyRequest().authenticated()
+		}
+	}
+
+	def "#138 webSecurityExpressionHandler defaults"() {
+		when:
+			loadConfig(WebSecurityExpressionHandlerDefaultsConfig)
+		then:
+			SecurityExpressionHandler wseh = context.getBean(SecurityExpressionHandler)
+			wseh instanceof DefaultWebSecurityExpressionHandler
+	}
+
+	@EnableWebSecurity
+	static class WebSecurityExpressionHandlerDefaultsConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().authenticated()
+		}
+	}
+
+	def "#138 WebInvocationPrivilegeEvaluator defaults"() {
+		when:
+			loadConfig(WebInvocationPrivilegeEvaluatorDefaultsConfig)
+		then:
+			WebInvocationPrivilegeEvaluator wipe = context.getBean(WebInvocationPrivilegeEvaluator)
+			wipe instanceof DefaultWebInvocationPrivilegeEvaluator
+			wipe.securityInterceptor != null
+	}
+
+	@EnableWebSecurity
+	static class WebInvocationPrivilegeEvaluatorDefaultsConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().authenticated()
+		}
+	}
+
+	def "SEC-2303: DefaultExpressionHandler has bean resolver set"() {
+		when:
+			loadConfig(DefaultExpressionHandlerSetsBeanResolverConfig)
+		then: "the exposed bean has a BeanResolver set"
+			ReflectionTestUtils.getField(context.getBean(SecurityExpressionHandler),"br")
+		when:
+			springSecurityFilterChain.doFilter(request, response, chain)
+		then: "we can use the BeanResolver with a grant"
+			noExceptionThrown()
+		when: "we can use the Beanresolver with a deny"
+			springSecurityFilterChain.doFilter(new MockHttpServletRequest(method:'POST'), response, chain)
+		then:
+			noExceptionThrown()
+	}
+
+	@EnableWebSecurity
+	static class DefaultExpressionHandlerSetsBeanResolverConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().access("request.method == 'GET' ? @b.grant() : @b.deny()")
+		}
+
+		@Bean
+		public MyBean b() {
+			new MyBean()
+		}
+
+		static class MyBean {
+			boolean deny() {
+				false
+			}
+
+			boolean grant() {
+				true
+			}
+		}
+	}
+
+	def "SEC-2461: Multiple WebSecurityConfiguration instances cause null springSecurityFilterChain"() {
+		setup:
+			def parent = loadConfig(ParentConfig)
+			def child = new AnnotationConfigApplicationContext()
+			child.register(ChildConfig)
+			child.parent = parent
+		when:
+			child.refresh()
+		then: "springSecurityFilterChain can be found in parent and child"
+			parent.getBean("springSecurityFilterChain")
+			child.getBean("springSecurityFilterChain")
+		and: "springSecurityFilterChain is defined in both parent and child (don't search parent)"
+			parent.containsBeanDefinition("springSecurityFilterChain")
+			child.containsBeanDefinition("springSecurityFilterChain")
+		cleanup:
+			child?.close()
+			// parent.close() is in superclass
+	}
+
+	@EnableWebSecurity
+	static class ParentConfig extends WebSecurityConfigurerAdapter {
+		@Autowired
+		public void configureGlobal(AuthenticationManagerBuilder auth) {
+			auth.inMemoryAuthentication()
+		}
+	}
+
+	@EnableWebSecurity
+	static class ChildConfig extends WebSecurityConfigurerAdapter { }
+
+	def "SEC-2773: delegatingApplicationListener is static method"() {
+		expect: 'delegatingApplicationListener to prevent premature instantiation of WebSecurityConfiguration'
+		Modifier.isStatic(WebSecurityConfiguration.metaClass.methods.find { it.name == 'delegatingApplicationListener'}.modifiers)
+	}
 }

+ 12 - 12
config/src/test/groovy/org/springframework/security/config/annotation/web/configuration/sec2377/Sec2377Tests.groovy

@@ -22,17 +22,17 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationCon
 
 public class Sec2377Tests extends BaseSpringSpec {
 
-    def "SEC-2377: Error reporting with multiple EnableWebSecurity from other packages"() {
-        when:
-            AnnotationConfigWebApplicationContext parent = new AnnotationConfigWebApplicationContext()
-            parent.register(Sec2377AConfig)
-            parent.refresh()
+	def "SEC-2377: Error reporting with multiple EnableWebSecurity from other packages"() {
+		when:
+			AnnotationConfigWebApplicationContext parent = new AnnotationConfigWebApplicationContext()
+			parent.register(Sec2377AConfig)
+			parent.refresh()
 
-            AnnotationConfigWebApplicationContext child = new AnnotationConfigWebApplicationContext()
-            child.register(Sec2377BConfig)
-            child.parent = parent
-            child.refresh()
-        then:
-            noExceptionThrown();
-    }
+			AnnotationConfigWebApplicationContext child = new AnnotationConfigWebApplicationContext()
+			child.register(Sec2377BConfig)
+			child.parent = parent
+			child.refresh()
+		then:
+			noExceptionThrown();
+	}
 }

+ 33 - 33
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/AbstractConfigAttributeRequestMatcherRegistryTests.groovy

@@ -29,43 +29,43 @@ import spock.lang.Specification
  *
  */
 class AbstractConfigAttributeRequestMatcherRegistryTests extends Specification {
-    ConcreteAbstractRequestMatcherMappingConfigurer registry = new ConcreteAbstractRequestMatcherMappingConfigurer()
+	ConcreteAbstractRequestMatcherMappingConfigurer registry = new ConcreteAbstractRequestMatcherMappingConfigurer()
 
-    def "regexMatchers(GET,'/a.*') uses RegexRequestMatcher"() {
-        when:
-        def matchers = registry.regexMatchers(HttpMethod.GET,"/a.*")
-        then: 'matcher is a RegexRequestMatcher'
-        matchers.collect {it.class } == [RegexRequestMatcher]
-    }
+	def "regexMatchers(GET,'/a.*') uses RegexRequestMatcher"() {
+		when:
+		def matchers = registry.regexMatchers(HttpMethod.GET,"/a.*")
+		then: 'matcher is a RegexRequestMatcher'
+		matchers.collect {it.class } == [RegexRequestMatcher]
+	}
 
-    def "regexMatchers('/a.*') uses RegexRequestMatcher"() {
-        when:
-        def matchers = registry.regexMatchers("/a.*")
-        then: 'matcher is a RegexRequestMatcher'
-        matchers.collect {it.class } == [RegexRequestMatcher]
-    }
+	def "regexMatchers('/a.*') uses RegexRequestMatcher"() {
+		when:
+		def matchers = registry.regexMatchers("/a.*")
+		then: 'matcher is a RegexRequestMatcher'
+		matchers.collect {it.class } == [RegexRequestMatcher]
+	}
 
-    def "antMatchers(GET,'/a.*') uses AntPathRequestMatcher"() {
-        when:
-        def matchers = registry.antMatchers(HttpMethod.GET, "/a.*")
-        then: 'matcher is a RegexRequestMatcher'
-        matchers.collect {it.class } == [AntPathRequestMatcher]
-    }
+	def "antMatchers(GET,'/a.*') uses AntPathRequestMatcher"() {
+		when:
+		def matchers = registry.antMatchers(HttpMethod.GET, "/a.*")
+		then: 'matcher is a RegexRequestMatcher'
+		matchers.collect {it.class } == [AntPathRequestMatcher]
+	}
 
-    def "antMatchers('/a.*') uses AntPathRequestMatcher"() {
-        when:
-        def matchers = registry.antMatchers("/a.*")
-        then: 'matcher is a AntPathRequestMatcher'
-        matchers.collect {it.class } == [AntPathRequestMatcher]
-    }
+	def "antMatchers('/a.*') uses AntPathRequestMatcher"() {
+		when:
+		def matchers = registry.antMatchers("/a.*")
+		then: 'matcher is a AntPathRequestMatcher'
+		matchers.collect {it.class } == [AntPathRequestMatcher]
+	}
 
-    static class ConcreteAbstractRequestMatcherMappingConfigurer extends AbstractConfigAttributeRequestMatcherRegistry<List<RequestMatcher>> {
-        List<AccessDecisionVoter> decisionVoters() {
-            return null;
-        }
+	static class ConcreteAbstractRequestMatcherMappingConfigurer extends AbstractConfigAttributeRequestMatcherRegistry<List<RequestMatcher>> {
+		List<AccessDecisionVoter> decisionVoters() {
+			return null;
+		}
 
-        List<RequestMatcher> chainRequestMatchersInternal(List<RequestMatcher> requestMatchers) {
-            return requestMatchers;
-        }
-    }
+		List<RequestMatcher> chainRequestMatchersInternal(List<RequestMatcher> requestMatchers) {
+			return requestMatchers;
+		}
+	}
 }

+ 17 - 17
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/AnonymousConfigurerTests.groovy

@@ -31,23 +31,23 @@ import org.springframework.security.web.authentication.logout.LogoutFilter
  */
 class AnonymousConfigurerTests extends BaseSpringSpec {
 
-    def "invoke logout twice does not override"() {
-        when:
-            loadConfig(InvokeTwiceDoesNotOverride)
-        then:
-            findFilter(AnonymousAuthenticationFilter).key == "custom"
-    }
+	def "invoke logout twice does not override"() {
+		when:
+			loadConfig(InvokeTwiceDoesNotOverride)
+		then:
+			findFilter(AnonymousAuthenticationFilter).key == "custom"
+	}
 
-    @EnableWebSecurity
-    static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
+	@EnableWebSecurity
+	static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
 
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .anonymous()
-                    .key("custom")
-                    .and()
-                .anonymous()
-        }
-    }
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.anonymous()
+					.key("custom")
+					.and()
+				.anonymous()
+		}
+	}
 }

+ 38 - 38
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurerTests.groovy

@@ -33,46 +33,46 @@ import org.springframework.security.web.access.channel.SecureChannelProcessor
  */
 class ChannelSecurityConfigurerTests extends BaseSpringSpec {
 
-    def "requiresChannel ObjectPostProcessor"() {
-        setup: "initialize the AUTH_FILTER as a mock"
-            AnyObjectPostProcessor objectPostProcessor = Mock()
-        when:
-            HttpSecurity http = new HttpSecurity(objectPostProcessor, authenticationBldr, [:])
-            http
-                .requiresChannel()
-                    .anyRequest().requiresSecure()
-                    .and()
-                .build()
+	def "requiresChannel ObjectPostProcessor"() {
+		setup: "initialize the AUTH_FILTER as a mock"
+			AnyObjectPostProcessor objectPostProcessor = Mock()
+		when:
+			HttpSecurity http = new HttpSecurity(objectPostProcessor, authenticationBldr, [:])
+			http
+				.requiresChannel()
+					.anyRequest().requiresSecure()
+					.and()
+				.build()
 
-        then: "InsecureChannelProcessor is registered with LifecycleManager"
-            1 * objectPostProcessor.postProcess(_ as InsecureChannelProcessor) >> {InsecureChannelProcessor o -> o}
-        and: "SecureChannelProcessor is registered with LifecycleManager"
-            1 * objectPostProcessor.postProcess(_ as SecureChannelProcessor) >> {SecureChannelProcessor o -> o}
-        and: "ChannelDecisionManagerImpl is registered with LifecycleManager"
-            1 * objectPostProcessor.postProcess(_ as ChannelDecisionManagerImpl) >> {ChannelDecisionManagerImpl o -> o}
-        and: "ChannelProcessingFilter is registered with LifecycleManager"
-            1 * objectPostProcessor.postProcess(_ as ChannelProcessingFilter) >> {ChannelProcessingFilter o -> o}
-    }
+		then: "InsecureChannelProcessor is registered with LifecycleManager"
+			1 * objectPostProcessor.postProcess(_ as InsecureChannelProcessor) >> {InsecureChannelProcessor o -> o}
+		and: "SecureChannelProcessor is registered with LifecycleManager"
+			1 * objectPostProcessor.postProcess(_ as SecureChannelProcessor) >> {SecureChannelProcessor o -> o}
+		and: "ChannelDecisionManagerImpl is registered with LifecycleManager"
+			1 * objectPostProcessor.postProcess(_ as ChannelDecisionManagerImpl) >> {ChannelDecisionManagerImpl o -> o}
+		and: "ChannelProcessingFilter is registered with LifecycleManager"
+			1 * objectPostProcessor.postProcess(_ as ChannelProcessingFilter) >> {ChannelProcessingFilter o -> o}
+	}
 
-    def "invoke requiresChannel twice does not override"() {
-        setup:
-            loadConfig(DuplicateInvocationsDoesNotOverrideConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.redirectedUrl == "https://localhost"
-    }
+	def "invoke requiresChannel twice does not override"() {
+		setup:
+			loadConfig(DuplicateInvocationsDoesNotOverrideConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.redirectedUrl == "https://localhost"
+	}
 
-    @EnableWebSecurity
-    static class DuplicateInvocationsDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
+	@EnableWebSecurity
+	static class DuplicateInvocationsDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
 
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .requiresChannel()
-                    .anyRequest().requiresSecure()
-                    .and()
-                .requiresChannel()
-        }
-    }
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.requiresChannel()
+					.anyRequest().requiresSecure()
+					.and()
+				.requiresChannel()
+		}
+	}
 }

+ 424 - 424
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerTests.groovy

@@ -42,428 +42,428 @@ import spock.lang.Unroll
  */
 class CsrfConfigurerTests extends BaseSpringSpec {
 
-    @Unroll
-    def "csrf applied by default"() {
-        setup:
-            loadConfig(CsrfAppliedDefaultConfig)
-            request.method = httpMethod
-            clearCsrfToken()
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == httpStatus
-        where:
-            httpMethod | httpStatus
-            'POST'     | HttpServletResponse.SC_FORBIDDEN
-            'PUT'      | HttpServletResponse.SC_FORBIDDEN
-            'PATCH'    | HttpServletResponse.SC_FORBIDDEN
-            'DELETE'   | HttpServletResponse.SC_FORBIDDEN
-            'INVALID'  | HttpServletResponse.SC_FORBIDDEN
-            'GET'      | HttpServletResponse.SC_OK
-            'HEAD'     | HttpServletResponse.SC_OK
-            'TRACE'    | HttpServletResponse.SC_OK
-            'OPTIONS'  | HttpServletResponse.SC_OK
-    }
-
-    def "csrf default creates CsrfRequestDataValueProcessor"() {
-        when:
-            loadConfig(CsrfAppliedDefaultConfig)
-        then:
-            context.getBean(RequestDataValueProcessor)
-    }
-
-    @EnableWebSecurity
-    static class CsrfAppliedDefaultConfig extends WebSecurityConfigurerAdapter {
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-        }
-    }
-
-    def "csrf disable"() {
-        setup:
-            loadConfig(DisableCsrfConfig)
-            request.method = "POST"
-            clearCsrfToken()
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            !findFilter(CsrfFilter)
-            response.status == HttpServletResponse.SC_OK
-    }
-
-    @EnableWebSecurity
-    static class DisableCsrfConfig extends WebSecurityConfigurerAdapter {
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .csrf().disable()
-        }
-    }
-
-    def "SEC-2498: Disable CSRF enables RequestCache for any method"() {
-        setup:
-            loadConfig(DisableCsrfEnablesRequestCacheConfig)
-            request.requestURI = '/tosave'
-            request.method = "POST"
-            clearCsrfToken()
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.redirectedUrl
-        when:
-            super.setupWeb(request.session)
-            request.method = "POST"
-            request.servletPath = '/login'
-            request.parameters['username'] = ['user'] as String[]
-            request.parameters['password'] = ['password'] as String[]
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.redirectedUrl == 'http://localhost/tosave'
-    }
-
-    @EnableWebSecurity
-    static class DisableCsrfEnablesRequestCacheConfig extends WebSecurityConfigurerAdapter {
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().authenticated()
-                    .and()
-                .formLogin().and()
-                .csrf().disable()
-
-        }
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER")
-        }
-    }
-
-    def "SEC-2422: csrf expire CSRF token and session-management invalid-session-url"() {
-        setup:
-            loadConfig(InvalidSessionUrlConfig)
-            request.session.clearAttributes()
-            request.setParameter("_csrf","abc")
-            request.method = "POST"
-        when: "No existing expected CsrfToken (session times out) and a POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to the session timeout page page"
-            response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-            response.redirectedUrl == "/error/sessionError"
-        when: "Existing expected CsrfToken and a POST (invalid token provided)"
-            response = new MockHttpServletResponse()
-            request = new MockHttpServletRequest(session: request.session, method:'POST')
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "Access Denied occurs"
-            response.status == HttpServletResponse.SC_FORBIDDEN
-    }
-
-    @EnableWebSecurity
-    static class InvalidSessionUrlConfig extends WebSecurityConfigurerAdapter {
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .csrf().and()
-                .sessionManagement()
-                    .invalidSessionUrl("/error/sessionError")
-        }
-    }
-
-    def "csrf requireCsrfProtectionMatcher"() {
-        setup:
-            RequireCsrfProtectionMatcherConfig.matcher = Mock(RequestMatcher)
-            RequireCsrfProtectionMatcherConfig.matcher.matches(_) >>> [false,true]
-            loadConfig(RequireCsrfProtectionMatcherConfig)
-            clearCsrfToken()
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_OK
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_FORBIDDEN
-    }
-
-    @EnableWebSecurity
-    static class RequireCsrfProtectionMatcherConfig extends WebSecurityConfigurerAdapter {
-        static RequestMatcher matcher
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .csrf()
-                    .requireCsrfProtectionMatcher(matcher)
-        }
-    }
-
-    def "csrf csrfTokenRepository"() {
-        setup:
-            CsrfTokenRepositoryConfig.repo = Mock(CsrfTokenRepository)
-            loadConfig(CsrfTokenRepositoryConfig)
-            clearCsrfToken()
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            1 * CsrfTokenRepositoryConfig.repo.loadToken(_) >> csrfToken
-            response.status == HttpServletResponse.SC_OK
-    }
-
-    def "csrf clears on logout"() {
-        setup:
-            CsrfTokenRepositoryConfig.repo = Mock(CsrfTokenRepository)
-            1 * CsrfTokenRepositoryConfig.repo.loadToken(_) >> csrfToken
-            loadConfig(CsrfTokenRepositoryConfig)
-            login()
-            request.method = "POST"
-            request.servletPath = "/logout"
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            1 *  CsrfTokenRepositoryConfig.repo.saveToken(null, _, _)
-    }
-
-    def "csrf clears on login"() {
-        setup:
-            CsrfTokenRepositoryConfig.repo = Mock(CsrfTokenRepository)
-            (1.._) * CsrfTokenRepositoryConfig.repo.loadToken(_) >> csrfToken
-            (1.._) * CsrfTokenRepositoryConfig.repo.generateToken(_) >> csrfToken
-            loadConfig(CsrfTokenRepositoryConfig)
-            request.method = "POST"
-            request.getSession()
-            request.servletPath = "/login"
-            request.setParameter("username", "user")
-            request.setParameter("password", "password")
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.redirectedUrl == "/"
-            (1.._) *  CsrfTokenRepositoryConfig.repo.saveToken(null, _, _)
-    }
-
-    @EnableWebSecurity
-    static class CsrfTokenRepositoryConfig extends WebSecurityConfigurerAdapter {
-        static CsrfTokenRepository repo
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .formLogin()
-                    .and()
-                .csrf()
-                    .csrfTokenRepository(repo)
-        }
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER")
-        }
-    }
-
-    def "csrf access denied handler"() {
-        setup:
-            AccessDeniedHandlerConfig.deniedHandler = Mock(AccessDeniedHandler)
-            1 * AccessDeniedHandlerConfig.deniedHandler.handle(_, _, _)
-            loadConfig(AccessDeniedHandlerConfig)
-            clearCsrfToken()
-            request.method = "POST"
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_OK
-    }
-
-    @EnableWebSecurity
-    static class AccessDeniedHandlerConfig extends WebSecurityConfigurerAdapter {
-        static AccessDeniedHandler deniedHandler
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .exceptionHandling()
-                    .accessDeniedHandler(deniedHandler)
-        }
-    }
-
-    def "formLogin requires CSRF token"() {
-        setup:
-            loadConfig(FormLoginConfig)
-            clearCsrfToken()
-            request.setParameter("username", "user")
-            request.setParameter("password", "password")
-            request.servletPath = "/login"
-            request.method = "POST"
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_FORBIDDEN
-            currentAuthentication == null
-    }
-
-    @EnableWebSecurity
-    static class FormLoginConfig extends WebSecurityConfigurerAdapter {
-        static AccessDeniedHandler deniedHandler
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .formLogin()
-        }
-    }
-
-    def "logout requires CSRF token"() {
-        setup:
-            loadConfig(LogoutConfig)
-            clearCsrfToken()
-            login()
-            request.servletPath = "/logout"
-            request.method = "POST"
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "logout is not allowed and user is still authenticated"
-            response.status == HttpServletResponse.SC_FORBIDDEN
-            currentAuthentication != null
-    }
-
-    def "SEC-2543: CSRF means logout requires POST"() {
-        setup:
-            loadConfig(LogoutConfig)
-            login()
-            request.servletPath = "/logout"
-            request.method = "GET"
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "logout with GET is not performed"
-            currentAuthentication != null
-    }
-
-    @EnableWebSecurity
-    static class LogoutConfig extends WebSecurityConfigurerAdapter {
-        static AccessDeniedHandler deniedHandler
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .formLogin()
-        }
-    }
-
-    def "CSRF can explicitly enable GET for logout"() {
-        setup:
-            loadConfig(LogoutAllowsGetConfig)
-            login()
-            request.servletPath = "/logout"
-            request.method = "GET"
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "logout with GET is not performed"
-            currentAuthentication == null
-    }
-
-    @EnableWebSecurity
-    static class LogoutAllowsGetConfig extends WebSecurityConfigurerAdapter {
-        static AccessDeniedHandler deniedHandler
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .formLogin().and()
-                .logout()
-                    .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
-        }
-    }
-
-    def "csrf disables POST requests from RequestCache"() {
-        setup:
-            CsrfDisablesPostRequestFromRequestCacheConfig.repo = Mock(CsrfTokenRepository)
-            (1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.generateToken(_) >> csrfToken
-            loadConfig(CsrfDisablesPostRequestFromRequestCacheConfig)
-            request.servletPath = "/some-url"
-            request.requestURI = "/some-url"
-            request.method = "POST"
-        when: "CSRF passes and our session times out"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to the login page"
-            (1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
-            response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-            response.redirectedUrl == "http://localhost/login"
-        when: "authenticate successfully"
-            super.setupWeb(request.session)
-            request.servletPath = "/login"
-            request.setParameter("username","user")
-            request.setParameter("password","password")
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to default success because we don't want csrf attempts made prior to authentication to pass"
-            (1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
-            response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-            response.redirectedUrl == "/"
-    }
-
-    def "csrf enables GET requests with RequestCache"() {
-        setup:
-            CsrfDisablesPostRequestFromRequestCacheConfig.repo = Mock(CsrfTokenRepository)
-            (1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.generateToken(_) >> csrfToken
-            loadConfig(CsrfDisablesPostRequestFromRequestCacheConfig)
-            request.servletPath = "/some-url"
-            request.requestURI = "/some-url"
-            request.method = "GET"
-        when: "CSRF passes and our session times out"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to the login page"
-            (1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
-            response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-            response.redirectedUrl == "http://localhost/login"
-        when: "authenticate successfully"
-            super.setupWeb(request.session)
-            request.servletPath = "/login"
-            request.setParameter("username","user")
-            request.setParameter("password","password")
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to original URL since it was a GET"
-            (1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
-            response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-            response.redirectedUrl == "http://localhost/some-url"
-    }
-
-    @EnableWebSecurity
-    static class CsrfDisablesPostRequestFromRequestCacheConfig extends WebSecurityConfigurerAdapter {
-        static CsrfTokenRepository repo
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().authenticated()
-                    .and()
-                .formLogin()
-                    .and()
-                .csrf()
-                    .csrfTokenRepository(repo)
-        }
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER")
-        }
-    }
-
-    def 'SEC-2749: requireCsrfProtectionMatcher null'() {
-        when:
-        new CsrfConfigurer<>().requireCsrfProtectionMatcher(null)
-        then:
-        thrown(IllegalArgumentException)
-    }
-
-    def clearCsrfToken() {
-        request.removeAllParameters()
-    }
+	@Unroll
+	def "csrf applied by default"() {
+		setup:
+			loadConfig(CsrfAppliedDefaultConfig)
+			request.method = httpMethod
+			clearCsrfToken()
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == httpStatus
+		where:
+			httpMethod | httpStatus
+			'POST'     | HttpServletResponse.SC_FORBIDDEN
+			'PUT'      | HttpServletResponse.SC_FORBIDDEN
+			'PATCH'    | HttpServletResponse.SC_FORBIDDEN
+			'DELETE'   | HttpServletResponse.SC_FORBIDDEN
+			'INVALID'  | HttpServletResponse.SC_FORBIDDEN
+			'GET'      | HttpServletResponse.SC_OK
+			'HEAD'     | HttpServletResponse.SC_OK
+			'TRACE'    | HttpServletResponse.SC_OK
+			'OPTIONS'  | HttpServletResponse.SC_OK
+	}
+
+	def "csrf default creates CsrfRequestDataValueProcessor"() {
+		when:
+			loadConfig(CsrfAppliedDefaultConfig)
+		then:
+			context.getBean(RequestDataValueProcessor)
+	}
+
+	@EnableWebSecurity
+	static class CsrfAppliedDefaultConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+		}
+	}
+
+	def "csrf disable"() {
+		setup:
+			loadConfig(DisableCsrfConfig)
+			request.method = "POST"
+			clearCsrfToken()
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			!findFilter(CsrfFilter)
+			response.status == HttpServletResponse.SC_OK
+	}
+
+	@EnableWebSecurity
+	static class DisableCsrfConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.csrf().disable()
+		}
+	}
+
+	def "SEC-2498: Disable CSRF enables RequestCache for any method"() {
+		setup:
+			loadConfig(DisableCsrfEnablesRequestCacheConfig)
+			request.requestURI = '/tosave'
+			request.method = "POST"
+			clearCsrfToken()
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.redirectedUrl
+		when:
+			super.setupWeb(request.session)
+			request.method = "POST"
+			request.servletPath = '/login'
+			request.parameters['username'] = ['user'] as String[]
+			request.parameters['password'] = ['password'] as String[]
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.redirectedUrl == 'http://localhost/tosave'
+	}
+
+	@EnableWebSecurity
+	static class DisableCsrfEnablesRequestCacheConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().authenticated()
+					.and()
+				.formLogin().and()
+				.csrf().disable()
+
+		}
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER")
+		}
+	}
+
+	def "SEC-2422: csrf expire CSRF token and session-management invalid-session-url"() {
+		setup:
+			loadConfig(InvalidSessionUrlConfig)
+			request.session.clearAttributes()
+			request.setParameter("_csrf","abc")
+			request.method = "POST"
+		when: "No existing expected CsrfToken (session times out) and a POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to the session timeout page page"
+			response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
+			response.redirectedUrl == "/error/sessionError"
+		when: "Existing expected CsrfToken and a POST (invalid token provided)"
+			response = new MockHttpServletResponse()
+			request = new MockHttpServletRequest(session: request.session, method:'POST')
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "Access Denied occurs"
+			response.status == HttpServletResponse.SC_FORBIDDEN
+	}
+
+	@EnableWebSecurity
+	static class InvalidSessionUrlConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.csrf().and()
+				.sessionManagement()
+					.invalidSessionUrl("/error/sessionError")
+		}
+	}
+
+	def "csrf requireCsrfProtectionMatcher"() {
+		setup:
+			RequireCsrfProtectionMatcherConfig.matcher = Mock(RequestMatcher)
+			RequireCsrfProtectionMatcherConfig.matcher.matches(_) >>> [false,true]
+			loadConfig(RequireCsrfProtectionMatcherConfig)
+			clearCsrfToken()
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_OK
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_FORBIDDEN
+	}
+
+	@EnableWebSecurity
+	static class RequireCsrfProtectionMatcherConfig extends WebSecurityConfigurerAdapter {
+		static RequestMatcher matcher
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.csrf()
+					.requireCsrfProtectionMatcher(matcher)
+		}
+	}
+
+	def "csrf csrfTokenRepository"() {
+		setup:
+			CsrfTokenRepositoryConfig.repo = Mock(CsrfTokenRepository)
+			loadConfig(CsrfTokenRepositoryConfig)
+			clearCsrfToken()
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			1 * CsrfTokenRepositoryConfig.repo.loadToken(_) >> csrfToken
+			response.status == HttpServletResponse.SC_OK
+	}
+
+	def "csrf clears on logout"() {
+		setup:
+			CsrfTokenRepositoryConfig.repo = Mock(CsrfTokenRepository)
+			1 * CsrfTokenRepositoryConfig.repo.loadToken(_) >> csrfToken
+			loadConfig(CsrfTokenRepositoryConfig)
+			login()
+			request.method = "POST"
+			request.servletPath = "/logout"
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			1 *  CsrfTokenRepositoryConfig.repo.saveToken(null, _, _)
+	}
+
+	def "csrf clears on login"() {
+		setup:
+			CsrfTokenRepositoryConfig.repo = Mock(CsrfTokenRepository)
+			(1.._) * CsrfTokenRepositoryConfig.repo.loadToken(_) >> csrfToken
+			(1.._) * CsrfTokenRepositoryConfig.repo.generateToken(_) >> csrfToken
+			loadConfig(CsrfTokenRepositoryConfig)
+			request.method = "POST"
+			request.getSession()
+			request.servletPath = "/login"
+			request.setParameter("username", "user")
+			request.setParameter("password", "password")
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.redirectedUrl == "/"
+			(1.._) *  CsrfTokenRepositoryConfig.repo.saveToken(null, _, _)
+	}
+
+	@EnableWebSecurity
+	static class CsrfTokenRepositoryConfig extends WebSecurityConfigurerAdapter {
+		static CsrfTokenRepository repo
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.formLogin()
+					.and()
+				.csrf()
+					.csrfTokenRepository(repo)
+		}
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER")
+		}
+	}
+
+	def "csrf access denied handler"() {
+		setup:
+			AccessDeniedHandlerConfig.deniedHandler = Mock(AccessDeniedHandler)
+			1 * AccessDeniedHandlerConfig.deniedHandler.handle(_, _, _)
+			loadConfig(AccessDeniedHandlerConfig)
+			clearCsrfToken()
+			request.method = "POST"
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_OK
+	}
+
+	@EnableWebSecurity
+	static class AccessDeniedHandlerConfig extends WebSecurityConfigurerAdapter {
+		static AccessDeniedHandler deniedHandler
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.exceptionHandling()
+					.accessDeniedHandler(deniedHandler)
+		}
+	}
+
+	def "formLogin requires CSRF token"() {
+		setup:
+			loadConfig(FormLoginConfig)
+			clearCsrfToken()
+			request.setParameter("username", "user")
+			request.setParameter("password", "password")
+			request.servletPath = "/login"
+			request.method = "POST"
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_FORBIDDEN
+			currentAuthentication == null
+	}
+
+	@EnableWebSecurity
+	static class FormLoginConfig extends WebSecurityConfigurerAdapter {
+		static AccessDeniedHandler deniedHandler
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.formLogin()
+		}
+	}
+
+	def "logout requires CSRF token"() {
+		setup:
+			loadConfig(LogoutConfig)
+			clearCsrfToken()
+			login()
+			request.servletPath = "/logout"
+			request.method = "POST"
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "logout is not allowed and user is still authenticated"
+			response.status == HttpServletResponse.SC_FORBIDDEN
+			currentAuthentication != null
+	}
+
+	def "SEC-2543: CSRF means logout requires POST"() {
+		setup:
+			loadConfig(LogoutConfig)
+			login()
+			request.servletPath = "/logout"
+			request.method = "GET"
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "logout with GET is not performed"
+			currentAuthentication != null
+	}
+
+	@EnableWebSecurity
+	static class LogoutConfig extends WebSecurityConfigurerAdapter {
+		static AccessDeniedHandler deniedHandler
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.formLogin()
+		}
+	}
+
+	def "CSRF can explicitly enable GET for logout"() {
+		setup:
+			loadConfig(LogoutAllowsGetConfig)
+			login()
+			request.servletPath = "/logout"
+			request.method = "GET"
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "logout with GET is not performed"
+			currentAuthentication == null
+	}
+
+	@EnableWebSecurity
+	static class LogoutAllowsGetConfig extends WebSecurityConfigurerAdapter {
+		static AccessDeniedHandler deniedHandler
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.formLogin().and()
+				.logout()
+					.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
+		}
+	}
+
+	def "csrf disables POST requests from RequestCache"() {
+		setup:
+			CsrfDisablesPostRequestFromRequestCacheConfig.repo = Mock(CsrfTokenRepository)
+			(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.generateToken(_) >> csrfToken
+			loadConfig(CsrfDisablesPostRequestFromRequestCacheConfig)
+			request.servletPath = "/some-url"
+			request.requestURI = "/some-url"
+			request.method = "POST"
+		when: "CSRF passes and our session times out"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to the login page"
+			(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
+			response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
+			response.redirectedUrl == "http://localhost/login"
+		when: "authenticate successfully"
+			super.setupWeb(request.session)
+			request.servletPath = "/login"
+			request.setParameter("username","user")
+			request.setParameter("password","password")
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to default success because we don't want csrf attempts made prior to authentication to pass"
+			(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
+			response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
+			response.redirectedUrl == "/"
+	}
+
+	def "csrf enables GET requests with RequestCache"() {
+		setup:
+			CsrfDisablesPostRequestFromRequestCacheConfig.repo = Mock(CsrfTokenRepository)
+			(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.generateToken(_) >> csrfToken
+			loadConfig(CsrfDisablesPostRequestFromRequestCacheConfig)
+			request.servletPath = "/some-url"
+			request.requestURI = "/some-url"
+			request.method = "GET"
+		when: "CSRF passes and our session times out"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to the login page"
+			(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
+			response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
+			response.redirectedUrl == "http://localhost/login"
+		when: "authenticate successfully"
+			super.setupWeb(request.session)
+			request.servletPath = "/login"
+			request.setParameter("username","user")
+			request.setParameter("password","password")
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to original URL since it was a GET"
+			(1.._) * CsrfDisablesPostRequestFromRequestCacheConfig.repo.loadToken(_) >> csrfToken
+			response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
+			response.redirectedUrl == "http://localhost/some-url"
+	}
+
+	@EnableWebSecurity
+	static class CsrfDisablesPostRequestFromRequestCacheConfig extends WebSecurityConfigurerAdapter {
+		static CsrfTokenRepository repo
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().authenticated()
+					.and()
+				.formLogin()
+					.and()
+				.csrf()
+					.csrfTokenRepository(repo)
+		}
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER")
+		}
+	}
+
+	def 'SEC-2749: requireCsrfProtectionMatcher null'() {
+		when:
+		new CsrfConfigurer<>().requireCsrfProtectionMatcher(null)
+		then:
+		thrown(IllegalArgumentException)
+	}
+
+	def clearCsrfToken() {
+		request.removeAllParameters()
+	}
 }

+ 89 - 89
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/DefaultFiltersTests.groovy

@@ -54,103 +54,103 @@ import org.springframework.security.web.util.matcher.AnyRequestMatcher
  */
 class DefaultFiltersTests extends BaseSpringSpec {
 
-    def "Default the WebSecurityConfigurerAdapter"() {
-        when:
-        context = new AnnotationConfigApplicationContext(FilterChainProxyBuilderMissingConfig)
-        then:
-        context.getBean(FilterChainProxy) != null
-    }
+	def "Default the WebSecurityConfigurerAdapter"() {
+		when:
+		context = new AnnotationConfigApplicationContext(FilterChainProxyBuilderMissingConfig)
+		then:
+		context.getBean(FilterChainProxy) != null
+	}
 
-    @EnableWebSecurity
-    static class FilterChainProxyBuilderMissingConfig {
-        @Autowired
-        public void configureGlobal(AuthenticationManagerBuilder auth) {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER")
-        }
-    }
+	@EnableWebSecurity
+	static class FilterChainProxyBuilderMissingConfig {
+		@Autowired
+		public void configureGlobal(AuthenticationManagerBuilder auth) {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER")
+		}
+	}
 
-    @EnableWebSecurity
-    static class FilterChainProxyBuilderNoSecurityFilterBuildersConfig {
-        @Bean
-        public WebSecurity filterChainProxyBuilder(ObjectPostProcessor<Object> opp) {
-            new WebSecurity(opp)
-                .ignoring()
-                    .antMatchers("/resources/**")
-        }
-    }
+	@EnableWebSecurity
+	static class FilterChainProxyBuilderNoSecurityFilterBuildersConfig {
+		@Bean
+		public WebSecurity filterChainProxyBuilder(ObjectPostProcessor<Object> opp) {
+			new WebSecurity(opp)
+				.ignoring()
+					.antMatchers("/resources/**")
+		}
+	}
 
-    def "null WebInvocationPrivilegeEvaluator"() {
-        when:
-        context = new AnnotationConfigApplicationContext(NullWebInvocationPrivilegeEvaluatorConfig)
-        then:
-        List<DefaultSecurityFilterChain> filterChains = context.getBean(FilterChainProxy).filterChains
-        filterChains.size() == 1
-        filterChains[0].requestMatcher instanceof AnyRequestMatcher
-        filterChains[0].filters.size() == 1
-        filterChains[0].filters.find { it instanceof UsernamePasswordAuthenticationFilter }
-    }
+	def "null WebInvocationPrivilegeEvaluator"() {
+		when:
+		context = new AnnotationConfigApplicationContext(NullWebInvocationPrivilegeEvaluatorConfig)
+		then:
+		List<DefaultSecurityFilterChain> filterChains = context.getBean(FilterChainProxy).filterChains
+		filterChains.size() == 1
+		filterChains[0].requestMatcher instanceof AnyRequestMatcher
+		filterChains[0].filters.size() == 1
+		filterChains[0].filters.find { it instanceof UsernamePasswordAuthenticationFilter }
+	}
 
-    @EnableWebSecurity
-    static class NullWebInvocationPrivilegeEvaluatorConfig extends BaseWebConfig {
-        NullWebInvocationPrivilegeEvaluatorConfig() {
-            super(true)
-        }
+	@EnableWebSecurity
+	static class NullWebInvocationPrivilegeEvaluatorConfig extends BaseWebConfig {
+		NullWebInvocationPrivilegeEvaluatorConfig() {
+			super(true)
+		}
 
-        protected void configure(HttpSecurity http) {
-            http.formLogin()
-        }
-    }
+		protected void configure(HttpSecurity http) {
+			http.formLogin()
+		}
+	}
 
-    def "FilterChainProxyBuilder ignoring resources"() {
-        when:
-            loadConfig(FilterChainProxyBuilderIgnoringConfig)
-        then:
-            List<DefaultSecurityFilterChain> filterChains = context.getBean(FilterChainProxy).filterChains
-            filterChains.size() == 2
-            filterChains[0].requestMatcher.pattern == '/resources/**'
-            filterChains[0].filters.empty
-            filterChains[1].requestMatcher instanceof AnyRequestMatcher
-            filterChains[1].filters.collect { it.class } ==
-                    [WebAsyncManagerIntegrationFilter, SecurityContextPersistenceFilter, HeaderWriterFilter, CsrfFilter, LogoutFilter, RequestCacheAwareFilter,
-                     SecurityContextHolderAwareRequestFilter, AnonymousAuthenticationFilter, SessionManagementFilter,
-                     ExceptionTranslationFilter, FilterSecurityInterceptor ]
-    }
+	def "FilterChainProxyBuilder ignoring resources"() {
+		when:
+			loadConfig(FilterChainProxyBuilderIgnoringConfig)
+		then:
+			List<DefaultSecurityFilterChain> filterChains = context.getBean(FilterChainProxy).filterChains
+			filterChains.size() == 2
+			filterChains[0].requestMatcher.pattern == '/resources/**'
+			filterChains[0].filters.empty
+			filterChains[1].requestMatcher instanceof AnyRequestMatcher
+			filterChains[1].filters.collect { it.class } ==
+					[WebAsyncManagerIntegrationFilter, SecurityContextPersistenceFilter, HeaderWriterFilter, CsrfFilter, LogoutFilter, RequestCacheAwareFilter,
+					 SecurityContextHolderAwareRequestFilter, AnonymousAuthenticationFilter, SessionManagementFilter,
+					 ExceptionTranslationFilter, FilterSecurityInterceptor ]
+	}
 
-    @EnableWebSecurity
-    static class FilterChainProxyBuilderIgnoringConfig extends BaseWebConfig {
-        @Override
-        public void configure(WebSecurity builder)	throws Exception {
-            builder
-                .ignoring()
-                    .antMatchers("/resources/**");
-        }
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER");
-        }
-    }
+	@EnableWebSecurity
+	static class FilterChainProxyBuilderIgnoringConfig extends BaseWebConfig {
+		@Override
+		public void configure(WebSecurity builder)	throws Exception {
+			builder
+				.ignoring()
+					.antMatchers("/resources/**");
+		}
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER");
+		}
+	}
 
    def "DefaultFilters.permitAll()"() {
-        when:
-            loadConfig(DefaultFiltersConfigPermitAll)
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            request = new MockHttpServletRequest(servletPath : uri, queryString: query, method:"POST")
-            setupCsrf()
-            springSecurityFilterChain.doFilter(request, response, new MockFilterChain())
-        then:
-            response.redirectedUrl == "/login?logout"
-        where:
-            uri | query
-            "/logout" | null
-    }
+		when:
+			loadConfig(DefaultFiltersConfigPermitAll)
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			request = new MockHttpServletRequest(servletPath : uri, queryString: query, method:"POST")
+			setupCsrf()
+			springSecurityFilterChain.doFilter(request, response, new MockFilterChain())
+		then:
+			response.redirectedUrl == "/login?logout"
+		where:
+			uri | query
+			"/logout" | null
+	}
 
-    @EnableWebSecurity
-    static class DefaultFiltersConfigPermitAll extends BaseWebConfig {
-        protected void configure(HttpSecurity http) {
-        }
-    }
+	@EnableWebSecurity
+	static class DefaultFiltersConfigPermitAll extends BaseWebConfig {
+		protected void configure(HttpSecurity http) {
+		}
+	}
 }

+ 249 - 249
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurerTests.groovy

@@ -42,295 +42,295 @@ import org.springframework.security.web.authentication.ui.DefaultLoginPageGenera
  *
  */
 public class DefaultLoginPageConfigurerTests extends BaseSpringSpec {
-    def "http/form-login default login generating page"() {
-        setup:
-            loadConfig(DefaultLoginPageConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            findFilter(DefaultLoginPageGeneratingFilter)
-            response.getRedirectedUrl() == "http://localhost/login"
-        when: "request the login page"
-            super.setup()
-            request.requestURI = "/login"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
+	def "http/form-login default login generating page"() {
+		setup:
+			loadConfig(DefaultLoginPageConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			findFilter(DefaultLoginPageGeneratingFilter)
+			response.getRedirectedUrl() == "http://localhost/login"
+		when: "request the login page"
+			super.setup()
+			request.requestURI = "/login"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
 <h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
  <table>
-    <tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
-    <tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
-    <tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
-    <input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
+	<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
+	<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
+	<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
+	<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
   </table>
 </form></body></html>"""
-        when: "fail to log in"
-            super.setup()
-            request.servletPath = "/login"
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to login error page"
-            response.getRedirectedUrl() == "/login?error"
-        when: "request the error page"
-            HttpSession session = request.session
-            super.setup()
-            request.session = session
-            request.requestURI = "/login"
-            request.queryString = "error"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
+		when: "fail to log in"
+			super.setup()
+			request.servletPath = "/login"
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to login error page"
+			response.getRedirectedUrl() == "/login?error"
+		when: "request the error page"
+			HttpSession session = request.session
+			super.setup()
+			request.session = session
+			request.requestURI = "/login"
+			request.queryString = "error"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
 <p><font color='red'>Your login attempt was not successful, try again.<br/><br/>Reason: Bad credentials</font></p><h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
  <table>
-    <tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
-    <tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
-    <tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
-    <input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
+	<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
+	<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
+	<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
+	<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
   </table>
 </form></body></html>"""
-        when: "login success"
-            super.setup()
-            request.servletPath = "/login"
-            request.method = "POST"
-            request.parameters.username = ["user"] as String[]
-            request.parameters.password = ["password"] as String[]
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to default succes page"
-            response.getRedirectedUrl() == "/"
-    }
+		when: "login success"
+			super.setup()
+			request.servletPath = "/login"
+			request.method = "POST"
+			request.parameters.username = ["user"] as String[]
+			request.parameters.password = ["password"] as String[]
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to default succes page"
+			response.getRedirectedUrl() == "/"
+	}
 
-    def "logout success renders"() {
-        setup:
-            loadConfig(DefaultLoginPageConfig)
-        when: "logout success"
-            request.requestURI = "/login"
-            request.queryString = "logout"
-            request.method = "GET"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to default success page"
-            response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
+	def "logout success renders"() {
+		setup:
+			loadConfig(DefaultLoginPageConfig)
+		when: "logout success"
+			request.requestURI = "/login"
+			request.queryString = "logout"
+			request.method = "GET"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to default success page"
+			response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
 <p><font color='green'>You have been logged out</font></p><h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
  <table>
-    <tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
-    <tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
-    <tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
-    <input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
+	<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
+	<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
+	<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
+	<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
   </table>
 </form></body></html>"""
-    }
+	}
 
-    @Configuration
-    static class DefaultLoginPageConfig extends BaseWebConfig {
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .formLogin()
-        }
-    }
+	@Configuration
+	static class DefaultLoginPageConfig extends BaseWebConfig {
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin()
+		}
+	}
 
-    def "custom logout success handler prevents rendering"() {
-        setup:
-            loadConfig(DefaultLoginPageCustomLogoutSuccessHandlerConfig)
-        when: "logout success"
-            request.requestURI = "/login"
-            request.queryString = "logout"
-            request.method = "GET"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "default success page is NOT rendered (application is in charge of it)"
-            response.getContentAsString() == ""
-    }
+	def "custom logout success handler prevents rendering"() {
+		setup:
+			loadConfig(DefaultLoginPageCustomLogoutSuccessHandlerConfig)
+		when: "logout success"
+			request.requestURI = "/login"
+			request.queryString = "logout"
+			request.method = "GET"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "default success page is NOT rendered (application is in charge of it)"
+			response.getContentAsString() == ""
+	}
 
-    @Configuration
-    static class DefaultLoginPageCustomLogoutSuccessHandlerConfig extends BaseWebConfig {
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .logout()
-                    .logoutSuccessHandler(new SimpleUrlLogoutSuccessHandler())
-                    .and()
-                .formLogin()
-        }
-    }
+	@Configuration
+	static class DefaultLoginPageCustomLogoutSuccessHandlerConfig extends BaseWebConfig {
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.logout()
+					.logoutSuccessHandler(new SimpleUrlLogoutSuccessHandler())
+					.and()
+				.formLogin()
+		}
+	}
 
-    def "custom logout success url prevents rendering"() {
-        setup:
-            loadConfig(DefaultLoginPageCustomLogoutConfig)
-        when: "logout success"
-            request.requestURI = "/login"
-            request.queryString = "logout"
-            request.method = "GET"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "default success page is NOT rendered (application is in charge of it)"
-            response.getContentAsString() == ""
-    }
+	def "custom logout success url prevents rendering"() {
+		setup:
+			loadConfig(DefaultLoginPageCustomLogoutConfig)
+		when: "logout success"
+			request.requestURI = "/login"
+			request.queryString = "logout"
+			request.method = "GET"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "default success page is NOT rendered (application is in charge of it)"
+			response.getContentAsString() == ""
+	}
 
-    @Configuration
-    static class DefaultLoginPageCustomLogoutConfig extends BaseWebConfig {
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .logout()
-                    .logoutSuccessUrl("/login?logout")
-                    .and()
-                .formLogin()
-        }
-    }
+	@Configuration
+	static class DefaultLoginPageCustomLogoutConfig extends BaseWebConfig {
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.logout()
+					.logoutSuccessUrl("/login?logout")
+					.and()
+				.formLogin()
+		}
+	}
 
-    def "http/form-login default login with remember me"() {
-        setup:
-            loadConfig(DefaultLoginPageWithRememberMeConfig)
-        when: "request the login page"
-            super.setup()
-            request.requestURI = "/login"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
+	def "http/form-login default login with remember me"() {
+		setup:
+			loadConfig(DefaultLoginPageWithRememberMeConfig)
+		when: "request the login page"
+			super.setup()
+			request.requestURI = "/login"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
 <h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
  <table>
-    <tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
-    <tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
-    <tr><td><input type='checkbox' name='remember-me'/></td><td>Remember me on this computer.</td></tr>
-    <tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
-    <input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
+	<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
+	<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
+	<tr><td><input type='checkbox' name='remember-me'/></td><td>Remember me on this computer.</td></tr>
+	<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
+	<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
   </table>
 </form></body></html>"""
-    }
+	}
 
-    @Configuration
-    static class DefaultLoginPageWithRememberMeConfig extends BaseWebConfig {
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .formLogin()
-                    .and()
-                .rememberMe()
-        }
-    }
+	@Configuration
+	static class DefaultLoginPageWithRememberMeConfig extends BaseWebConfig {
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin()
+					.and()
+				.rememberMe()
+		}
+	}
 
-    def "http/form-login default login with openid"() {
-        setup:
-            loadConfig(DefaultLoginPageWithOpenIDConfig)
-        when: "request the login page"
-            request.requestURI = "/login"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.getContentAsString() == """<html><head><title>Login Page</title></head><h3>Login with OpenID Identity</h3><form name='oidf' action='/login/openid' method='POST'>
+	def "http/form-login default login with openid"() {
+		setup:
+			loadConfig(DefaultLoginPageWithOpenIDConfig)
+		when: "request the login page"
+			request.requestURI = "/login"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.getContentAsString() == """<html><head><title>Login Page</title></head><h3>Login with OpenID Identity</h3><form name='oidf' action='/login/openid' method='POST'>
  <table>
-    <tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
-    <tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
+	<tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
+	<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
   </table>
-    <input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
+	<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
 </form></body></html>"""
-    }
+	}
 
-    @Configuration
-    static class DefaultLoginPageWithOpenIDConfig extends BaseWebConfig {
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .openidLogin()
-        }
-    }
+	@Configuration
+	static class DefaultLoginPageWithOpenIDConfig extends BaseWebConfig {
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.openidLogin()
+		}
+	}
 
-    def "http/form-login default login with openid, form login, and rememberme"() {
-        setup:
-            loadConfig(DefaultLoginPageWithFormLoginOpenIDRememberMeConfig)
-        when: "request the login page"
-            request.requestURI = "/login"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
+	def "http/form-login default login with openid, form login, and rememberme"() {
+		setup:
+			loadConfig(DefaultLoginPageWithFormLoginOpenIDRememberMeConfig)
+		when: "request the login page"
+			request.requestURI = "/login"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
 <h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
  <table>
-    <tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
-    <tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
-    <tr><td><input type='checkbox' name='remember-me'/></td><td>Remember me on this computer.</td></tr>
-    <tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
-    <input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
+	<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
+	<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
+	<tr><td><input type='checkbox' name='remember-me'/></td><td>Remember me on this computer.</td></tr>
+	<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
+	<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
   </table>
 </form><h3>Login with OpenID Identity</h3><form name='oidf' action='/login/openid' method='POST'>
  <table>
-    <tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
-    <tr><td><input type='checkbox' name='remember-me'></td><td>Remember me on this computer.</td></tr>
-    <tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
+	<tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
+	<tr><td><input type='checkbox' name='remember-me'></td><td>Remember me on this computer.</td></tr>
+	<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
   </table>
-    <input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
+	<input name="${csrfToken.parameterName}" type="hidden" value="${csrfToken.token}" />
 </form></body></html>"""
-    }
+	}
 
-    @Configuration
-    static class DefaultLoginPageWithFormLoginOpenIDRememberMeConfig extends BaseWebConfig {
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .rememberMe()
-                    .and()
-                .formLogin()
-                    .and()
-                .openidLogin()
-        }
-    }
+	@Configuration
+	static class DefaultLoginPageWithFormLoginOpenIDRememberMeConfig extends BaseWebConfig {
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.rememberMe()
+					.and()
+				.formLogin()
+					.and()
+				.openidLogin()
+		}
+	}
 
-    def "default login with custom AuthenticationEntryPoint"() {
-        when:
-            loadConfig(DefaultLoginWithCustomAuthenticationEntryPointConfig)
-        then:
-            !findFilter(DefaultLoginPageGeneratingFilter)
-    }
+	def "default login with custom AuthenticationEntryPoint"() {
+		when:
+			loadConfig(DefaultLoginWithCustomAuthenticationEntryPointConfig)
+		then:
+			!findFilter(DefaultLoginPageGeneratingFilter)
+	}
 
-    @Configuration
-    static class DefaultLoginWithCustomAuthenticationEntryPointConfig extends BaseWebConfig {
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .exceptionHandling()
-                    .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login"))
-                    .and()
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .formLogin()
-        }
-    }
+	@Configuration
+	static class DefaultLoginWithCustomAuthenticationEntryPointConfig extends BaseWebConfig {
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.exceptionHandling()
+					.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login"))
+					.and()
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin()
+		}
+	}
 
-    def "DefaultLoginPage ObjectPostProcessor"() {
-        setup:
-            AnyObjectPostProcessor objectPostProcessor = Mock()
-        when:
-            HttpSecurity http = new HttpSecurity(objectPostProcessor, authenticationBldr, [:])
-            DefaultLoginPageConfigurer defaultLoginConfig = new DefaultLoginPageConfigurer([builder:http])
-            defaultLoginConfig.addObjectPostProcessor(objectPostProcessor)
-            http
-                // must set builder manually due to groovy not selecting correct method
-                .apply(defaultLoginConfig).and()
-                .exceptionHandling()
-                    .and()
-                .formLogin()
-                    .and()
-                .build()
+	def "DefaultLoginPage ObjectPostProcessor"() {
+		setup:
+			AnyObjectPostProcessor objectPostProcessor = Mock()
+		when:
+			HttpSecurity http = new HttpSecurity(objectPostProcessor, authenticationBldr, [:])
+			DefaultLoginPageConfigurer defaultLoginConfig = new DefaultLoginPageConfigurer([builder:http])
+			defaultLoginConfig.addObjectPostProcessor(objectPostProcessor)
+			http
+				// must set builder manually due to groovy not selecting correct method
+				.apply(defaultLoginConfig).and()
+				.exceptionHandling()
+					.and()
+				.formLogin()
+					.and()
+				.build()
 
-        then: "DefaultLoginPageGeneratingFilter is registered with LifecycleManager"
-            1 * objectPostProcessor.postProcess(_ as DefaultLoginPageGeneratingFilter) >> {DefaultLoginPageGeneratingFilter o -> o}
-            1 * objectPostProcessor.postProcess(_ as UsernamePasswordAuthenticationFilter) >> {UsernamePasswordAuthenticationFilter o -> o}
-            1 * objectPostProcessor.postProcess(_ as LoginUrlAuthenticationEntryPoint) >> {LoginUrlAuthenticationEntryPoint o -> o}
-            1 * objectPostProcessor.postProcess(_ as ExceptionTranslationFilter) >> {ExceptionTranslationFilter o -> o}
-    }
+		then: "DefaultLoginPageGeneratingFilter is registered with LifecycleManager"
+			1 * objectPostProcessor.postProcess(_ as DefaultLoginPageGeneratingFilter) >> {DefaultLoginPageGeneratingFilter o -> o}
+			1 * objectPostProcessor.postProcess(_ as UsernamePasswordAuthenticationFilter) >> {UsernamePasswordAuthenticationFilter o -> o}
+			1 * objectPostProcessor.postProcess(_ as LoginUrlAuthenticationEntryPoint) >> {LoginUrlAuthenticationEntryPoint o -> o}
+			1 * objectPostProcessor.postProcess(_ as ExceptionTranslationFilter) >> {ExceptionTranslationFilter o -> o}
+	}
 }

+ 149 - 149
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurerTests.groovy

@@ -46,153 +46,153 @@ import spock.lang.Unroll
  */
 class ExceptionHandlingConfigurerTests extends BaseSpringSpec {
 
-    def "exception ObjectPostProcessor"() {
-        setup: "initialize the AUTH_FILTER as a mock"
-            AnyObjectPostProcessor opp = Mock()
-        when:
-            HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
-            http
-                .exceptionHandling()
-                    .and()
-                .build()
-
-        then: "ExceptionTranslationFilter is registered with LifecycleManager"
-            1 * opp.postProcess(_ as ExceptionTranslationFilter) >> {ExceptionTranslationFilter o -> o}
-    }
-
-    @Unroll
-    def "SEC-2199: defaultEntryPoint for httpBasic and formLogin"(String acceptHeader, int httpStatus) {
-        setup:
-            loadConfig(HttpBasicAndFormLoginEntryPointsConfig)
-        when:
-            request.addHeader("Accept", acceptHeader)
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == httpStatus
-        where:
-            acceptHeader                                 | httpStatus
-            MediaType.APPLICATION_XHTML_XML_VALUE        | HttpServletResponse.SC_MOVED_TEMPORARILY
-            MediaType.IMAGE_GIF_VALUE                    | HttpServletResponse.SC_MOVED_TEMPORARILY
-            MediaType.IMAGE_JPEG_VALUE                   | HttpServletResponse.SC_MOVED_TEMPORARILY
-            MediaType.IMAGE_PNG_VALUE                    | HttpServletResponse.SC_MOVED_TEMPORARILY
-            MediaType.TEXT_HTML_VALUE                    | HttpServletResponse.SC_MOVED_TEMPORARILY
-            MediaType.TEXT_PLAIN_VALUE                   | HttpServletResponse.SC_MOVED_TEMPORARILY
-            MediaType.APPLICATION_ATOM_XML_VALUE         | HttpServletResponse.SC_UNAUTHORIZED
-            MediaType.APPLICATION_FORM_URLENCODED_VALUE  | HttpServletResponse.SC_UNAUTHORIZED
-            MediaType.APPLICATION_JSON_VALUE             | HttpServletResponse.SC_UNAUTHORIZED
-            MediaType.APPLICATION_OCTET_STREAM_VALUE     | HttpServletResponse.SC_UNAUTHORIZED
-            MediaType.APPLICATION_XML_VALUE              | HttpServletResponse.SC_UNAUTHORIZED
-            MediaType.MULTIPART_FORM_DATA_VALUE          | HttpServletResponse.SC_UNAUTHORIZED
-            MediaType.TEXT_XML_VALUE                     | HttpServletResponse.SC_UNAUTHORIZED
-    }
-
-    def "ContentNegotiationStrategy defaults to HeaderContentNegotiationStrategy"() {
-        when:
-            loadConfig(HttpBasicAndFormLoginEntryPointsConfig)
-            DelegatingAuthenticationEntryPoint delegateEntryPoint = findFilter(ExceptionTranslationFilter).authenticationEntryPoint
-        then:
-            delegateEntryPoint.entryPoints.keySet().collect {it.contentNegotiationStrategy.class} == [HeaderContentNegotiationStrategy,HeaderContentNegotiationStrategy]
-    }
-
-    @EnableWebSecurity
-    static class HttpBasicAndFormLoginEntryPointsConfig extends WebSecurityConfigurerAdapter {
-
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER")
-        }
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().authenticated()
-                    .and()
-                .httpBasic()
-                    .and()
-                .formLogin()
-        }
-    }
-
-    def "ContentNegotiationStrategy overrides with @Bean"() {
-        setup:
-            OverrideContentNegotiationStrategySharedObjectConfig.CNS = Mock(ContentNegotiationStrategy)
-        when:
-            loadConfig(OverrideContentNegotiationStrategySharedObjectConfig)
-            DelegatingAuthenticationEntryPoint delegateEntryPoint = findFilter(ExceptionTranslationFilter).authenticationEntryPoint
-        then:
-            delegateEntryPoint.entryPoints.keySet().collect {it.contentNegotiationStrategy} == [OverrideContentNegotiationStrategySharedObjectConfig.CNS,OverrideContentNegotiationStrategySharedObjectConfig.CNS]
-    }
-
-    def "Override ContentNegotiationStrategy with @Bean"() {
-        setup:
-            OverrideContentNegotiationStrategySharedObjectConfig.CNS = Mock(ContentNegotiationStrategy)
-        when:
-            loadConfig(OverrideContentNegotiationStrategySharedObjectConfig)
-        then:
-            context.getBean(OverrideContentNegotiationStrategySharedObjectConfig).http.getSharedObject(ContentNegotiationStrategy) == OverrideContentNegotiationStrategySharedObjectConfig.CNS
-    }
-
-    @EnableWebSecurity
-    static class OverrideContentNegotiationStrategySharedObjectConfig extends WebSecurityConfigurerAdapter {
-        static ContentNegotiationStrategy CNS
-
-        @Bean
-        public ContentNegotiationStrategy cns() {
-            return CNS
-        }
-    }
-
-    def "delegatingAuthenticationEntryPoint.defaultEntryPoint is LoginUrlAuthenticationEntryPoint when using DefaultHttpConf"() {
-        when:
-            loadConfig(DefaultHttpConf)
-        then:
-            findFilter(ExceptionTranslationFilter).authenticationEntryPoint.defaultEntryPoint.class == LoginUrlAuthenticationEntryPoint
-    }
-
-    @EnableWebSecurity
-    static class DefaultHttpConf extends WebSecurityConfigurerAdapter {
-    }
-
-    def "delegatingAuthenticationEntryPoint.defaultEntryPoint is BasicAuthenticationEntryPoint when httpBasic before formLogin"() {
-        when:
-            loadConfig(BasicAuthenticationEntryPointBeforeFormLoginConf)
-        then:
-            findFilter(ExceptionTranslationFilter).authenticationEntryPoint.defaultEntryPoint.defaultEntryPoint.class == BasicAuthenticationEntryPoint
-    }
-
-    @EnableWebSecurity
-    static class BasicAuthenticationEntryPointBeforeFormLoginConf extends WebSecurityConfigurerAdapter {
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .httpBasic()
-                    .and()
-                .formLogin()
-        }
-    }
-
-    def "invoke exceptionHandling twice does not override"() {
-        setup:
-            InvokeTwiceDoesNotOverrideConfig.AEP = Mock(AuthenticationEntryPoint)
-        when:
-            loadConfig(InvokeTwiceDoesNotOverrideConfig)
-        then:
-            findFilter(ExceptionTranslationFilter).authenticationEntryPoint == InvokeTwiceDoesNotOverrideConfig.AEP
-    }
-
-    @EnableWebSecurity
-    static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
-        static AuthenticationEntryPoint AEP
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .exceptionHandling()
-                    .authenticationEntryPoint(AEP)
-                    .and()
-                .exceptionHandling()
-        }
-    }
+	def "exception ObjectPostProcessor"() {
+		setup: "initialize the AUTH_FILTER as a mock"
+			AnyObjectPostProcessor opp = Mock()
+		when:
+			HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
+			http
+				.exceptionHandling()
+					.and()
+				.build()
+
+		then: "ExceptionTranslationFilter is registered with LifecycleManager"
+			1 * opp.postProcess(_ as ExceptionTranslationFilter) >> {ExceptionTranslationFilter o -> o}
+	}
+
+	@Unroll
+	def "SEC-2199: defaultEntryPoint for httpBasic and formLogin"(String acceptHeader, int httpStatus) {
+		setup:
+			loadConfig(HttpBasicAndFormLoginEntryPointsConfig)
+		when:
+			request.addHeader("Accept", acceptHeader)
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == httpStatus
+		where:
+			acceptHeader                                 | httpStatus
+			MediaType.APPLICATION_XHTML_XML_VALUE        | HttpServletResponse.SC_MOVED_TEMPORARILY
+			MediaType.IMAGE_GIF_VALUE                    | HttpServletResponse.SC_MOVED_TEMPORARILY
+			MediaType.IMAGE_JPEG_VALUE                   | HttpServletResponse.SC_MOVED_TEMPORARILY
+			MediaType.IMAGE_PNG_VALUE                    | HttpServletResponse.SC_MOVED_TEMPORARILY
+			MediaType.TEXT_HTML_VALUE                    | HttpServletResponse.SC_MOVED_TEMPORARILY
+			MediaType.TEXT_PLAIN_VALUE                   | HttpServletResponse.SC_MOVED_TEMPORARILY
+			MediaType.APPLICATION_ATOM_XML_VALUE         | HttpServletResponse.SC_UNAUTHORIZED
+			MediaType.APPLICATION_FORM_URLENCODED_VALUE  | HttpServletResponse.SC_UNAUTHORIZED
+			MediaType.APPLICATION_JSON_VALUE             | HttpServletResponse.SC_UNAUTHORIZED
+			MediaType.APPLICATION_OCTET_STREAM_VALUE     | HttpServletResponse.SC_UNAUTHORIZED
+			MediaType.APPLICATION_XML_VALUE              | HttpServletResponse.SC_UNAUTHORIZED
+			MediaType.MULTIPART_FORM_DATA_VALUE          | HttpServletResponse.SC_UNAUTHORIZED
+			MediaType.TEXT_XML_VALUE                     | HttpServletResponse.SC_UNAUTHORIZED
+	}
+
+	def "ContentNegotiationStrategy defaults to HeaderContentNegotiationStrategy"() {
+		when:
+			loadConfig(HttpBasicAndFormLoginEntryPointsConfig)
+			DelegatingAuthenticationEntryPoint delegateEntryPoint = findFilter(ExceptionTranslationFilter).authenticationEntryPoint
+		then:
+			delegateEntryPoint.entryPoints.keySet().collect {it.contentNegotiationStrategy.class} == [HeaderContentNegotiationStrategy,HeaderContentNegotiationStrategy]
+	}
+
+	@EnableWebSecurity
+	static class HttpBasicAndFormLoginEntryPointsConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER")
+		}
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().authenticated()
+					.and()
+				.httpBasic()
+					.and()
+				.formLogin()
+		}
+	}
+
+	def "ContentNegotiationStrategy overrides with @Bean"() {
+		setup:
+			OverrideContentNegotiationStrategySharedObjectConfig.CNS = Mock(ContentNegotiationStrategy)
+		when:
+			loadConfig(OverrideContentNegotiationStrategySharedObjectConfig)
+			DelegatingAuthenticationEntryPoint delegateEntryPoint = findFilter(ExceptionTranslationFilter).authenticationEntryPoint
+		then:
+			delegateEntryPoint.entryPoints.keySet().collect {it.contentNegotiationStrategy} == [OverrideContentNegotiationStrategySharedObjectConfig.CNS,OverrideContentNegotiationStrategySharedObjectConfig.CNS]
+	}
+
+	def "Override ContentNegotiationStrategy with @Bean"() {
+		setup:
+			OverrideContentNegotiationStrategySharedObjectConfig.CNS = Mock(ContentNegotiationStrategy)
+		when:
+			loadConfig(OverrideContentNegotiationStrategySharedObjectConfig)
+		then:
+			context.getBean(OverrideContentNegotiationStrategySharedObjectConfig).http.getSharedObject(ContentNegotiationStrategy) == OverrideContentNegotiationStrategySharedObjectConfig.CNS
+	}
+
+	@EnableWebSecurity
+	static class OverrideContentNegotiationStrategySharedObjectConfig extends WebSecurityConfigurerAdapter {
+		static ContentNegotiationStrategy CNS
+
+		@Bean
+		public ContentNegotiationStrategy cns() {
+			return CNS
+		}
+	}
+
+	def "delegatingAuthenticationEntryPoint.defaultEntryPoint is LoginUrlAuthenticationEntryPoint when using DefaultHttpConf"() {
+		when:
+			loadConfig(DefaultHttpConf)
+		then:
+			findFilter(ExceptionTranslationFilter).authenticationEntryPoint.defaultEntryPoint.class == LoginUrlAuthenticationEntryPoint
+	}
+
+	@EnableWebSecurity
+	static class DefaultHttpConf extends WebSecurityConfigurerAdapter {
+	}
+
+	def "delegatingAuthenticationEntryPoint.defaultEntryPoint is BasicAuthenticationEntryPoint when httpBasic before formLogin"() {
+		when:
+			loadConfig(BasicAuthenticationEntryPointBeforeFormLoginConf)
+		then:
+			findFilter(ExceptionTranslationFilter).authenticationEntryPoint.defaultEntryPoint.defaultEntryPoint.class == BasicAuthenticationEntryPoint
+	}
+
+	@EnableWebSecurity
+	static class BasicAuthenticationEntryPointBeforeFormLoginConf extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.httpBasic()
+					.and()
+				.formLogin()
+		}
+	}
+
+	def "invoke exceptionHandling twice does not override"() {
+		setup:
+			InvokeTwiceDoesNotOverrideConfig.AEP = Mock(AuthenticationEntryPoint)
+		when:
+			loadConfig(InvokeTwiceDoesNotOverrideConfig)
+		then:
+			findFilter(ExceptionTranslationFilter).authenticationEntryPoint == InvokeTwiceDoesNotOverrideConfig.AEP
+	}
+
+	@EnableWebSecurity
+	static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
+		static AuthenticationEntryPoint AEP
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.exceptionHandling()
+					.authenticationEntryPoint(AEP)
+					.and()
+				.exceptionHandling()
+		}
+	}
 }

+ 490 - 490
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationsTests.groovy

@@ -37,494 +37,494 @@ import org.springframework.security.web.access.intercept.FilterSecurityIntercept
 
 public class ExpressionUrlAuthorizationConfigurerTests extends BaseSpringSpec {
 
-    def "hasAnyAuthority('ROLE_USER')"() {
-        when:
-            def expression = ExpressionUrlAuthorizationConfigurer.hasAnyAuthority("ROLE_USER")
-        then:
-            expression == "hasAnyAuthority('ROLE_USER')"
-    }
-
-    def "hasAnyAuthority('ROLE_USER','ROLE_ADMIN')"() {
-        when:
-            def expression = ExpressionUrlAuthorizationConfigurer.hasAnyAuthority("ROLE_USER","ROLE_ADMIN")
-        then:
-            expression == "hasAnyAuthority('ROLE_USER','ROLE_ADMIN')"
-    }
-
-    def "hasAnyRole('USER')"() {
-        when:
-            def expression = ExpressionUrlAuthorizationConfigurer.hasAnyRole("USER")
-        then:
-            expression == "hasAnyRole('ROLE_USER')"
-    }
-
-    def "hasAnyRole('USER','ADMIN')"() {
-        when:
-            def expression = ExpressionUrlAuthorizationConfigurer.hasAnyRole("USER","ADMIN")
-        then:
-            expression == "hasAnyRole('ROLE_USER','ROLE_ADMIN')"
-    }
-
-    def "hasRole('ROLE_USER') is rejected due to starting with ROLE_"() {
-        when:
-            def expression = ExpressionUrlAuthorizationConfigurer.hasRole("ROLE_USER")
-        then:
-            IllegalArgumentException e = thrown()
-            e.message == "role should not start with 'ROLE_' since it is automatically inserted. Got 'ROLE_USER'"
-    }
-
-    def "authorizeRequests() uses AffirmativeBased AccessDecisionManager"() {
-        when: "Load Config with no specific AccessDecisionManager"
-            loadConfig(NoSpecificAccessDecessionManagerConfig)
-        then: "AccessDecessionManager matches the HttpSecurityBuilder's default"
-            findFilter(FilterSecurityInterceptor).accessDecisionManager.class == AffirmativeBased
-    }
-
-    @EnableWebSecurity
-    static class NoSpecificAccessDecessionManagerConfig extends WebSecurityConfigurerAdapter {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-        }
-    }
-
-    def "authorizeRequests() no requests"() {
-        when: "Load Config with no requests"
-            loadConfig(NoRequestsConfig)
-        then: "A meaningful exception is thrown"
-            BeanCreationException success = thrown()
-            success.message.contains "At least one mapping is required (i.e. authorizeRequests().anyRequest.authenticated())"
-    }
-
-    @EnableWebSecurity
-    static class NoRequestsConfig extends WebSecurityConfigurerAdapter {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-        }
-    }
-
-    def "authorizeRequests() incomplete mapping"() {
-        when: "Load Config with incomplete mapping"
-            loadConfig(IncompleteMappingConfig)
-        then: "A meaningful exception is thrown"
-            BeanCreationException success = thrown()
-            success.message.contains "An incomplete mapping was found for "
-    }
-
-    @EnableWebSecurity
-    static class IncompleteMappingConfig extends WebSecurityConfigurerAdapter {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .antMatchers("/a").authenticated()
-                    .anyRequest()
-        }
-    }
-
-    def "authorizeRequests() hasAuthority"() {
-        setup:
-            loadConfig(HasAuthorityConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_UNAUTHORIZED
-        when:
-            super.setup()
-            login()
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_OK
-        when:
-            super.setup()
-            login("user","ROLE_INVALID")
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_FORBIDDEN
-    }
-
-    @EnableWebSecurity
-    static class HasAuthorityConfig extends WebSecurityConfigurerAdapter {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .httpBasic()
-                    .and()
-                .authorizeRequests()
-                    .anyRequest().hasAuthority("ROLE_USER")
-        }
-    }
-
-    def "authorizeRequests() hasAnyAuthority"() {
-        setup:
-            loadConfig(HasAnyAuthorityConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_UNAUTHORIZED
-        when:
-            super.setup()
-            login("user","ROLE_ADMIN")
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_OK
-        when:
-            super.setup()
-            login("user","ROLE_DBA")
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_OK
-        when:
-            super.setup()
-            login("user","ROLE_INVALID")
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_FORBIDDEN
-    }
-
-    @EnableWebSecurity
-    static class HasAnyAuthorityConfig extends WebSecurityConfigurerAdapter {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .httpBasic()
-                    .and()
-                .authorizeRequests()
-                    .anyRequest().hasAnyAuthority("ROLE_ADMIN","ROLE_DBA")
-        }
-    }
-
-    def "authorizeRequests() hasIpAddress"() {
-        setup:
-            loadConfig(HasIpAddressConfig)
-        when:
-            request.remoteAddr = "192.168.1.1"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_UNAUTHORIZED
-        when:
-            super.setup()
-            request.remoteAddr = "192.168.1.0"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_OK
-    }
-
-    @EnableWebSecurity
-    static class HasIpAddressConfig extends WebSecurityConfigurerAdapter {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .httpBasic()
-                    .and()
-                .authorizeRequests()
-                    .anyRequest().hasIpAddress("192.168.1.0")
-        }
-    }
-
-    def "authorizeRequests() anonymous"() {
-        setup:
-            loadConfig(AnonymousConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_OK
-        when:
-            super.setup()
-            login()
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_FORBIDDEN
-    }
-
-    @EnableWebSecurity
-    static class AnonymousConfig extends WebSecurityConfigurerAdapter {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .httpBasic()
-                    .and()
-                .authorizeRequests()
-                    .anyRequest().anonymous()
-        }
-    }
-
-    def "authorizeRequests() rememberMe"() {
-        setup:
-            loadConfig(RememberMeConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_UNAUTHORIZED
-        when:
-            super.setup()
-            login(new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_OK
-    }
-
-    @EnableWebSecurity
-    static class RememberMeConfig extends WebSecurityConfigurerAdapter {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .rememberMe()
-                    .and()
-                .httpBasic()
-                    .and()
-                .authorizeRequests()
-                    .anyRequest().rememberMe()
-        }
-
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER")
-        }
-    }
-
-    def "authorizeRequests() denyAll"() {
-        setup:
-            loadConfig(DenyAllConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_UNAUTHORIZED
-        when:
-            super.setup()
-            login(new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_FORBIDDEN
-    }
-
-    @EnableWebSecurity
-    static class DenyAllConfig extends WebSecurityConfigurerAdapter {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .httpBasic()
-                    .and()
-                .authorizeRequests()
-                    .anyRequest().denyAll()
-        }
-    }
-
-    def "authorizeRequests() not denyAll"() {
-        setup:
-            loadConfig(NotDenyAllConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_OK
-        when:
-            super.setup()
-            login(new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_OK
-    }
-
-    @EnableWebSecurity
-    static class NotDenyAllConfig extends WebSecurityConfigurerAdapter {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .httpBasic()
-                    .and()
-                .authorizeRequests()
-                    .anyRequest().not().denyAll()
-        }
-    }
-
-    def "authorizeRequests() fullyAuthenticated"() {
-        setup:
-            loadConfig(FullyAuthenticatedConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_UNAUTHORIZED
-        when:
-            super.setup()
-            login(new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_FORBIDDEN
-        when:
-            super.setup()
-            login()
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_OK
-    }
-
-    @EnableWebSecurity
-    static class FullyAuthenticatedConfig extends WebSecurityConfigurerAdapter {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .rememberMe()
-                    .and()
-                .httpBasic()
-                    .and()
-                .authorizeRequests()
-                    .anyRequest().fullyAuthenticated()
-        }
-
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER")
-        }
-    }
-
-    def "authorizeRequests() access"() {
-        setup:
-            loadConfig(AccessConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "Access is granted due to GET"
-            response.status == HttpServletResponse.SC_OK
-        when:
-            super.setup()
-            login()
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "Access is granted due to role"
-            response.status == HttpServletResponse.SC_OK
-        when:
-            super.setup()
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "Access is denied"
-            response.status == HttpServletResponse.SC_UNAUTHORIZED
-    }
-
-    @EnableWebSecurity
-    static class AccessConfig extends WebSecurityConfigurerAdapter {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .rememberMe()
-                    .and()
-                .httpBasic()
-                    .and()
-                .authorizeRequests()
-                    .anyRequest().access("hasRole('ROLE_USER') or request.method == 'GET'")
-        }
-
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER")
-        }
-    }
-
-
-    def "invoke authorizeUrls twice does not reset"() {
-        setup:
-            loadConfig(InvokeTwiceDoesNotResetConfig)
-        when:
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "Access is denied"
-            response.status == HttpServletResponse.SC_UNAUTHORIZED
-    }
-
-    @EnableWebSecurity
-    static class InvokeTwiceDoesNotResetConfig extends WebSecurityConfigurerAdapter {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .httpBasic()
-                    .and()
-                .authorizeRequests()
-                    .anyRequest().authenticated()
-                    .and()
-                .authorizeRequests()
-        }
-
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-        }
-    }
-
-    def "All Properties are accessible and chain properly"() {
-        when:
-            loadConfig(AllPropertiesWorkConfig)
-        then:
-            noExceptionThrown()
-    }
-
-    def "AuthorizedRequests withPostProcessor"() {
-        setup:
-            ApplicationListener al = Mock()
-            AuthorizedRequestsWithPostProcessorConfig.AL = al
-            loadConfig(AuthorizedRequestsWithPostProcessorConfig)
-        when:
-            springSecurityFilterChain.doFilter(request, response, chain)
-        then:
-            1 * al.onApplicationEvent(_ as AuthorizedEvent)
-    }
-
-    def "Use @permission.check in access"() {
-        setup:
-            loadConfig(UseBeansInExpressions)
-        when: "invoke standard expression that denies access"
-            login()
-            request.servletPath = "/admin/1"
-            springSecurityFilterChain.doFilter(request, response, chain)
-        then: "standard expression works - get forbidden"
-            response.status == HttpServletResponse.SC_FORBIDDEN
-        when: "invoke standard expression that allows access"
-            super.setup()
-            login()
-            request.servletPath = "/user/1"
-            springSecurityFilterChain.doFilter(request, response, chain)
-        then: "standard expression works - get ok"
-            response.status == HttpServletResponse.SC_OK
-        when: "invoke custom bean as expression that allows access"
-            super.setup()
-            login()
-            request.servletPath = "/allow/1"
-            springSecurityFilterChain.doFilter(request, response, chain)
-        then: "custom bean expression allows access"
-            response.status == HttpServletResponse.SC_OK
-        when: "invoke custom bean as expression that denies access"
-            super.setup()
-            login()
-            request.servletPath = "/deny/1"
-            springSecurityFilterChain.doFilter(request, response, chain)
-        then: "custom bean expression denies access"
-            response.status == HttpServletResponse.SC_FORBIDDEN
-    }
-
-    def "Use custom expressionroot in access"() {
-        setup:
-            loadConfig(CustomExpressionRootConfig)
-        when: "invoke standard expression that denies access"
-            login()
-            request.servletPath = "/admin/1"
-            springSecurityFilterChain.doFilter(request, response, chain)
-        then: "standard expression works - get forbidden"
-            response.status == HttpServletResponse.SC_FORBIDDEN
-        when: "invoke standard expression that allows access"
-            super.setup()
-            login()
-            request.servletPath = "/user/1"
-            springSecurityFilterChain.doFilter(request, response, chain)
-        then: "standard expression works - get ok"
-            response.status == HttpServletResponse.SC_OK
-        when: "invoke custom bean as expression that allows access"
-            super.setup()
-            login()
-            request.servletPath = "/allow/1"
-            springSecurityFilterChain.doFilter(request, response, chain)
-        then: "custom bean expression allows access"
-            response.status == HttpServletResponse.SC_OK
-        when: "invoke custom bean as expression that denies access"
-            super.setup()
-            login()
-            request.servletPath = "/deny/1"
-            springSecurityFilterChain.doFilter(request, response, chain)
-        then: "custom bean expression denies access"
-            response.status == HttpServletResponse.SC_FORBIDDEN
-    }
+	def "hasAnyAuthority('ROLE_USER')"() {
+		when:
+			def expression = ExpressionUrlAuthorizationConfigurer.hasAnyAuthority("ROLE_USER")
+		then:
+			expression == "hasAnyAuthority('ROLE_USER')"
+	}
+
+	def "hasAnyAuthority('ROLE_USER','ROLE_ADMIN')"() {
+		when:
+			def expression = ExpressionUrlAuthorizationConfigurer.hasAnyAuthority("ROLE_USER","ROLE_ADMIN")
+		then:
+			expression == "hasAnyAuthority('ROLE_USER','ROLE_ADMIN')"
+	}
+
+	def "hasAnyRole('USER')"() {
+		when:
+			def expression = ExpressionUrlAuthorizationConfigurer.hasAnyRole("USER")
+		then:
+			expression == "hasAnyRole('ROLE_USER')"
+	}
+
+	def "hasAnyRole('USER','ADMIN')"() {
+		when:
+			def expression = ExpressionUrlAuthorizationConfigurer.hasAnyRole("USER","ADMIN")
+		then:
+			expression == "hasAnyRole('ROLE_USER','ROLE_ADMIN')"
+	}
+
+	def "hasRole('ROLE_USER') is rejected due to starting with ROLE_"() {
+		when:
+			def expression = ExpressionUrlAuthorizationConfigurer.hasRole("ROLE_USER")
+		then:
+			IllegalArgumentException e = thrown()
+			e.message == "role should not start with 'ROLE_' since it is automatically inserted. Got 'ROLE_USER'"
+	}
+
+	def "authorizeRequests() uses AffirmativeBased AccessDecisionManager"() {
+		when: "Load Config with no specific AccessDecisionManager"
+			loadConfig(NoSpecificAccessDecessionManagerConfig)
+		then: "AccessDecessionManager matches the HttpSecurityBuilder's default"
+			findFilter(FilterSecurityInterceptor).accessDecisionManager.class == AffirmativeBased
+	}
+
+	@EnableWebSecurity
+	static class NoSpecificAccessDecessionManagerConfig extends WebSecurityConfigurerAdapter {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+		}
+	}
+
+	def "authorizeRequests() no requests"() {
+		when: "Load Config with no requests"
+			loadConfig(NoRequestsConfig)
+		then: "A meaningful exception is thrown"
+			BeanCreationException success = thrown()
+			success.message.contains "At least one mapping is required (i.e. authorizeRequests().anyRequest.authenticated())"
+	}
+
+	@EnableWebSecurity
+	static class NoRequestsConfig extends WebSecurityConfigurerAdapter {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+		}
+	}
+
+	def "authorizeRequests() incomplete mapping"() {
+		when: "Load Config with incomplete mapping"
+			loadConfig(IncompleteMappingConfig)
+		then: "A meaningful exception is thrown"
+			BeanCreationException success = thrown()
+			success.message.contains "An incomplete mapping was found for "
+	}
+
+	@EnableWebSecurity
+	static class IncompleteMappingConfig extends WebSecurityConfigurerAdapter {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.antMatchers("/a").authenticated()
+					.anyRequest()
+		}
+	}
+
+	def "authorizeRequests() hasAuthority"() {
+		setup:
+			loadConfig(HasAuthorityConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_UNAUTHORIZED
+		when:
+			super.setup()
+			login()
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_OK
+		when:
+			super.setup()
+			login("user","ROLE_INVALID")
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_FORBIDDEN
+	}
+
+	@EnableWebSecurity
+	static class HasAuthorityConfig extends WebSecurityConfigurerAdapter {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.httpBasic()
+					.and()
+				.authorizeRequests()
+					.anyRequest().hasAuthority("ROLE_USER")
+		}
+	}
+
+	def "authorizeRequests() hasAnyAuthority"() {
+		setup:
+			loadConfig(HasAnyAuthorityConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_UNAUTHORIZED
+		when:
+			super.setup()
+			login("user","ROLE_ADMIN")
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_OK
+		when:
+			super.setup()
+			login("user","ROLE_DBA")
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_OK
+		when:
+			super.setup()
+			login("user","ROLE_INVALID")
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_FORBIDDEN
+	}
+
+	@EnableWebSecurity
+	static class HasAnyAuthorityConfig extends WebSecurityConfigurerAdapter {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.httpBasic()
+					.and()
+				.authorizeRequests()
+					.anyRequest().hasAnyAuthority("ROLE_ADMIN","ROLE_DBA")
+		}
+	}
+
+	def "authorizeRequests() hasIpAddress"() {
+		setup:
+			loadConfig(HasIpAddressConfig)
+		when:
+			request.remoteAddr = "192.168.1.1"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_UNAUTHORIZED
+		when:
+			super.setup()
+			request.remoteAddr = "192.168.1.0"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_OK
+	}
+
+	@EnableWebSecurity
+	static class HasIpAddressConfig extends WebSecurityConfigurerAdapter {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.httpBasic()
+					.and()
+				.authorizeRequests()
+					.anyRequest().hasIpAddress("192.168.1.0")
+		}
+	}
+
+	def "authorizeRequests() anonymous"() {
+		setup:
+			loadConfig(AnonymousConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_OK
+		when:
+			super.setup()
+			login()
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_FORBIDDEN
+	}
+
+	@EnableWebSecurity
+	static class AnonymousConfig extends WebSecurityConfigurerAdapter {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.httpBasic()
+					.and()
+				.authorizeRequests()
+					.anyRequest().anonymous()
+		}
+	}
+
+	def "authorizeRequests() rememberMe"() {
+		setup:
+			loadConfig(RememberMeConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_UNAUTHORIZED
+		when:
+			super.setup()
+			login(new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_OK
+	}
+
+	@EnableWebSecurity
+	static class RememberMeConfig extends WebSecurityConfigurerAdapter {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.rememberMe()
+					.and()
+				.httpBasic()
+					.and()
+				.authorizeRequests()
+					.anyRequest().rememberMe()
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER")
+		}
+	}
+
+	def "authorizeRequests() denyAll"() {
+		setup:
+			loadConfig(DenyAllConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_UNAUTHORIZED
+		when:
+			super.setup()
+			login(new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_FORBIDDEN
+	}
+
+	@EnableWebSecurity
+	static class DenyAllConfig extends WebSecurityConfigurerAdapter {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.httpBasic()
+					.and()
+				.authorizeRequests()
+					.anyRequest().denyAll()
+		}
+	}
+
+	def "authorizeRequests() not denyAll"() {
+		setup:
+			loadConfig(NotDenyAllConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_OK
+		when:
+			super.setup()
+			login(new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_OK
+	}
+
+	@EnableWebSecurity
+	static class NotDenyAllConfig extends WebSecurityConfigurerAdapter {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.httpBasic()
+					.and()
+				.authorizeRequests()
+					.anyRequest().not().denyAll()
+		}
+	}
+
+	def "authorizeRequests() fullyAuthenticated"() {
+		setup:
+			loadConfig(FullyAuthenticatedConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_UNAUTHORIZED
+		when:
+			super.setup()
+			login(new RememberMeAuthenticationToken("key", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_FORBIDDEN
+		when:
+			super.setup()
+			login()
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_OK
+	}
+
+	@EnableWebSecurity
+	static class FullyAuthenticatedConfig extends WebSecurityConfigurerAdapter {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.rememberMe()
+					.and()
+				.httpBasic()
+					.and()
+				.authorizeRequests()
+					.anyRequest().fullyAuthenticated()
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER")
+		}
+	}
+
+	def "authorizeRequests() access"() {
+		setup:
+			loadConfig(AccessConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "Access is granted due to GET"
+			response.status == HttpServletResponse.SC_OK
+		when:
+			super.setup()
+			login()
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "Access is granted due to role"
+			response.status == HttpServletResponse.SC_OK
+		when:
+			super.setup()
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "Access is denied"
+			response.status == HttpServletResponse.SC_UNAUTHORIZED
+	}
+
+	@EnableWebSecurity
+	static class AccessConfig extends WebSecurityConfigurerAdapter {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.rememberMe()
+					.and()
+				.httpBasic()
+					.and()
+				.authorizeRequests()
+					.anyRequest().access("hasRole('ROLE_USER') or request.method == 'GET'")
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER")
+		}
+	}
+
+
+	def "invoke authorizeUrls twice does not reset"() {
+		setup:
+			loadConfig(InvokeTwiceDoesNotResetConfig)
+		when:
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "Access is denied"
+			response.status == HttpServletResponse.SC_UNAUTHORIZED
+	}
+
+	@EnableWebSecurity
+	static class InvokeTwiceDoesNotResetConfig extends WebSecurityConfigurerAdapter {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.httpBasic()
+					.and()
+				.authorizeRequests()
+					.anyRequest().authenticated()
+					.and()
+				.authorizeRequests()
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+		}
+	}
+
+	def "All Properties are accessible and chain properly"() {
+		when:
+			loadConfig(AllPropertiesWorkConfig)
+		then:
+			noExceptionThrown()
+	}
+
+	def "AuthorizedRequests withPostProcessor"() {
+		setup:
+			ApplicationListener al = Mock()
+			AuthorizedRequestsWithPostProcessorConfig.AL = al
+			loadConfig(AuthorizedRequestsWithPostProcessorConfig)
+		when:
+			springSecurityFilterChain.doFilter(request, response, chain)
+		then:
+			1 * al.onApplicationEvent(_ as AuthorizedEvent)
+	}
+
+	def "Use @permission.check in access"() {
+		setup:
+			loadConfig(UseBeansInExpressions)
+		when: "invoke standard expression that denies access"
+			login()
+			request.servletPath = "/admin/1"
+			springSecurityFilterChain.doFilter(request, response, chain)
+		then: "standard expression works - get forbidden"
+			response.status == HttpServletResponse.SC_FORBIDDEN
+		when: "invoke standard expression that allows access"
+			super.setup()
+			login()
+			request.servletPath = "/user/1"
+			springSecurityFilterChain.doFilter(request, response, chain)
+		then: "standard expression works - get ok"
+			response.status == HttpServletResponse.SC_OK
+		when: "invoke custom bean as expression that allows access"
+			super.setup()
+			login()
+			request.servletPath = "/allow/1"
+			springSecurityFilterChain.doFilter(request, response, chain)
+		then: "custom bean expression allows access"
+			response.status == HttpServletResponse.SC_OK
+		when: "invoke custom bean as expression that denies access"
+			super.setup()
+			login()
+			request.servletPath = "/deny/1"
+			springSecurityFilterChain.doFilter(request, response, chain)
+		then: "custom bean expression denies access"
+			response.status == HttpServletResponse.SC_FORBIDDEN
+	}
+
+	def "Use custom expressionroot in access"() {
+		setup:
+			loadConfig(CustomExpressionRootConfig)
+		when: "invoke standard expression that denies access"
+			login()
+			request.servletPath = "/admin/1"
+			springSecurityFilterChain.doFilter(request, response, chain)
+		then: "standard expression works - get forbidden"
+			response.status == HttpServletResponse.SC_FORBIDDEN
+		when: "invoke standard expression that allows access"
+			super.setup()
+			login()
+			request.servletPath = "/user/1"
+			springSecurityFilterChain.doFilter(request, response, chain)
+		then: "standard expression works - get ok"
+			response.status == HttpServletResponse.SC_OK
+		when: "invoke custom bean as expression that allows access"
+			super.setup()
+			login()
+			request.servletPath = "/allow/1"
+			springSecurityFilterChain.doFilter(request, response, chain)
+		then: "custom bean expression allows access"
+			response.status == HttpServletResponse.SC_OK
+		when: "invoke custom bean as expression that denies access"
+			super.setup()
+			login()
+			request.servletPath = "/deny/1"
+			springSecurityFilterChain.doFilter(request, response, chain)
+		then: "custom bean expression denies access"
+			response.status == HttpServletResponse.SC_FORBIDDEN
+	}
 }

+ 262 - 262
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurerTests.groovy

@@ -56,266 +56,266 @@ import spock.lang.Unroll
  * @author Rob Winch
  */
 class FormLoginConfigurerTests extends BaseSpringSpec {
-    def "Form Login"() {
-        when: "load formLogin()"
-            context = new AnnotationConfigApplicationContext(FormLoginConfig)
-
-        then: "FilterChains configured correctly"
-            def filterChains = filterChains()
-            filterChains.size() == 2
-            filterChains[0].requestMatcher.pattern == '/resources/**'
-            filterChains[0].filters.empty
-            filterChains[1].requestMatcher instanceof AnyRequestMatcher
-            filterChains[1].filters.collect { it.class.name.contains('$') ? it.class.superclass : it.class } ==
-                    [WebAsyncManagerIntegrationFilter, SecurityContextPersistenceFilter, HeaderWriterFilter, CsrfFilter, LogoutFilter, UsernamePasswordAuthenticationFilter,
-                     RequestCacheAwareFilter, SecurityContextHolderAwareRequestFilter,
-                     AnonymousAuthenticationFilter, SessionManagementFilter, ExceptionTranslationFilter, FilterSecurityInterceptor ]
-
-        and: "UsernamePasswordAuthentictionFilter is configured correctly"
-            UsernamePasswordAuthenticationFilter authFilter = findFilter(UsernamePasswordAuthenticationFilter,1)
-            authFilter.usernameParameter == "username"
-            authFilter.passwordParameter == "password"
-            authFilter.failureHandler.defaultFailureUrl == "/login?error"
-            authFilter.successHandler.defaultTargetUrl == "/"
-            authFilter.requiresAuthentication(new MockHttpServletRequest(servletPath : "/login", method: "POST"), new MockHttpServletResponse())
-            !authFilter.requiresAuthentication(new MockHttpServletRequest(servletPath : "/login", method: "GET"), new MockHttpServletResponse())
-
-        and: "SessionFixationProtectionStrategy is configured correctly"
-            SessionFixationProtectionStrategy sessionStrategy = ReflectionTestUtils.getField(authFilter,"sessionStrategy").delegateStrategies.find { SessionFixationProtectionStrategy }
-            sessionStrategy.migrateSessionAttributes
-
-        and: "Exception handling is configured correctly"
-            AuthenticationEntryPoint authEntryPoint = filterChains[1].filters.find { it instanceof ExceptionTranslationFilter}.authenticationEntryPoint
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            authEntryPoint.commence(new MockHttpServletRequest(servletPath: "/private/"), response, new BadCredentialsException(""))
-            response.redirectedUrl == "http://localhost/login"
-    }
-
-    @EnableWebSecurity
-    static class FormLoginConfig extends BaseWebConfig {
-        @Override
-        public void configure(WebSecurity web)	throws Exception {
-            web
-                .ignoring()
-                    .antMatchers("/resources/**");
-        }
-
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .formLogin()
-                    .loginPage("/login")
-        }
-    }
-
-    def "FormLogin.permitAll()"() {
-        when: "load formLogin() with permitAll"
-            context = new AnnotationConfigApplicationContext(FormLoginConfigPermitAll)
-            FilterChainProxy filterChain = context.getBean(FilterChainProxy)
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            request = new MockHttpServletRequest(servletPath : servletPath, requestURI: servletPath, queryString: query, method: method)
-            setupCsrf()
-
-        then: "the formLogin URLs are granted access"
-            filterChain.doFilter(request, response, new MockFilterChain())
-            response.redirectedUrl == redirectUrl
-
-        where:
-            servletPath | method | query | redirectUrl
-            "/login" | "GET" | null | null
-            "/login" | "POST" | null | "/login?error"
-            "/login" | "GET" | "error" | null
-    }
-
-    @EnableWebSecurity
-    static class FormLoginConfigPermitAll extends BaseWebConfig {
-
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .formLogin()
-                    .permitAll()
-        }
-    }
-
-    @Unroll
-    def "FormLogin loginConventions changes defaults"() {
-        when: "load formLogin() with permitAll"
-            loadConfig(FormLoginDefaultsConfig)
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            request = new MockHttpServletRequest(servletPath : servletPath, requestURI: servletPath, queryString: query, method: method)
-            setupCsrf()
-
-        then: "the other default login/logout URLs are updated and granted access"
-            springSecurityFilterChain.doFilter(request, response, new MockFilterChain())
-            response.redirectedUrl == redirectUrl
-
-        where:
-            servletPath     | method | query | redirectUrl
-            "/authenticate" | "GET"  | null    | null
-            "/authenticate" | "POST" | null    | "/authenticate?error"
-            "/authenticate" | "GET"  | "error" | null
-            "/logout"       | "POST" | null    | "/authenticate?logout"
-            "/authenticate" | "GET"  | "logout"| null
-    }
-
-    @EnableWebSecurity
-    static class FormLoginDefaultsConfig extends BaseWebConfig {
-
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .formLogin()
-                    .loginPage("/authenticate")
-                    .permitAll()
-                    .and()
-                .logout()
-                    .permitAll()
-        }
-    }
-
-    def "FormLogin loginProcessingUrl"() {
-        setup:
-            loadConfig(FormLoginLoginProcessingUrlConfig)
-            request.servletPath = "/loginCheck"
-            request.method = "POST"
-            request.parameters.username = ["user"] as String[]
-            request.parameters.password = ["password"] as String[]
-        when:
-            springSecurityFilterChain.doFilter(request, response, new MockFilterChain())
-        then:
-            response.redirectedUrl == "/"
-    }
-
-    @EnableWebSecurity
-    static class FormLoginLoginProcessingUrlConfig extends BaseWebConfig {
-
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().authenticated()
-                    .and()
-                .formLogin()
-                    .loginProcessingUrl("/loginCheck")
-                    .loginPage("/login")
-                    //.failureUrl("/loginFailure")
-                    .defaultSuccessUrl("/", true)
-                    .passwordParameter("password")
-                    .usernameParameter("username")
-                    .permitAll()
-                    .and()
-                .logout()
-                    .logoutSuccessUrl("/login")
-                    .logoutUrl("/logout")
-                    .deleteCookies("JSESSIONID")
-        }
-    }
-
-    def "FormLogin uses PortMapper"() {
-        when: "load formLogin() with permitAll"
-            FormLoginUsesPortMapperConfig.PORT_MAPPER = Mock(PortMapper)
-            loadConfig(FormLoginUsesPortMapperConfig)
-        then: "the formLogin URLs are granted access"
-            findFilter(ExceptionTranslationFilter).authenticationEntryPoint.portMapper == FormLoginUsesPortMapperConfig.PORT_MAPPER
-    }
-
-    @EnableWebSecurity
-    static class FormLoginUsesPortMapperConfig extends BaseWebConfig {
-        static PortMapper PORT_MAPPER
-
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .formLogin()
-                    .permitAll()
-                    .and()
-                .portMapper()
-                    .portMapper(PORT_MAPPER)
-        }
-    }
-
-    def "FormLogin permitAll ignores failureUrl when failureHandler set"() {
-        setup:
-            PermitAllIgnoresFailureHandlerConfig.FAILURE_HANDLER = Mock(AuthenticationFailureHandler)
-            loadConfig(PermitAllIgnoresFailureHandlerConfig)
-            FilterChainProxy springSecurityFilterChain = context.getBean(FilterChainProxy)
-        when: "access default failureUrl and configured explicit FailureHandler"
-            MockHttpServletRequest request = new MockHttpServletRequest(servletPath:"/login",requestURI:"/login",queryString:"error",method:"GET")
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            springSecurityFilterChain.doFilter(request,response,new MockFilterChain())
-        then: "access is not granted to the failure handler (sent to login page)"
-            response.status == 302
-    }
-
-    @EnableWebSecurity
-    static class PermitAllIgnoresFailureHandlerConfig extends BaseWebConfig {
-        static AuthenticationFailureHandler FAILURE_HANDLER
-
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .formLogin()
-                    .failureHandler(FAILURE_HANDLER)
-                    .permitAll()
-        }
-    }
-
-    def "duplicate formLogin does not override"() {
-        setup:
-            DuplicateInvocationsDoesNotOverrideConfig.FAILURE_HANDLER = Mock(AuthenticationFailureHandler)
-        when:
-            loadConfig(DuplicateInvocationsDoesNotOverrideConfig)
-        then:
-            findFilter(UsernamePasswordAuthenticationFilter).usernameParameter == "custom-username"
-    }
-
-    @EnableWebSecurity
-    static class DuplicateInvocationsDoesNotOverrideConfig extends BaseWebConfig {
-        static AuthenticationFailureHandler FAILURE_HANDLER
-
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .formLogin()
-                    .usernameParameter("custom-username")
-                    .and()
-                .formLogin()
-        }
-    }
-
-    def "formLogin ObjectPostProcessor"() {
-        setup: "initialize the AUTH_FILTER as a mock"
-            AnyObjectPostProcessor opp = Mock()
-            HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
-        when:
-            http
-                .exceptionHandling()
-                    .and()
-                .formLogin()
-                    .and()
-                .build()
-
-        then: "UsernamePasswordAuthenticationFilter is registered with ObjectPostProcessor"
-            1 * opp.postProcess(_ as UsernamePasswordAuthenticationFilter) >> {UsernamePasswordAuthenticationFilter o -> o}
-        and: "LoginUrlAuthenticationEntryPoint is registered with ObjectPostProcessor"
-            1 * opp.postProcess(_ as LoginUrlAuthenticationEntryPoint) >> {LoginUrlAuthenticationEntryPoint o -> o}
-        and: "ExceptionTranslationFilter is registered with ObjectPostProcessor"
-            1 * opp.postProcess(_ as ExceptionTranslationFilter) >> {ExceptionTranslationFilter o -> o}
-    }
+	def "Form Login"() {
+		when: "load formLogin()"
+			context = new AnnotationConfigApplicationContext(FormLoginConfig)
+
+		then: "FilterChains configured correctly"
+			def filterChains = filterChains()
+			filterChains.size() == 2
+			filterChains[0].requestMatcher.pattern == '/resources/**'
+			filterChains[0].filters.empty
+			filterChains[1].requestMatcher instanceof AnyRequestMatcher
+			filterChains[1].filters.collect { it.class.name.contains('$') ? it.class.superclass : it.class } ==
+					[WebAsyncManagerIntegrationFilter, SecurityContextPersistenceFilter, HeaderWriterFilter, CsrfFilter, LogoutFilter, UsernamePasswordAuthenticationFilter,
+					 RequestCacheAwareFilter, SecurityContextHolderAwareRequestFilter,
+					 AnonymousAuthenticationFilter, SessionManagementFilter, ExceptionTranslationFilter, FilterSecurityInterceptor ]
+
+		and: "UsernamePasswordAuthentictionFilter is configured correctly"
+			UsernamePasswordAuthenticationFilter authFilter = findFilter(UsernamePasswordAuthenticationFilter,1)
+			authFilter.usernameParameter == "username"
+			authFilter.passwordParameter == "password"
+			authFilter.failureHandler.defaultFailureUrl == "/login?error"
+			authFilter.successHandler.defaultTargetUrl == "/"
+			authFilter.requiresAuthentication(new MockHttpServletRequest(servletPath : "/login", method: "POST"), new MockHttpServletResponse())
+			!authFilter.requiresAuthentication(new MockHttpServletRequest(servletPath : "/login", method: "GET"), new MockHttpServletResponse())
+
+		and: "SessionFixationProtectionStrategy is configured correctly"
+			SessionFixationProtectionStrategy sessionStrategy = ReflectionTestUtils.getField(authFilter,"sessionStrategy").delegateStrategies.find { SessionFixationProtectionStrategy }
+			sessionStrategy.migrateSessionAttributes
+
+		and: "Exception handling is configured correctly"
+			AuthenticationEntryPoint authEntryPoint = filterChains[1].filters.find { it instanceof ExceptionTranslationFilter}.authenticationEntryPoint
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			authEntryPoint.commence(new MockHttpServletRequest(servletPath: "/private/"), response, new BadCredentialsException(""))
+			response.redirectedUrl == "http://localhost/login"
+	}
+
+	@EnableWebSecurity
+	static class FormLoginConfig extends BaseWebConfig {
+		@Override
+		public void configure(WebSecurity web)	throws Exception {
+			web
+				.ignoring()
+					.antMatchers("/resources/**");
+		}
+
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin()
+					.loginPage("/login")
+		}
+	}
+
+	def "FormLogin.permitAll()"() {
+		when: "load formLogin() with permitAll"
+			context = new AnnotationConfigApplicationContext(FormLoginConfigPermitAll)
+			FilterChainProxy filterChain = context.getBean(FilterChainProxy)
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			request = new MockHttpServletRequest(servletPath : servletPath, requestURI: servletPath, queryString: query, method: method)
+			setupCsrf()
+
+		then: "the formLogin URLs are granted access"
+			filterChain.doFilter(request, response, new MockFilterChain())
+			response.redirectedUrl == redirectUrl
+
+		where:
+			servletPath | method | query | redirectUrl
+			"/login" | "GET" | null | null
+			"/login" | "POST" | null | "/login?error"
+			"/login" | "GET" | "error" | null
+	}
+
+	@EnableWebSecurity
+	static class FormLoginConfigPermitAll extends BaseWebConfig {
+
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin()
+					.permitAll()
+		}
+	}
+
+	@Unroll
+	def "FormLogin loginConventions changes defaults"() {
+		when: "load formLogin() with permitAll"
+			loadConfig(FormLoginDefaultsConfig)
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			request = new MockHttpServletRequest(servletPath : servletPath, requestURI: servletPath, queryString: query, method: method)
+			setupCsrf()
+
+		then: "the other default login/logout URLs are updated and granted access"
+			springSecurityFilterChain.doFilter(request, response, new MockFilterChain())
+			response.redirectedUrl == redirectUrl
+
+		where:
+			servletPath     | method | query | redirectUrl
+			"/authenticate" | "GET"  | null    | null
+			"/authenticate" | "POST" | null    | "/authenticate?error"
+			"/authenticate" | "GET"  | "error" | null
+			"/logout"       | "POST" | null    | "/authenticate?logout"
+			"/authenticate" | "GET"  | "logout"| null
+	}
+
+	@EnableWebSecurity
+	static class FormLoginDefaultsConfig extends BaseWebConfig {
+
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin()
+					.loginPage("/authenticate")
+					.permitAll()
+					.and()
+				.logout()
+					.permitAll()
+		}
+	}
+
+	def "FormLogin loginProcessingUrl"() {
+		setup:
+			loadConfig(FormLoginLoginProcessingUrlConfig)
+			request.servletPath = "/loginCheck"
+			request.method = "POST"
+			request.parameters.username = ["user"] as String[]
+			request.parameters.password = ["password"] as String[]
+		when:
+			springSecurityFilterChain.doFilter(request, response, new MockFilterChain())
+		then:
+			response.redirectedUrl == "/"
+	}
+
+	@EnableWebSecurity
+	static class FormLoginLoginProcessingUrlConfig extends BaseWebConfig {
+
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().authenticated()
+					.and()
+				.formLogin()
+					.loginProcessingUrl("/loginCheck")
+					.loginPage("/login")
+					//.failureUrl("/loginFailure")
+					.defaultSuccessUrl("/", true)
+					.passwordParameter("password")
+					.usernameParameter("username")
+					.permitAll()
+					.and()
+				.logout()
+					.logoutSuccessUrl("/login")
+					.logoutUrl("/logout")
+					.deleteCookies("JSESSIONID")
+		}
+	}
+
+	def "FormLogin uses PortMapper"() {
+		when: "load formLogin() with permitAll"
+			FormLoginUsesPortMapperConfig.PORT_MAPPER = Mock(PortMapper)
+			loadConfig(FormLoginUsesPortMapperConfig)
+		then: "the formLogin URLs are granted access"
+			findFilter(ExceptionTranslationFilter).authenticationEntryPoint.portMapper == FormLoginUsesPortMapperConfig.PORT_MAPPER
+	}
+
+	@EnableWebSecurity
+	static class FormLoginUsesPortMapperConfig extends BaseWebConfig {
+		static PortMapper PORT_MAPPER
+
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin()
+					.permitAll()
+					.and()
+				.portMapper()
+					.portMapper(PORT_MAPPER)
+		}
+	}
+
+	def "FormLogin permitAll ignores failureUrl when failureHandler set"() {
+		setup:
+			PermitAllIgnoresFailureHandlerConfig.FAILURE_HANDLER = Mock(AuthenticationFailureHandler)
+			loadConfig(PermitAllIgnoresFailureHandlerConfig)
+			FilterChainProxy springSecurityFilterChain = context.getBean(FilterChainProxy)
+		when: "access default failureUrl and configured explicit FailureHandler"
+			MockHttpServletRequest request = new MockHttpServletRequest(servletPath:"/login",requestURI:"/login",queryString:"error",method:"GET")
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			springSecurityFilterChain.doFilter(request,response,new MockFilterChain())
+		then: "access is not granted to the failure handler (sent to login page)"
+			response.status == 302
+	}
+
+	@EnableWebSecurity
+	static class PermitAllIgnoresFailureHandlerConfig extends BaseWebConfig {
+		static AuthenticationFailureHandler FAILURE_HANDLER
+
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin()
+					.failureHandler(FAILURE_HANDLER)
+					.permitAll()
+		}
+	}
+
+	def "duplicate formLogin does not override"() {
+		setup:
+			DuplicateInvocationsDoesNotOverrideConfig.FAILURE_HANDLER = Mock(AuthenticationFailureHandler)
+		when:
+			loadConfig(DuplicateInvocationsDoesNotOverrideConfig)
+		then:
+			findFilter(UsernamePasswordAuthenticationFilter).usernameParameter == "custom-username"
+	}
+
+	@EnableWebSecurity
+	static class DuplicateInvocationsDoesNotOverrideConfig extends BaseWebConfig {
+		static AuthenticationFailureHandler FAILURE_HANDLER
+
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.formLogin()
+					.usernameParameter("custom-username")
+					.and()
+				.formLogin()
+		}
+	}
+
+	def "formLogin ObjectPostProcessor"() {
+		setup: "initialize the AUTH_FILTER as a mock"
+			AnyObjectPostProcessor opp = Mock()
+			HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
+		when:
+			http
+				.exceptionHandling()
+					.and()
+				.formLogin()
+					.and()
+				.build()
+
+		then: "UsernamePasswordAuthenticationFilter is registered with ObjectPostProcessor"
+			1 * opp.postProcess(_ as UsernamePasswordAuthenticationFilter) >> {UsernamePasswordAuthenticationFilter o -> o}
+		and: "LoginUrlAuthenticationEntryPoint is registered with ObjectPostProcessor"
+			1 * opp.postProcess(_ as LoginUrlAuthenticationEntryPoint) >> {LoginUrlAuthenticationEntryPoint o -> o}
+		and: "ExceptionTranslationFilter is registered with ObjectPostProcessor"
+			1 * opp.postProcess(_ as ExceptionTranslationFilter) >> {ExceptionTranslationFilter o -> o}
+	}
 }

+ 159 - 159
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/HeadersConfigurerTests.groovy

@@ -39,163 +39,163 @@ import spock.lang.Unroll;
  */
 class HeadersConfigurerTests extends BaseSpringSpec {
 
-    def "headers"() {
-        setup:
-            loadConfig(HeadersConfig)
-            request.secure = true
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            responseHeaders == ['X-Content-Type-Options':'nosniff',
-                         'X-Frame-Options':'DENY',
-                         'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
-                         'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
-                         'Expires' : '0',
-                         'Pragma':'no-cache',
-                         'X-XSS-Protection' : '1; mode=block']
-    }
-
-    @EnableWebSecurity
-    static class HeadersConfig extends WebSecurityConfigurerAdapter {
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http.headers()
-        }
-    }
-
-    def "headers.contentType"() {
-        setup:
-            loadConfig(ContentTypeOptionsConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            responseHeaders == ['X-Content-Type-Options':'nosniff']
-    }
-
-    @EnableWebSecurity
-    static class ContentTypeOptionsConfig extends WebSecurityConfigurerAdapter {
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .headers()
-                    .defaultsDisabled()
-                    .contentTypeOptions()
-        }
-    }
-
-    def "headers.frameOptions"() {
-        setup:
-            loadConfig(FrameOptionsConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            responseHeaders == ['X-Frame-Options':'DENY']
-    }
-
-    @EnableWebSecurity
-    static class FrameOptionsConfig extends WebSecurityConfigurerAdapter {
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .headers()
-                    .defaultsDisabled()
-                    .frameOptions()
-        }
-    }
-
-    def "headers.hsts"() {
-        setup:
-            loadConfig(HstsConfig)
-            request.secure = true
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            responseHeaders == ['Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains']
-    }
-
-    @EnableWebSecurity
-    static class HstsConfig extends WebSecurityConfigurerAdapter {
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .headers()
-                    .defaultsDisabled()
-                    .httpStrictTransportSecurity()
-        }
-    }
-
-    def "headers.cacheControl"() {
-        setup:
-            loadConfig(CacheControlConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            responseHeaders == ['Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
-                         'Expires' : '0',
-                         'Pragma':'no-cache']
-    }
-
-    @EnableWebSecurity
-    static class CacheControlConfig extends WebSecurityConfigurerAdapter {
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .headers()
-                    .defaultsDisabled()
-                    .cacheControl()
-        }
-    }
-
-    def "headers.xssProtection"() {
-        setup:
-            loadConfig(XssProtectionConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            responseHeaders == ['X-XSS-Protection' : '1; mode=block']
-    }
-
-    @EnableWebSecurity
-    static class XssProtectionConfig extends WebSecurityConfigurerAdapter {
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .headers()
-                    .defaultsDisabled()
-                    .xssProtection()
-        }
-    }
-
-    def "headers custom x-frame-options"() {
-        setup:
-            loadConfig(HeadersCustomSameOriginConfig)
-            request.secure = true
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            responseHeaders == ['X-Content-Type-Options':'nosniff',
-                         'X-Frame-Options':'SAMEORIGIN',
-                         'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
-                         'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
-                         'Expires' : '0',
-                         'Pragma':'no-cache',
-                         'X-XSS-Protection' : '1; mode=block']
-    }
-
-    @EnableWebSecurity
-    static class HeadersCustomSameOriginConfig extends WebSecurityConfigurerAdapter {
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .headers()
-                    .frameOptions().sameOrigin()
-        }
-    }
+	def "headers"() {
+		setup:
+			loadConfig(HeadersConfig)
+			request.secure = true
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			responseHeaders == ['X-Content-Type-Options':'nosniff',
+						 'X-Frame-Options':'DENY',
+						 'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
+						 'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
+						 'Expires' : '0',
+						 'Pragma':'no-cache',
+						 'X-XSS-Protection' : '1; mode=block']
+	}
+
+	@EnableWebSecurity
+	static class HeadersConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http.headers()
+		}
+	}
+
+	def "headers.contentType"() {
+		setup:
+			loadConfig(ContentTypeOptionsConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			responseHeaders == ['X-Content-Type-Options':'nosniff']
+	}
+
+	@EnableWebSecurity
+	static class ContentTypeOptionsConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.headers()
+					.defaultsDisabled()
+					.contentTypeOptions()
+		}
+	}
+
+	def "headers.frameOptions"() {
+		setup:
+			loadConfig(FrameOptionsConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			responseHeaders == ['X-Frame-Options':'DENY']
+	}
+
+	@EnableWebSecurity
+	static class FrameOptionsConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.headers()
+					.defaultsDisabled()
+					.frameOptions()
+		}
+	}
+
+	def "headers.hsts"() {
+		setup:
+			loadConfig(HstsConfig)
+			request.secure = true
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			responseHeaders == ['Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains']
+	}
+
+	@EnableWebSecurity
+	static class HstsConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.headers()
+					.defaultsDisabled()
+					.httpStrictTransportSecurity()
+		}
+	}
+
+	def "headers.cacheControl"() {
+		setup:
+			loadConfig(CacheControlConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			responseHeaders == ['Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
+						 'Expires' : '0',
+						 'Pragma':'no-cache']
+	}
+
+	@EnableWebSecurity
+	static class CacheControlConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.headers()
+					.defaultsDisabled()
+					.cacheControl()
+		}
+	}
+
+	def "headers.xssProtection"() {
+		setup:
+			loadConfig(XssProtectionConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			responseHeaders == ['X-XSS-Protection' : '1; mode=block']
+	}
+
+	@EnableWebSecurity
+	static class XssProtectionConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.headers()
+					.defaultsDisabled()
+					.xssProtection()
+		}
+	}
+
+	def "headers custom x-frame-options"() {
+		setup:
+			loadConfig(HeadersCustomSameOriginConfig)
+			request.secure = true
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			responseHeaders == ['X-Content-Type-Options':'nosniff',
+						 'X-Frame-Options':'SAMEORIGIN',
+						 'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
+						 'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
+						 'Expires' : '0',
+						 'Pragma':'no-cache',
+						 'X-XSS-Protection' : '1; mode=block']
+	}
+
+	@EnableWebSecurity
+	static class HeadersCustomSameOriginConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.headers()
+					.frameOptions().sameOrigin()
+		}
+	}
 }

+ 85 - 85
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/HttpBasicConfigurerTests.groovy

@@ -33,101 +33,101 @@ import org.springframework.security.web.authentication.www.BasicAuthenticationFi
  */
 class HttpBasicConfigurerTests extends BaseSpringSpec {
 
-    def "httBasic ObjectPostProcessor"() {
-        setup:
-            AnyObjectPostProcessor opp = Mock()
-            HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
-        when:
-            http
-                .httpBasic()
-                    .and()
-                .build()
+	def "httBasic ObjectPostProcessor"() {
+		setup:
+			AnyObjectPostProcessor opp = Mock()
+			HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
+		when:
+			http
+				.httpBasic()
+					.and()
+				.build()
 
-        then: "ExceptionTranslationFilter is registered with LifecycleManager"
-            1 * opp.postProcess(_ as BasicAuthenticationFilter) >> {BasicAuthenticationFilter o -> o}
-    }
+		then: "ExceptionTranslationFilter is registered with LifecycleManager"
+			1 * opp.postProcess(_ as BasicAuthenticationFilter) >> {BasicAuthenticationFilter o -> o}
+	}
 
-    def "SEC-2198: http.httpBasic() defaults AuthenticationEntryPoint"() {
-        setup:
-            loadConfig(DefaultsEntryPointConfig)
-        when:
-            springSecurityFilterChain.doFilter(request, response, chain)
-        then:
-            response.status == 401
-            response.getHeader("WWW-Authenticate") == 'Basic realm="Realm"'
-    }
+	def "SEC-2198: http.httpBasic() defaults AuthenticationEntryPoint"() {
+		setup:
+			loadConfig(DefaultsEntryPointConfig)
+		when:
+			springSecurityFilterChain.doFilter(request, response, chain)
+		then:
+			response.status == 401
+			response.getHeader("WWW-Authenticate") == 'Basic realm="Realm"'
+	}
 
-    @EnableWebSecurity
-    static class DefaultsEntryPointConfig extends WebSecurityConfigurerAdapter {
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().authenticated()
-                    .and()
-                .httpBasic()
-        }
+	@EnableWebSecurity
+	static class DefaultsEntryPointConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().authenticated()
+					.and()
+				.httpBasic()
+		}
 
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-        }
-    }
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+		}
+	}
 
-    def "http.httpBasic().authenticationEntryPoint used for AuthenticationEntryPoint"() {
-        setup:
-            CustomAuthenticationEntryPointConfig.ENTRY_POINT = Mock(AuthenticationEntryPoint)
-        when:
-            loadConfig(CustomAuthenticationEntryPointConfig)
-        then:
-            findFilter(ExceptionTranslationFilter).authenticationEntryPoint == CustomAuthenticationEntryPointConfig.ENTRY_POINT
-    }
+	def "http.httpBasic().authenticationEntryPoint used for AuthenticationEntryPoint"() {
+		setup:
+			CustomAuthenticationEntryPointConfig.ENTRY_POINT = Mock(AuthenticationEntryPoint)
+		when:
+			loadConfig(CustomAuthenticationEntryPointConfig)
+		then:
+			findFilter(ExceptionTranslationFilter).authenticationEntryPoint == CustomAuthenticationEntryPointConfig.ENTRY_POINT
+	}
 
-    @EnableWebSecurity
-    static class CustomAuthenticationEntryPointConfig extends WebSecurityConfigurerAdapter {
-        static AuthenticationEntryPoint ENTRY_POINT
+	@EnableWebSecurity
+	static class CustomAuthenticationEntryPointConfig extends WebSecurityConfigurerAdapter {
+		static AuthenticationEntryPoint ENTRY_POINT
 
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .httpBasic()
-                    .authenticationEntryPoint(ENTRY_POINT)
-        }
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.httpBasic()
+					.authenticationEntryPoint(ENTRY_POINT)
+		}
 
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-        }
-    }
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+		}
+	}
 
-    def "duplicate httpBasic invocations does not override"() {
-        setup:
-            DuplicateDoesNotOverrideConfig.ENTRY_POINT = Mock(AuthenticationEntryPoint)
-        when:
-            loadConfig(DuplicateDoesNotOverrideConfig)
-        then:
-            findFilter(ExceptionTranslationFilter).authenticationEntryPoint == DuplicateDoesNotOverrideConfig.ENTRY_POINT
-    }
+	def "duplicate httpBasic invocations does not override"() {
+		setup:
+			DuplicateDoesNotOverrideConfig.ENTRY_POINT = Mock(AuthenticationEntryPoint)
+		when:
+			loadConfig(DuplicateDoesNotOverrideConfig)
+		then:
+			findFilter(ExceptionTranslationFilter).authenticationEntryPoint == DuplicateDoesNotOverrideConfig.ENTRY_POINT
+	}
 
-    @EnableWebSecurity
-    static class DuplicateDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
-        static AuthenticationEntryPoint ENTRY_POINT
+	@EnableWebSecurity
+	static class DuplicateDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
+		static AuthenticationEntryPoint ENTRY_POINT
 
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .httpBasic()
-                    .authenticationEntryPoint(ENTRY_POINT)
-                    .and()
-                .httpBasic()
-        }
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.httpBasic()
+					.authenticationEntryPoint(ENTRY_POINT)
+					.and()
+				.httpBasic()
+		}
 
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-        }
-    }
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+		}
+	}
 }

+ 31 - 31
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/JeeConfigurerTests.groovy

@@ -31,38 +31,38 @@ import org.springframework.security.web.authentication.preauth.j2ee.J2eePreAuthe
  */
 class JeeConfigurerTests extends BaseSpringSpec {
 
-    def "jee ObjectPostProcessor"() {
-        setup:
-            AnyObjectPostProcessor opp = Mock()
-            HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
-        when:
-            http
-                .jee()
-                    .and()
-                .build()
+	def "jee ObjectPostProcessor"() {
+		setup:
+			AnyObjectPostProcessor opp = Mock()
+			HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
+		when:
+			http
+				.jee()
+					.and()
+				.build()
 
-        then: "J2eePreAuthenticatedProcessingFilter is registered with LifecycleManager"
-            1 * opp.postProcess(_ as J2eePreAuthenticatedProcessingFilter) >> {J2eePreAuthenticatedProcessingFilter o -> o}
-        and: "J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource is registered with LifecycleManager"
-            1 * opp.postProcess(_ as J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource) >> {J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource o -> o}
-    }
+		then: "J2eePreAuthenticatedProcessingFilter is registered with LifecycleManager"
+			1 * opp.postProcess(_ as J2eePreAuthenticatedProcessingFilter) >> {J2eePreAuthenticatedProcessingFilter o -> o}
+		and: "J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource is registered with LifecycleManager"
+			1 * opp.postProcess(_ as J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource) >> {J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource o -> o}
+	}
 
-    def "invoke jee twice does not override"() {
-        when:
-            loadConfig(InvokeTwiceDoesNotOverride)
-        then:
-            findFilter(J2eePreAuthenticatedProcessingFilter).authenticationDetailsSource.j2eeMappableRoles == ["ROLE_USER"] as Set
-    }
+	def "invoke jee twice does not override"() {
+		when:
+			loadConfig(InvokeTwiceDoesNotOverride)
+		then:
+			findFilter(J2eePreAuthenticatedProcessingFilter).authenticationDetailsSource.j2eeMappableRoles == ["ROLE_USER"] as Set
+	}
 
-    @EnableWebSecurity
-    static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .jee()
-                    .mappableRoles("USER")
-                    .and()
-                .jee()
-        }
-    }
+	@EnableWebSecurity
+	static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.jee()
+					.mappableRoles("USER")
+					.and()
+				.jee()
+		}
+	}
 }

+ 70 - 70
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/LogoutConfigurerTests.groovy

@@ -30,85 +30,85 @@ import org.springframework.security.web.authentication.logout.LogoutFilter
  */
 class LogoutConfigurerTests extends BaseSpringSpec {
 
-    def "logout ObjectPostProcessor"() {
-        setup:
-            AnyObjectPostProcessor opp = Mock()
-            HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
-        when:
-            http
-                .logout()
-                    .and()
-                .build()
+	def "logout ObjectPostProcessor"() {
+		setup:
+			AnyObjectPostProcessor opp = Mock()
+			HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
+		when:
+			http
+				.logout()
+					.and()
+				.build()
 
-        then: "LogoutFilter is registered with LifecycleManager"
-            1 * opp.postProcess(_ as LogoutFilter) >> {LogoutFilter o -> o}
-    }
+		then: "LogoutFilter is registered with LifecycleManager"
+			1 * opp.postProcess(_ as LogoutFilter) >> {LogoutFilter o -> o}
+	}
 
-    def "invoke logout twice does not override"() {
-        when:
-            loadConfig(InvokeTwiceDoesNotOverride)
-            request.method = "POST"
-            request.servletPath = "/custom/logout"
-            findFilter(LogoutFilter).doFilter(request,response,chain)
-        then:
-            response.redirectedUrl == "/login?logout"
-    }
+	def "invoke logout twice does not override"() {
+		when:
+			loadConfig(InvokeTwiceDoesNotOverride)
+			request.method = "POST"
+			request.servletPath = "/custom/logout"
+			findFilter(LogoutFilter).doFilter(request,response,chain)
+		then:
+			response.redirectedUrl == "/login?logout"
+	}
 
-    @EnableWebSecurity
-    static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
+	@EnableWebSecurity
+	static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
 
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .logout()
-                    .logoutUrl("/custom/logout")
-                    .and()
-                .logout()
-        }
-    }
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.logout()
+					.logoutUrl("/custom/logout")
+					.and()
+				.logout()
+		}
+	}
 
-    def "SEC-2311: Logout allows other methods if CSRF is disabled"() {
-        when:
-            loadConfig(CsrfDisabledConfig)
-            request.method = "GET"
-            request.servletPath = "/logout"
-            findFilter(LogoutFilter).doFilter(request,response,chain)
-        then:
-            response.redirectedUrl == "/login?logout"
-    }
+	def "SEC-2311: Logout allows other methods if CSRF is disabled"() {
+		when:
+			loadConfig(CsrfDisabledConfig)
+			request.method = "GET"
+			request.servletPath = "/logout"
+			findFilter(LogoutFilter).doFilter(request,response,chain)
+		then:
+			response.redirectedUrl == "/login?logout"
+	}
 
-    @EnableWebSecurity
-    static class CsrfDisabledConfig extends WebSecurityConfigurerAdapter {
+	@EnableWebSecurity
+	static class CsrfDisabledConfig extends WebSecurityConfigurerAdapter {
 
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .csrf().disable()
-                .logout()
-        }
-    }
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.csrf().disable()
+				.logout()
+		}
+	}
 
 
-    def "SEC-2311: Logout allows other methods if CSRF is disabled with custom logout URL"() {
-        when:
-            loadConfig(CsrfDisabledCustomLogoutUrlConfig)
-            request.method = "GET"
-            request.servletPath = "/custom/logout"
-            findFilter(LogoutFilter).doFilter(request,response,chain)
-        then:
-            response.redirectedUrl == "/login?logout"
-    }
+	def "SEC-2311: Logout allows other methods if CSRF is disabled with custom logout URL"() {
+		when:
+			loadConfig(CsrfDisabledCustomLogoutUrlConfig)
+			request.method = "GET"
+			request.servletPath = "/custom/logout"
+			findFilter(LogoutFilter).doFilter(request,response,chain)
+		then:
+			response.redirectedUrl == "/login?logout"
+	}
 
-    @EnableWebSecurity
-    static class CsrfDisabledCustomLogoutUrlConfig extends WebSecurityConfigurerAdapter {
+	@EnableWebSecurity
+	static class CsrfDisabledCustomLogoutUrlConfig extends WebSecurityConfigurerAdapter {
 
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .logout()
-                    .logoutUrl("/custom/logout")
-                    .and()
-                .csrf().disable()
-        }
-    }
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.logout()
+					.logoutUrl("/custom/logout")
+					.and()
+				.csrf().disable()
+		}
+	}
 }

+ 9 - 9
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceDebugTests.groovy

@@ -64,14 +64,14 @@ import spock.lang.Ignore;
  *
  */
 public class NamespaceDebugTests extends BaseSpringSpec {
-    def "debug=true"() {
-        when: "Load configuraiton with debug enabled"
-            loadConfig(DebugWebSecurity)
-        then: "The DebugFilter is present"
-            context.getBean("springSecurityFilterChain").class == DebugFilter
-    }
+	def "debug=true"() {
+		when: "Load configuraiton with debug enabled"
+			loadConfig(DebugWebSecurity)
+		then: "The DebugFilter is present"
+			context.getBean("springSecurityFilterChain").class == DebugFilter
+	}
 
-    @EnableWebSecurity(debug=true)
-    static class DebugWebSecurity extends WebSecurityConfigurerAdapter {
-    }
+	@EnableWebSecurity(debug=true)
+	static class DebugWebSecurity extends WebSecurityConfigurerAdapter {
+	}
 }

+ 36 - 36
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpAccessDeniedHandlerTests.groovy

@@ -37,44 +37,44 @@ import org.springframework.security.web.access.ExceptionTranslationFilter;
  *
  */
 public class NamespaceHttpAccessDeniedHandlerTests extends BaseSpringSpec {
-    def "http/access-denied-handler@error-page"() {
-        when:
-        loadConfig(AccessDeniedPageConfig)
-        then:
-        findFilter(ExceptionTranslationFilter).accessDeniedHandler.errorPage == "/AccessDeniedPageConfig"
-    }
+	def "http/access-denied-handler@error-page"() {
+		when:
+		loadConfig(AccessDeniedPageConfig)
+		then:
+		findFilter(ExceptionTranslationFilter).accessDeniedHandler.errorPage == "/AccessDeniedPageConfig"
+	}
 
-    @Configuration
-    static class AccessDeniedPageConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) {
-            http.
-                exceptionHandling()
-                    .accessDeniedPage("/AccessDeniedPageConfig")
-        }
-    }
+	@Configuration
+	static class AccessDeniedPageConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) {
+			http.
+				exceptionHandling()
+					.accessDeniedPage("/AccessDeniedPageConfig")
+		}
+	}
 
-    def "http/access-denied-handler@ref"() {
-        when:
-        loadConfig(AccessDeniedHandlerRefConfig)
-        then:
-        findFilter(ExceptionTranslationFilter).accessDeniedHandler.class == AccessDeniedHandlerRefConfig.CustomAccessDeniedHandler
-    }
+	def "http/access-denied-handler@ref"() {
+		when:
+		loadConfig(AccessDeniedHandlerRefConfig)
+		then:
+		findFilter(ExceptionTranslationFilter).accessDeniedHandler.class == AccessDeniedHandlerRefConfig.CustomAccessDeniedHandler
+	}
 
-    @Configuration
-    static class AccessDeniedHandlerRefConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) {
-            CustomAccessDeniedHandler accessDeniedHandler = new CustomAccessDeniedHandler()
-            http.
-                exceptionHandling()
-                    .accessDeniedHandler(accessDeniedHandler)
-        }
+	@Configuration
+	static class AccessDeniedHandlerRefConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) {
+			CustomAccessDeniedHandler accessDeniedHandler = new CustomAccessDeniedHandler()
+			http.
+				exceptionHandling()
+					.accessDeniedHandler(accessDeniedHandler)
+		}
 
-        static class CustomAccessDeniedHandler implements AccessDeniedHandler {
-            public void handle(HttpServletRequest request,
-                    HttpServletResponse response,
-                    AccessDeniedException accessDeniedException)
-                    throws IOException, ServletException {
-            }
-        }
-    }
+		static class CustomAccessDeniedHandler implements AccessDeniedHandler {
+			public void handle(HttpServletRequest request,
+					HttpServletResponse response,
+					AccessDeniedException accessDeniedException)
+					throws IOException, ServletException {
+			}
+		}
+	}
 }

+ 84 - 84
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpAnonymousTests.groovy

@@ -32,98 +32,98 @@ import org.springframework.security.web.authentication.AnonymousAuthenticationFi
  *
  */
 public class NamespaceHttpAnonymousTests extends BaseSpringSpec {
-    def "http/anonymous@enabled = true (default)"() {
-        when:
-        loadConfig(AnonymousConfig)
-        then:
-        def filter = findFilter(AnonymousAuthenticationFilter)
-        filter != null
-        def authManager = findFilter(FilterSecurityInterceptor).authenticationManager
-        authManager.authenticate(new AnonymousAuthenticationToken(filter.key, filter.principal, filter.authorities)).authenticated
-    }
+	def "http/anonymous@enabled = true (default)"() {
+		when:
+		loadConfig(AnonymousConfig)
+		then:
+		def filter = findFilter(AnonymousAuthenticationFilter)
+		filter != null
+		def authManager = findFilter(FilterSecurityInterceptor).authenticationManager
+		authManager.authenticate(new AnonymousAuthenticationToken(filter.key, filter.principal, filter.authorities)).authenticated
+	}
 
-    @Configuration
-    static class AnonymousConfig extends BaseWebConfig {
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER");
-        }
-    }
+	@Configuration
+	static class AnonymousConfig extends BaseWebConfig {
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER");
+		}
+	}
 
-    def "http/anonymous@enabled = false"() {
-        when:
-        loadConfig(AnonymousDisabledConfig)
-        then:
-        findFilter(AnonymousAuthenticationFilter) == null
-    }
+	def "http/anonymous@enabled = false"() {
+		when:
+		loadConfig(AnonymousDisabledConfig)
+		then:
+		findFilter(AnonymousAuthenticationFilter) == null
+	}
 
-    @Configuration
-    static class AnonymousDisabledConfig extends BaseWebConfig {
-      protected void configure(HttpSecurity http) {
-                http.anonymous().disable()
-        }
-    }
+	@Configuration
+	static class AnonymousDisabledConfig extends BaseWebConfig {
+	  protected void configure(HttpSecurity http) {
+				http.anonymous().disable()
+		}
+	}
 
-    def "http/anonymous@granted-authority"() {
-        when:
-        loadConfig(AnonymousGrantedAuthorityConfig)
-        then:
-        findFilter(AnonymousAuthenticationFilter).authorities == AuthorityUtils.createAuthorityList("ROLE_ANON")
-    }
+	def "http/anonymous@granted-authority"() {
+		when:
+		loadConfig(AnonymousGrantedAuthorityConfig)
+		then:
+		findFilter(AnonymousAuthenticationFilter).authorities == AuthorityUtils.createAuthorityList("ROLE_ANON")
+	}
 
-    @Configuration
-    static class AnonymousGrantedAuthorityConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) {
-            http
-                .anonymous()
-                    .authorities("ROLE_ANON")
-        }
-    }
+	@Configuration
+	static class AnonymousGrantedAuthorityConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) {
+			http
+				.anonymous()
+					.authorities("ROLE_ANON")
+		}
+	}
 
 
-    def "http/anonymous@key"() {
-        when:
-        loadConfig(AnonymousKeyConfig)
-        then:
-        def filter = findFilter(AnonymousAuthenticationFilter)
-        filter != null
-        filter.key == "AnonymousKeyConfig"
-        def authManager = findFilter(FilterSecurityInterceptor).authenticationManager
-        authManager.authenticate(new AnonymousAuthenticationToken(filter.key, filter.principal, filter.authorities)).authenticated
-    }
+	def "http/anonymous@key"() {
+		when:
+		loadConfig(AnonymousKeyConfig)
+		then:
+		def filter = findFilter(AnonymousAuthenticationFilter)
+		filter != null
+		filter.key == "AnonymousKeyConfig"
+		def authManager = findFilter(FilterSecurityInterceptor).authenticationManager
+		authManager.authenticate(new AnonymousAuthenticationToken(filter.key, filter.principal, filter.authorities)).authenticated
+	}
 
-    @Configuration
-    static class AnonymousKeyConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .anonymous().key("AnonymousKeyConfig")
-        }
-    }
+	@Configuration
+	static class AnonymousKeyConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.anonymous().key("AnonymousKeyConfig")
+		}
+	}
 
-    def "http/anonymous@username"() {
-        when:
-        loadConfig(AnonymousUsernameConfig)
-        then:
-        def filter = findFilter(AnonymousAuthenticationFilter)
-        filter != null
-        filter.principal == "AnonymousUsernameConfig"
-        def authManager = findFilter(FilterSecurityInterceptor).authenticationManager
-        authManager.authenticate(new AnonymousAuthenticationToken(filter.key, filter.principal, filter.authorities)).principal == "AnonymousUsernameConfig"
-    }
+	def "http/anonymous@username"() {
+		when:
+		loadConfig(AnonymousUsernameConfig)
+		then:
+		def filter = findFilter(AnonymousAuthenticationFilter)
+		filter != null
+		filter.principal == "AnonymousUsernameConfig"
+		def authManager = findFilter(FilterSecurityInterceptor).authenticationManager
+		authManager.authenticate(new AnonymousAuthenticationToken(filter.key, filter.principal, filter.authorities)).principal == "AnonymousUsernameConfig"
+	}
 
-    @Configuration
-    static class AnonymousUsernameConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .anonymous().principal("AnonymousUsernameConfig")
-        }
-    }
+	@Configuration
+	static class AnonymousUsernameConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.anonymous().principal("AnonymousUsernameConfig")
+		}
+	}
 }

+ 104 - 104
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpBasicTests.groovy

@@ -40,117 +40,117 @@ import org.springframework.security.web.authentication.www.BasicAuthenticationFi
  */
 public class NamespaceHttpBasicTests extends BaseSpringSpec {
 
-    def "http/http-basic"() {
-        setup:
-            loadConfig(HttpBasicConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_UNAUTHORIZED
-        when: "fail to log in"
-            super.setup()
-            basicLogin("user","invalid")
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "unauthorized"
-            response.status == HttpServletResponse.SC_UNAUTHORIZED
-            response.getHeader("WWW-Authenticate") == 'Basic realm="Realm"'
-        when: "login success"
-            super.setup()
-            basicLogin()
-        then: "sent to default succes page"
-            !response.committed
-    }
+	def "http/http-basic"() {
+		setup:
+			loadConfig(HttpBasicConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_UNAUTHORIZED
+		when: "fail to log in"
+			super.setup()
+			basicLogin("user","invalid")
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "unauthorized"
+			response.status == HttpServletResponse.SC_UNAUTHORIZED
+			response.getHeader("WWW-Authenticate") == 'Basic realm="Realm"'
+		when: "login success"
+			super.setup()
+			basicLogin()
+		then: "sent to default succes page"
+			!response.committed
+	}
 
-    @Configuration
-    static class HttpBasicConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .httpBasic();
-        }
-    }
+	@Configuration
+	static class HttpBasicConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.httpBasic();
+		}
+	}
 
-    def "http@realm"() {
-        setup:
-            loadConfig(CustomHttpBasicConfig)
-        when:
-            basicLogin("user","invalid")
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "unauthorized"
-            response.status == HttpServletResponse.SC_UNAUTHORIZED
-            response.getHeader("WWW-Authenticate") == 'Basic realm="Custom Realm"'
-    }
+	def "http@realm"() {
+		setup:
+			loadConfig(CustomHttpBasicConfig)
+		when:
+			basicLogin("user","invalid")
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "unauthorized"
+			response.status == HttpServletResponse.SC_UNAUTHORIZED
+			response.getHeader("WWW-Authenticate") == 'Basic realm="Custom Realm"'
+	}
 
-    @Configuration
-    static class CustomHttpBasicConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .httpBasic().realmName("Custom Realm");
-        }
-    }
+	@Configuration
+	static class CustomHttpBasicConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.httpBasic().realmName("Custom Realm");
+		}
+	}
 
-    def "http-basic@authentication-details-source-ref"() {
-        when:
-            loadConfig(AuthenticationDetailsSourceHttpBasicConfig)
-        then:
-            findFilter(BasicAuthenticationFilter).authenticationDetailsSource.class == CustomAuthenticationDetailsSource
-    }
+	def "http-basic@authentication-details-source-ref"() {
+		when:
+			loadConfig(AuthenticationDetailsSourceHttpBasicConfig)
+		then:
+			findFilter(BasicAuthenticationFilter).authenticationDetailsSource.class == CustomAuthenticationDetailsSource
+	}
 
-    @Configuration
-    static class AuthenticationDetailsSourceHttpBasicConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) {
-            http
-                .httpBasic()
-                    .authenticationDetailsSource(new CustomAuthenticationDetailsSource())
-        }
-    }
+	@Configuration
+	static class AuthenticationDetailsSourceHttpBasicConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) {
+			http
+				.httpBasic()
+					.authenticationDetailsSource(new CustomAuthenticationDetailsSource())
+		}
+	}
 
-    static class CustomAuthenticationDetailsSource extends WebAuthenticationDetailsSource {}
+	static class CustomAuthenticationDetailsSource extends WebAuthenticationDetailsSource {}
 
-    def "http-basic@entry-point-ref"() {
-        setup:
-            loadConfig(EntryPointRefHttpBasicConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_INTERNAL_SERVER_ERROR
-        when: "fail to log in"
-            super.setup()
-            basicLogin("user","invalid")
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "custom"
-            response.status == HttpServletResponse.SC_INTERNAL_SERVER_ERROR
-        when: "login success"
-            super.setup()
-            basicLogin()
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to default succes page"
-            !response.committed
-    }
+	def "http-basic@entry-point-ref"() {
+		setup:
+			loadConfig(EntryPointRefHttpBasicConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_INTERNAL_SERVER_ERROR
+		when: "fail to log in"
+			super.setup()
+			basicLogin("user","invalid")
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "custom"
+			response.status == HttpServletResponse.SC_INTERNAL_SERVER_ERROR
+		when: "login success"
+			super.setup()
+			basicLogin()
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to default succes page"
+			!response.committed
+	}
 
-    @Configuration
-    static class EntryPointRefHttpBasicConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .httpBasic()
-                    .authenticationEntryPoint(new AuthenticationEntryPoint() {
-                        public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) {
-                            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR)
-                        }
-                    })
-        }
-    }
+	@Configuration
+	static class EntryPointRefHttpBasicConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.httpBasic()
+					.authenticationEntryPoint(new AuthenticationEntryPoint() {
+						public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) {
+							response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR)
+						}
+					})
+		}
+	}
 
-    def basicLogin(String username="user",String password="password") {
-        def credentials = username + ":" + password
-        request.addHeader("Authorization", "Basic " + credentials.bytes.encodeBase64())
-    }
+	def basicLogin(String username="user",String password="password") {
+		def credentials = username + ":" + password
+		request.addHeader("Authorization", "Basic " + credentials.bytes.encodeBase64())
+	}
 }

+ 101 - 101
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpCustomFilterTests.groovy

@@ -65,105 +65,105 @@ import spock.lang.Ignore;
  *
  */
 public class NamespaceHttpCustomFilterTests extends BaseSpringSpec {
-    def "http/custom-filter@before"() {
-        when:
-        loadConfig(CustomFilterBeforeConfig)
-        then:
-        filterChain().filters[0].class == CustomFilter
-    }
-
-    @Configuration
-    static class CustomFilterBeforeConfig extends BaseWebConfig {
-        CustomFilterBeforeConfig() {
-            // do not add the default filters to make testing easier
-            super(true)
-        }
-
-        protected void configure(HttpSecurity http) {
-            http
-                .addFilterBefore(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
-                .formLogin()
-        }
-    }
-
-    def "http/custom-filter@after"() {
-        when:
-        loadConfig(CustomFilterAfterConfig)
-        then:
-        filterChain().filters[1].class == CustomFilter
-    }
-
-    @Configuration
-    static class CustomFilterAfterConfig extends BaseWebConfig {
-        CustomFilterAfterConfig() {
-            // do not add the default filters to make testing easier
-            super(true)
-        }
-
-        protected void configure(HttpSecurity http) {
-            http
-                .addFilterAfter(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
-                .formLogin()
-        }
-    }
-
-    def "http/custom-filter@position"() {
-        when:
-        loadConfig(CustomFilterPositionConfig)
-        then:
-        filterChain().filters.collect { it.class } == [CustomFilter]
-    }
-
-    @Configuration
-    static class CustomFilterPositionConfig extends BaseWebConfig {
-        CustomFilterPositionConfig() {
-            // do not add the default filters to make testing easier
-            super(true)
-        }
-
-        protected void configure(HttpSecurity http) {
-            http
-                // this works so long as the CustomFilter extends one of the standard filters
-                // if not, use addFilterBefore or addFilterAfter
-                .addFilter(new CustomFilter())
-        }
-
-    }
-
-    def "http/custom-filter no AuthenticationManager in HttpSecurity"() {
-        when:
-        loadConfig(NoAuthenticationManagerInHtppConfigurationConfig)
-        then:
-        filterChain().filters[0].class == CustomFilter
-    }
-
-    @EnableWebSecurity
-    static class NoAuthenticationManagerInHtppConfigurationConfig extends WebSecurityConfigurerAdapter {
-        NoAuthenticationManagerInHtppConfigurationConfig() {
-            super(true)
-        }
-
-        protected AuthenticationManager authenticationManager()
-                throws Exception {
-            return new CustomAuthenticationManager();
-        }
-
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .addFilterBefore(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
-        }
-    }
-
-    static class CustomFilter extends UsernamePasswordAuthenticationFilter {}
-
-    static class CustomAuthenticationManager implements AuthenticationManager {
-        public Authentication authenticate(Authentication authentication)
-                throws AuthenticationException {
-            return null;
-        }
-    }
+	def "http/custom-filter@before"() {
+		when:
+		loadConfig(CustomFilterBeforeConfig)
+		then:
+		filterChain().filters[0].class == CustomFilter
+	}
+
+	@Configuration
+	static class CustomFilterBeforeConfig extends BaseWebConfig {
+		CustomFilterBeforeConfig() {
+			// do not add the default filters to make testing easier
+			super(true)
+		}
+
+		protected void configure(HttpSecurity http) {
+			http
+				.addFilterBefore(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
+				.formLogin()
+		}
+	}
+
+	def "http/custom-filter@after"() {
+		when:
+		loadConfig(CustomFilterAfterConfig)
+		then:
+		filterChain().filters[1].class == CustomFilter
+	}
+
+	@Configuration
+	static class CustomFilterAfterConfig extends BaseWebConfig {
+		CustomFilterAfterConfig() {
+			// do not add the default filters to make testing easier
+			super(true)
+		}
+
+		protected void configure(HttpSecurity http) {
+			http
+				.addFilterAfter(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
+				.formLogin()
+		}
+	}
+
+	def "http/custom-filter@position"() {
+		when:
+		loadConfig(CustomFilterPositionConfig)
+		then:
+		filterChain().filters.collect { it.class } == [CustomFilter]
+	}
+
+	@Configuration
+	static class CustomFilterPositionConfig extends BaseWebConfig {
+		CustomFilterPositionConfig() {
+			// do not add the default filters to make testing easier
+			super(true)
+		}
+
+		protected void configure(HttpSecurity http) {
+			http
+				// this works so long as the CustomFilter extends one of the standard filters
+				// if not, use addFilterBefore or addFilterAfter
+				.addFilter(new CustomFilter())
+		}
+
+	}
+
+	def "http/custom-filter no AuthenticationManager in HttpSecurity"() {
+		when:
+		loadConfig(NoAuthenticationManagerInHtppConfigurationConfig)
+		then:
+		filterChain().filters[0].class == CustomFilter
+	}
+
+	@EnableWebSecurity
+	static class NoAuthenticationManagerInHtppConfigurationConfig extends WebSecurityConfigurerAdapter {
+		NoAuthenticationManagerInHtppConfigurationConfig() {
+			super(true)
+		}
+
+		protected AuthenticationManager authenticationManager()
+				throws Exception {
+			return new CustomAuthenticationManager();
+		}
+
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.addFilterBefore(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
+		}
+	}
+
+	static class CustomFilter extends UsernamePasswordAuthenticationFilter {}
+
+	static class CustomAuthenticationManager implements AuthenticationManager {
+		public Authentication authenticate(Authentication authentication)
+				throws AuthenticationException {
+			return null;
+		}
+	}
 }

+ 21 - 21
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpExpressionHandlerTests.groovy

@@ -30,27 +30,27 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
  *
  */
 public class NamespaceHttpExpressionHandlerTests extends BaseSpringSpec {
-    def "http/expression-handler@ref"() {
-        when:
-            def parser = new SpelExpressionParser()
-            ExpressionHandlerConfig.EXPRESSION_HANDLER = Mock(SecurityExpressionHandler.class)
-            ExpressionHandlerConfig.EXPRESSION_HANDLER.getExpressionParser() >> parser
-            loadConfig(ExpressionHandlerConfig)
-        then:
-            noExceptionThrown()
-    }
+	def "http/expression-handler@ref"() {
+		when:
+			def parser = new SpelExpressionParser()
+			ExpressionHandlerConfig.EXPRESSION_HANDLER = Mock(SecurityExpressionHandler.class)
+			ExpressionHandlerConfig.EXPRESSION_HANDLER.getExpressionParser() >> parser
+			loadConfig(ExpressionHandlerConfig)
+		then:
+			noExceptionThrown()
+	}
 
-    @EnableWebSecurity
-    static class ExpressionHandlerConfig extends BaseWebConfig {
-        static EXPRESSION_HANDLER;
+	@EnableWebSecurity
+	static class ExpressionHandlerConfig extends BaseWebConfig {
+		static EXPRESSION_HANDLER;
 
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .expressionHandler(EXPRESSION_HANDLER)
-                    .antMatchers("/users**","/sessions/**").hasRole("ADMIN")
-                    .antMatchers("/signup").permitAll()
-                    .anyRequest().hasRole("USER")
-        }
-    }
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.expressionHandler(EXPRESSION_HANDLER)
+					.antMatchers("/users**","/sessions/**").hasRole("ADMIN")
+					.antMatchers("/signup").permitAll()
+					.anyRequest().hasRole("USER")
+		}
+	}
 }

+ 59 - 59
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFirewallTests.groovy

@@ -38,73 +38,73 @@ import org.springframework.security.web.firewall.RequestRejectedException
  *
  */
 public class NamespaceHttpFirewallTests extends BaseSpringSpec {
-    FilterChainProxy springSecurityFilterChain
-    MockHttpServletRequest request
-    MockHttpServletResponse response
-    MockFilterChain chain
+	FilterChainProxy springSecurityFilterChain
+	MockHttpServletRequest request
+	MockHttpServletResponse response
+	MockFilterChain chain
 
-    def setup() {
-        request = new MockHttpServletRequest()
-        response = new MockHttpServletResponse()
-        chain = new MockFilterChain()
-    }
+	def setup() {
+		request = new MockHttpServletRequest()
+		response = new MockHttpServletResponse()
+		chain = new MockFilterChain()
+	}
 
-    def "http-firewall"() {
-        setup:
-            loadConfig(HttpFirewallConfig)
-            springSecurityFilterChain = context.getBean(FilterChainProxy)
-            request.setPathInfo("/public/../private/")
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "the default firewall is used"
-            thrown(RequestRejectedException)
-    }
+	def "http-firewall"() {
+		setup:
+			loadConfig(HttpFirewallConfig)
+			springSecurityFilterChain = context.getBean(FilterChainProxy)
+			request.setPathInfo("/public/../private/")
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "the default firewall is used"
+			thrown(RequestRejectedException)
+	}
 
-    @Configuration
-    static class HttpFirewallConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) {
-        }
-    }
+	@Configuration
+	static class HttpFirewallConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) {
+		}
+	}
 
-    def "http-firewall@ref"() {
-        setup:
-            loadConfig(CustomHttpFirewallConfig)
-            springSecurityFilterChain = context.getBean(FilterChainProxy)
-            request.setParameter("deny", "true")
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "the custom firewall is used"
-            thrown(RequestRejectedException)
-    }
+	def "http-firewall@ref"() {
+		setup:
+			loadConfig(CustomHttpFirewallConfig)
+			springSecurityFilterChain = context.getBean(FilterChainProxy)
+			request.setParameter("deny", "true")
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "the custom firewall is used"
+			thrown(RequestRejectedException)
+	}
 
-    @Configuration
-    static class CustomHttpFirewallConfig extends BaseWebConfig {
-        @Override
-        protected void configure(HttpSecurity http) { }
+	@Configuration
+	static class CustomHttpFirewallConfig extends BaseWebConfig {
+		@Override
+		protected void configure(HttpSecurity http) { }
 
-        @Override
-        public void configure(WebSecurity builder)	throws Exception {
-            builder
-                .httpFirewall(new CustomHttpFirewall())
-        }
-    }
+		@Override
+		public void configure(WebSecurity builder)	throws Exception {
+			builder
+				.httpFirewall(new CustomHttpFirewall())
+		}
+	}
 
-    static class CustomHttpFirewall extends DefaultHttpFirewall {
+	static class CustomHttpFirewall extends DefaultHttpFirewall {
 
-        @Override
-        public FirewalledRequest getFirewalledRequest(HttpServletRequest request)
-                throws RequestRejectedException {
-            if(request.getParameter("deny")) {
-                throw new RequestRejectedException("custom rejection")
-            }
-            return super.getFirewalledRequest(request)
-        }
+		@Override
+		public FirewalledRequest getFirewalledRequest(HttpServletRequest request)
+				throws RequestRejectedException {
+			if(request.getParameter("deny")) {
+				throw new RequestRejectedException("custom rejection")
+			}
+			return super.getFirewalledRequest(request)
+		}
 
-        @Override
-        public HttpServletResponse getFirewalledResponse(
-                HttpServletResponse response) {
-            return super.getFirewalledRequest(response)
-        }
+		@Override
+		public HttpServletResponse getFirewalledResponse(
+				HttpServletResponse response) {
+			return super.getFirewalledRequest(response)
+		}
 
-    }
+	}
 }

+ 120 - 120
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFormLoginTests.groovy

@@ -38,133 +38,133 @@ import org.springframework.security.web.authentication.WebAuthenticationDetailsS
  *
  */
 public class NamespaceHttpFormLoginTests extends BaseSpringSpec {
-    FilterChainProxy springSecurityFilterChain
+	FilterChainProxy springSecurityFilterChain
 
-    def "http/form-login"() {
-        setup:
-        loadConfig(FormLoginConfig)
-            springSecurityFilterChain = context.getBean(FilterChainProxy)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.getRedirectedUrl() == "http://localhost/login"
-        when: "fail to log in"
-            super.setup()
-            request.servletPath = "/login"
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to login error page"
-            response.getRedirectedUrl() == "/login?error"
-        when: "login success"
-            super.setup()
-            request.servletPath = "/login"
-            request.method = "POST"
-            request.parameters.username = ["user"] as String[]
-            request.parameters.password = ["password"] as String[]
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to default succes page"
-            response.getRedirectedUrl() == "/"
-    }
+	def "http/form-login"() {
+		setup:
+		loadConfig(FormLoginConfig)
+			springSecurityFilterChain = context.getBean(FilterChainProxy)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.getRedirectedUrl() == "http://localhost/login"
+		when: "fail to log in"
+			super.setup()
+			request.servletPath = "/login"
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to login error page"
+			response.getRedirectedUrl() == "/login?error"
+		when: "login success"
+			super.setup()
+			request.servletPath = "/login"
+			request.method = "POST"
+			request.parameters.username = ["user"] as String[]
+			request.parameters.password = ["password"] as String[]
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to default succes page"
+			response.getRedirectedUrl() == "/"
+	}
 
-    @Configuration
-    static class FormLoginConfig extends BaseWebConfig {
+	@Configuration
+	static class FormLoginConfig extends BaseWebConfig {
 
-        @Override
-        public void configure(WebSecurity web) throws Exception {
-            web
-                .ignoring()
-                    .antMatchers("/resources/**");
-        }
+		@Override
+		public void configure(WebSecurity web) throws Exception {
+			web
+				.ignoring()
+					.antMatchers("/resources/**");
+		}
 
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .formLogin()
-        }
-    }
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin()
+		}
+	}
 
-    def "http/form-login custom"() {
-        setup:
-            loadConfig(FormLoginCustomConfig)
-            springSecurityFilterChain = context.getBean(FilterChainProxy)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.getRedirectedUrl() == "http://localhost/authentication/login"
-        when: "fail to log in"
-            super.setup()
-            request.servletPath = "/authentication/login/process"
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-            then: "sent to login error page"
-            response.getRedirectedUrl() == "/authentication/login?failed"
-        when: "login success"
-            super.setup()
-            request.servletPath = "/authentication/login/process"
-            request.method = "POST"
-            request.parameters.username = ["user"] as String[]
-            request.parameters.password = ["password"] as String[]
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to default succes page"
-            response.getRedirectedUrl() == "/default"
-    }
+	def "http/form-login custom"() {
+		setup:
+			loadConfig(FormLoginCustomConfig)
+			springSecurityFilterChain = context.getBean(FilterChainProxy)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.getRedirectedUrl() == "http://localhost/authentication/login"
+		when: "fail to log in"
+			super.setup()
+			request.servletPath = "/authentication/login/process"
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+			then: "sent to login error page"
+			response.getRedirectedUrl() == "/authentication/login?failed"
+		when: "login success"
+			super.setup()
+			request.servletPath = "/authentication/login/process"
+			request.method = "POST"
+			request.parameters.username = ["user"] as String[]
+			request.parameters.password = ["password"] as String[]
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to default succes page"
+			response.getRedirectedUrl() == "/default"
+	}
 
-    @Configuration
-    static class FormLoginCustomConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            boolean alwaysUseDefaultSuccess = true;
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .formLogin()
-                    .usernameParameter("username") // form-login@username-parameter
-                    .passwordParameter("password") // form-login@password-parameter
-                    .loginPage("/authentication/login") // form-login@login-page
-                    .failureUrl("/authentication/login?failed") // form-login@authentication-failure-url
-                    .loginProcessingUrl("/authentication/login/process") // form-login@login-processing-url
-                    .defaultSuccessUrl("/default", alwaysUseDefaultSuccess) // form-login@default-target-url / form-login@always-use-default-target
-        }
-    }
+	@Configuration
+	static class FormLoginCustomConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			boolean alwaysUseDefaultSuccess = true;
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin()
+					.usernameParameter("username") // form-login@username-parameter
+					.passwordParameter("password") // form-login@password-parameter
+					.loginPage("/authentication/login") // form-login@login-page
+					.failureUrl("/authentication/login?failed") // form-login@authentication-failure-url
+					.loginProcessingUrl("/authentication/login/process") // form-login@login-processing-url
+					.defaultSuccessUrl("/default", alwaysUseDefaultSuccess) // form-login@default-target-url / form-login@always-use-default-target
+		}
+	}
 
-    def "http/form-login custom refs"() {
-        when:
-            loadConfig(FormLoginCustomRefsConfig)
-            springSecurityFilterChain = context.getBean(FilterChainProxy)
-            then: "CustomWebAuthenticationDetailsSource is used"
-            findFilter(UsernamePasswordAuthenticationFilter).authenticationDetailsSource.class == CustomWebAuthenticationDetailsSource
-        when: "fail to log in"
-            request.servletPath = "/login"
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to login error page"
-            response.getRedirectedUrl() == "/custom/failure"
-        when: "login success"
-            super.setup()
-            request.servletPath = "/login"
-            request.method = "POST"
-            request.parameters.username = ["user"] as String[]
-            request.parameters.password = ["password"] as String[]
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to default succes page"
-            response.getRedirectedUrl() == "/custom/targetUrl"
-    }
+	def "http/form-login custom refs"() {
+		when:
+			loadConfig(FormLoginCustomRefsConfig)
+			springSecurityFilterChain = context.getBean(FilterChainProxy)
+			then: "CustomWebAuthenticationDetailsSource is used"
+			findFilter(UsernamePasswordAuthenticationFilter).authenticationDetailsSource.class == CustomWebAuthenticationDetailsSource
+		when: "fail to log in"
+			request.servletPath = "/login"
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to login error page"
+			response.getRedirectedUrl() == "/custom/failure"
+		when: "login success"
+			super.setup()
+			request.servletPath = "/login"
+			request.method = "POST"
+			request.parameters.username = ["user"] as String[]
+			request.parameters.password = ["password"] as String[]
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to default succes page"
+			response.getRedirectedUrl() == "/custom/targetUrl"
+	}
 
-    @Configuration
-    static class FormLoginCustomRefsConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .formLogin()
-                    .loginPage("/login")
-                    .failureHandler(new SimpleUrlAuthenticationFailureHandler("/custom/failure")) // form-login@authentication-failure-handler-ref
-                    .successHandler(new SavedRequestAwareAuthenticationSuccessHandler( defaultTargetUrl : "/custom/targetUrl" )) // form-login@authentication-success-handler-ref
-                    .authenticationDetailsSource(new CustomWebAuthenticationDetailsSource()) // form-login@authentication-details-source-ref
-                    .and();
-        }
-    }
+	@Configuration
+	static class FormLoginCustomRefsConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.formLogin()
+					.loginPage("/login")
+					.failureHandler(new SimpleUrlAuthenticationFailureHandler("/custom/failure")) // form-login@authentication-failure-handler-ref
+					.successHandler(new SavedRequestAwareAuthenticationSuccessHandler( defaultTargetUrl : "/custom/targetUrl" )) // form-login@authentication-success-handler-ref
+					.authenticationDetailsSource(new CustomWebAuthenticationDetailsSource()) // form-login@authentication-details-source-ref
+					.and();
+		}
+	}
 
-    static class CustomWebAuthenticationDetailsSource extends WebAuthenticationDetailsSource {}
+	static class CustomWebAuthenticationDetailsSource extends WebAuthenticationDetailsSource {}
 }

+ 203 - 203
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpHeadersTests.groovy

@@ -38,230 +38,230 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
  */
 public class NamespaceHttpHeadersTests extends BaseSpringSpec {
 
-    def "http/headers"() {
-        setup:
-            loadConfig(HeadersDefaultConfig)
-            request.secure = true
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            responseHeaders == ['X-Content-Type-Options':'nosniff',
-                'X-Frame-Options':'DENY',
-                'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
-                'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
-                'Pragma':'no-cache',
-                'Expires' : '0',
-                'X-XSS-Protection' : '1; mode=block']
-    }
+	def "http/headers"() {
+		setup:
+			loadConfig(HeadersDefaultConfig)
+			request.secure = true
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			responseHeaders == ['X-Content-Type-Options':'nosniff',
+				'X-Frame-Options':'DENY',
+				'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
+				'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
+				'Pragma':'no-cache',
+				'Expires' : '0',
+				'X-XSS-Protection' : '1; mode=block']
+	}
 
-    @Configuration
-    static class HeadersDefaultConfig extends BaseWebConfig {
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .headers()
-        }
-    }
+	@Configuration
+	static class HeadersDefaultConfig extends BaseWebConfig {
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.headers()
+		}
+	}
 
-    def "http/headers/cache-control"() {
-        setup:
-            loadConfig(HeadersCacheControlConfig)
-            request.secure = true
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            responseHeaders == ['Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
-                'Expires' : '0',
-                'Pragma':'no-cache']
-    }
+	def "http/headers/cache-control"() {
+		setup:
+			loadConfig(HeadersCacheControlConfig)
+			request.secure = true
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			responseHeaders == ['Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
+				'Expires' : '0',
+				'Pragma':'no-cache']
+	}
 
-    @Configuration
-    static class HeadersCacheControlConfig extends BaseWebConfig {
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .headers()
-                    .defaultsDisabled()
-                    .cacheControl()
-        }
-    }
+	@Configuration
+	static class HeadersCacheControlConfig extends BaseWebConfig {
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.headers()
+					.defaultsDisabled()
+					.cacheControl()
+		}
+	}
 
-    def "http/headers/hsts"() {
-        setup:
-            loadConfig(HstsConfig)
-            request.secure = true
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            responseHeaders == ['Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains']
-    }
+	def "http/headers/hsts"() {
+		setup:
+			loadConfig(HstsConfig)
+			request.secure = true
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			responseHeaders == ['Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains']
+	}
 
-    @Configuration
-    static class HstsConfig extends BaseWebConfig {
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .headers()
-                    .defaultsDisabled()
-                    .httpStrictTransportSecurity()
-        }
-    }
+	@Configuration
+	static class HstsConfig extends BaseWebConfig {
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.headers()
+					.defaultsDisabled()
+					.httpStrictTransportSecurity()
+		}
+	}
 
-    def "http/headers/hsts custom"() {
-        setup:
-            loadConfig(HstsCustomConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            responseHeaders == ['Strict-Transport-Security': 'max-age=15768000']
-    }
+	def "http/headers/hsts custom"() {
+		setup:
+			loadConfig(HstsCustomConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			responseHeaders == ['Strict-Transport-Security': 'max-age=15768000']
+	}
 
-    @Configuration
-    static class HstsCustomConfig extends BaseWebConfig {
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .headers()
-                    // hsts@request-matcher-ref, hsts@max-age-seconds, hsts@include-subdomains
-                    .defaultsDisabled()
-                    .httpStrictTransportSecurity()
-                        .requestMatcher(AnyRequestMatcher.INSTANCE)
-                        .maxAgeInSeconds(15768000)
-                        .includeSubDomains(false)
-        }
-    }
+	@Configuration
+	static class HstsCustomConfig extends BaseWebConfig {
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.headers()
+					// hsts@request-matcher-ref, hsts@max-age-seconds, hsts@include-subdomains
+					.defaultsDisabled()
+					.httpStrictTransportSecurity()
+						.requestMatcher(AnyRequestMatcher.INSTANCE)
+						.maxAgeInSeconds(15768000)
+						.includeSubDomains(false)
+		}
+	}
 
-    def "http/headers/frame-options@policy=SAMEORIGIN"() {
-        setup:
-            loadConfig(FrameOptionsSameOriginConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            responseHeaders == ['X-Frame-Options': 'SAMEORIGIN']
-    }
+	def "http/headers/frame-options@policy=SAMEORIGIN"() {
+		setup:
+			loadConfig(FrameOptionsSameOriginConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			responseHeaders == ['X-Frame-Options': 'SAMEORIGIN']
+	}
 
-    @Configuration
-    static class FrameOptionsSameOriginConfig extends BaseWebConfig {
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .headers()
-                    // frame-options@policy=SAMEORIGIN
-                    .defaultsDisabled()
-                    .frameOptions()
-                        .sameOrigin()
-        }
-    }
+	@Configuration
+	static class FrameOptionsSameOriginConfig extends BaseWebConfig {
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.headers()
+					// frame-options@policy=SAMEORIGIN
+					.defaultsDisabled()
+					.frameOptions()
+						.sameOrigin()
+		}
+	}
 
-    // frame-options@strategy, frame-options@value, frame-options@parameter are not provided instead use frame-options@ref
+	// frame-options@strategy, frame-options@value, frame-options@parameter are not provided instead use frame-options@ref
 
-    def "http/headers/frame-options"() {
-        setup:
-            loadConfig(FrameOptionsAllowFromConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            responseHeaders == ['X-Frame-Options': 'ALLOW-FROM https://example.com']
-    }
+	def "http/headers/frame-options"() {
+		setup:
+			loadConfig(FrameOptionsAllowFromConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			responseHeaders == ['X-Frame-Options': 'ALLOW-FROM https://example.com']
+	}
 
 
-    @Configuration
-    static class FrameOptionsAllowFromConfig extends BaseWebConfig {
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .headers()
-                    // frame-options@ref
-                    .defaultsDisabled()
-                    .addHeaderWriter(new XFrameOptionsHeaderWriter(new StaticAllowFromStrategy(new URI("https://example.com"))))
-        }
-    }
+	@Configuration
+	static class FrameOptionsAllowFromConfig extends BaseWebConfig {
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.headers()
+					// frame-options@ref
+					.defaultsDisabled()
+					.addHeaderWriter(new XFrameOptionsHeaderWriter(new StaticAllowFromStrategy(new URI("https://example.com"))))
+		}
+	}
 
-    def "http/headers/xss-protection"() {
-        setup:
-            loadConfig(XssProtectionConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            responseHeaders == ['X-XSS-Protection': '1; mode=block']
-    }
+	def "http/headers/xss-protection"() {
+		setup:
+			loadConfig(XssProtectionConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			responseHeaders == ['X-XSS-Protection': '1; mode=block']
+	}
 
-    @Configuration
-    static class XssProtectionConfig extends BaseWebConfig {
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .headers()
-                    // xss-protection
-                    .defaultsDisabled()
-                    .xssProtection()
-        }
-    }
+	@Configuration
+	static class XssProtectionConfig extends BaseWebConfig {
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.headers()
+					// xss-protection
+					.defaultsDisabled()
+					.xssProtection()
+		}
+	}
 
-    def "http/headers/xss-protection custom"() {
-        setup:
-            loadConfig(XssProtectionCustomConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            responseHeaders == ['X-XSS-Protection': '1']
-    }
+	def "http/headers/xss-protection custom"() {
+		setup:
+			loadConfig(XssProtectionCustomConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			responseHeaders == ['X-XSS-Protection': '1']
+	}
 
-    @Configuration
-    static class XssProtectionCustomConfig extends BaseWebConfig {
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .headers()
-                    // xss-protection@enabled and xss-protection@block
-                    .defaultsDisabled()
-                    .xssProtection()
-                        .xssProtectionEnabled(true)
-                        .block(false)
-        }
-    }
+	@Configuration
+	static class XssProtectionCustomConfig extends BaseWebConfig {
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.headers()
+					// xss-protection@enabled and xss-protection@block
+					.defaultsDisabled()
+					.xssProtection()
+						.xssProtectionEnabled(true)
+						.block(false)
+		}
+	}
 
-    def "http/headers/content-type-options"() {
-        setup:
-            loadConfig(ContentTypeOptionsConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            responseHeaders == ['X-Content-Type-Options': 'nosniff']
-    }
+	def "http/headers/content-type-options"() {
+		setup:
+			loadConfig(ContentTypeOptionsConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			responseHeaders == ['X-Content-Type-Options': 'nosniff']
+	}
 
-    @Configuration
-    static class ContentTypeOptionsConfig extends BaseWebConfig {
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .headers()
-                    // content-type-options
-                    .defaultsDisabled()
-                    .contentTypeOptions()
-        }
-    }
+	@Configuration
+	static class ContentTypeOptionsConfig extends BaseWebConfig {
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.headers()
+					// content-type-options
+					.defaultsDisabled()
+					.contentTypeOptions()
+		}
+	}
 
-    // header@name / header@value are not provided instead use header@ref
+	// header@name / header@value are not provided instead use header@ref
 
-    def "http/headers/header@ref"() {
-        setup:
-            loadConfig(HeaderRefConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            responseHeaders == ['customHeaderName': 'customHeaderValue']
-    }
+	def "http/headers/header@ref"() {
+		setup:
+			loadConfig(HeaderRefConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			responseHeaders == ['customHeaderName': 'customHeaderValue']
+	}
 
-    @Configuration
-    static class HeaderRefConfig extends BaseWebConfig {
-        @Override
-        protected void configure(HttpSecurity http) {
-            http
-                .headers()
-                    .defaultsDisabled()
-                    .addHeaderWriter(new StaticHeadersWriter("customHeaderName", "customHeaderValue"))
-        }
-    }
+	@Configuration
+	static class HeaderRefConfig extends BaseWebConfig {
+		@Override
+		protected void configure(HttpSecurity http) {
+			http
+				.headers()
+					.defaultsDisabled()
+					.addHeaderWriter(new StaticHeadersWriter("customHeaderName", "customHeaderValue"))
+		}
+	}
 
 }

+ 118 - 118
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpInterceptUrlTests.groovy

@@ -42,128 +42,128 @@ import org.springframework.security.web.context.HttpSessionSecurityContextReposi
  */
 public class NamespaceHttpInterceptUrlTests extends BaseSpringSpec {
 
-    def "http/intercept-url denied when not logged in"() {
-        setup:
-            loadConfig(HttpInterceptUrlConfig)
-            request.servletPath == "/users"
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_FORBIDDEN
-    }
+	def "http/intercept-url denied when not logged in"() {
+		setup:
+			loadConfig(HttpInterceptUrlConfig)
+			request.servletPath == "/users"
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_FORBIDDEN
+	}
 
-    def "http/intercept-url denied when logged in"() {
-        setup:
-            loadConfig(HttpInterceptUrlConfig)
-            login()
-            request.setServletPath("/users")
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_FORBIDDEN
-    }
+	def "http/intercept-url denied when logged in"() {
+		setup:
+			loadConfig(HttpInterceptUrlConfig)
+			login()
+			request.setServletPath("/users")
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_FORBIDDEN
+	}
 
-    def "http/intercept-url allowed when logged in"() {
-        setup:
-            loadConfig(HttpInterceptUrlConfig)
-            login("admin","ROLE_ADMIN")
-            request.setServletPath("/users")
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_OK
-            !response.isCommitted()
-    }
+	def "http/intercept-url allowed when logged in"() {
+		setup:
+			loadConfig(HttpInterceptUrlConfig)
+			login("admin","ROLE_ADMIN")
+			request.setServletPath("/users")
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_OK
+			!response.isCommitted()
+	}
 
-    def "http/intercept-url@method=POST"() {
-        setup:
-            loadConfig(HttpInterceptUrlConfig)
-        when:
-            login()
-            request.setServletPath("/admin/post")
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_OK
-            !response.isCommitted()
-        when:
-            super.setup()
-            login()
-            request.setServletPath("/admin/post")
-            request.setMethod("POST")
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_FORBIDDEN
-        when:
-            super.setup()
-            login("admin","ROLE_ADMIN")
-            request.setServletPath("/admin/post")
-            request.setMethod("POST")
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_OK
-            !response.committed
-    }
+	def "http/intercept-url@method=POST"() {
+		setup:
+			loadConfig(HttpInterceptUrlConfig)
+		when:
+			login()
+			request.setServletPath("/admin/post")
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_OK
+			!response.isCommitted()
+		when:
+			super.setup()
+			login()
+			request.setServletPath("/admin/post")
+			request.setMethod("POST")
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_FORBIDDEN
+		when:
+			super.setup()
+			login("admin","ROLE_ADMIN")
+			request.setServletPath("/admin/post")
+			request.setMethod("POST")
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_OK
+			!response.committed
+	}
 
-    def "http/intercept-url@requires-channel"() {
-        setup:
-            loadConfig(HttpInterceptUrlConfig)
-        when:
-            request.setServletPath("/login")
-            request.setRequestURI("/login")
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.redirectedUrl == "https://localhost/login"
-        when:
-            super.setup()
-            request.setServletPath("/secured/a")
-            request.setRequestURI("/secured/a")
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.redirectedUrl == "https://localhost/secured/a"
-        when:
-            super.setup()
-            request.setSecure(true)
-            request.setScheme("https")
-            request.setServletPath("/user")
-            request.setRequestURI("/user")
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.redirectedUrl == "http://localhost/user"
-    }
+	def "http/intercept-url@requires-channel"() {
+		setup:
+			loadConfig(HttpInterceptUrlConfig)
+		when:
+			request.setServletPath("/login")
+			request.setRequestURI("/login")
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.redirectedUrl == "https://localhost/login"
+		when:
+			super.setup()
+			request.setServletPath("/secured/a")
+			request.setRequestURI("/secured/a")
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.redirectedUrl == "https://localhost/secured/a"
+		when:
+			super.setup()
+			request.setSecure(true)
+			request.setScheme("https")
+			request.setServletPath("/user")
+			request.setRequestURI("/user")
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.redirectedUrl == "http://localhost/user"
+	}
 
-    @EnableWebSecurity
-    static class HttpInterceptUrlConfig extends WebSecurityConfigurerAdapter {
+	@EnableWebSecurity
+	static class HttpInterceptUrlConfig extends WebSecurityConfigurerAdapter {
 
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    // the line below is similar to intercept-url@pattern:
-                    //    <intercept-url pattern="/users**" access="hasRole('ROLE_ADMIN')"/>
-                    //    <intercept-url pattern="/sessions/**" access="hasRole('ROLE_ADMIN')"/>
-                    .antMatchers("/users**","/sessions/**").hasRole("ADMIN")
-                    // the line below is similar to intercept-url@method:
-                    //    <intercept-url pattern="/admin/post" access="hasRole('ROLE_ADMIN')" method="POST"/>
-                    //    <intercept-url pattern="/admin/another-post/**" access="hasRole('ROLE_ADMIN')" method="POST"/>
-                    .antMatchers(HttpMethod.POST, "/admin/post","/admin/another-post/**").hasRole("ADMIN")
-                    .antMatchers("/signup").permitAll()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .requiresChannel()
-                    // NOTE: channel security is configured separately of authorization (i.e. intercept-url@access
-                    // the line below is similar to intercept-url@requires-channel="https":
-                    //    <intercept-url pattern="/login" requires-channel="https"/>
-                    //    <intercept-url pattern="/secured/**" requires-channel="https"/>
-                    .antMatchers("/login","/secured/**").requiresSecure()
-                    // the line below is similar to intercept-url@requires-channel="http":
-                    //    <intercept-url pattern="/**" requires-channel="http"/>
-                    .anyRequest().requiresInsecure()
-        }
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER").and()
-                    .withUser("admin").password("password").roles("USER", "ADMIN")
-        }
-    }
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					// the line below is similar to intercept-url@pattern:
+					//    <intercept-url pattern="/users**" access="hasRole('ROLE_ADMIN')"/>
+					//    <intercept-url pattern="/sessions/**" access="hasRole('ROLE_ADMIN')"/>
+					.antMatchers("/users**","/sessions/**").hasRole("ADMIN")
+					// the line below is similar to intercept-url@method:
+					//    <intercept-url pattern="/admin/post" access="hasRole('ROLE_ADMIN')" method="POST"/>
+					//    <intercept-url pattern="/admin/another-post/**" access="hasRole('ROLE_ADMIN')" method="POST"/>
+					.antMatchers(HttpMethod.POST, "/admin/post","/admin/another-post/**").hasRole("ADMIN")
+					.antMatchers("/signup").permitAll()
+					.anyRequest().hasRole("USER")
+					.and()
+				.requiresChannel()
+					// NOTE: channel security is configured separately of authorization (i.e. intercept-url@access
+					// the line below is similar to intercept-url@requires-channel="https":
+					//    <intercept-url pattern="/login" requires-channel="https"/>
+					//    <intercept-url pattern="/secured/**" requires-channel="https"/>
+					.antMatchers("/login","/secured/**").requiresSecure()
+					// the line below is similar to intercept-url@requires-channel="http":
+					//    <intercept-url pattern="/**" requires-channel="http"/>
+					.anyRequest().requiresInsecure()
+		}
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER").and()
+					.withUser("admin").password("password").roles("USER", "ADMIN")
+		}
+	}
 }

+ 54 - 54
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpJeeTests.groovy

@@ -80,64 +80,64 @@ import org.springframework.test.util.ReflectionTestUtils;
  */
 public class NamespaceHttpJeeTests extends BaseSpringSpec {
 
-    def "http/jee@mappable-roles"() {
-        when:
-            loadConfig(JeeMappableRolesConfig)
-            J2eePreAuthenticatedProcessingFilter filter = findFilter(J2eePreAuthenticatedProcessingFilter)
-            AuthenticationManager authenticationManager = ReflectionTestUtils.getField(filter,"authenticationManager")
-        then:
-            authenticationManager
-            filter.authenticationDetailsSource.class == J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
-            filter.authenticationDetailsSource.j2eeMappableRoles == ["ROLE_USER", "ROLE_ADMIN"] as Set
-            authenticationManager.providers.find { it instanceof PreAuthenticatedAuthenticationProvider }.preAuthenticatedUserDetailsService.class == PreAuthenticatedGrantedAuthoritiesUserDetailsService
-    }
+	def "http/jee@mappable-roles"() {
+		when:
+			loadConfig(JeeMappableRolesConfig)
+			J2eePreAuthenticatedProcessingFilter filter = findFilter(J2eePreAuthenticatedProcessingFilter)
+			AuthenticationManager authenticationManager = ReflectionTestUtils.getField(filter,"authenticationManager")
+		then:
+			authenticationManager
+			filter.authenticationDetailsSource.class == J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
+			filter.authenticationDetailsSource.j2eeMappableRoles == ["ROLE_USER", "ROLE_ADMIN"] as Set
+			authenticationManager.providers.find { it instanceof PreAuthenticatedAuthenticationProvider }.preAuthenticatedUserDetailsService.class == PreAuthenticatedGrantedAuthoritiesUserDetailsService
+	}
 
-    @EnableWebSecurity
-    public static class JeeMappableRolesConfig extends WebSecurityConfigurerAdapter {
+	@EnableWebSecurity
+	public static class JeeMappableRolesConfig extends WebSecurityConfigurerAdapter {
 
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .jee()
-                    .mappableRoles("USER","ADMIN");
-        }
-    }
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.jee()
+					.mappableRoles("USER","ADMIN");
+		}
+	}
 
-    def "http/jee@user-service-ref"() {
-        when:
-            loadConfig(JeeUserServiceRefConfig)
-            J2eePreAuthenticatedProcessingFilter filter = findFilter(J2eePreAuthenticatedProcessingFilter)
-            AuthenticationManager authenticationManager = ReflectionTestUtils.getField(filter,"authenticationManager")
-        then:
-            authenticationManager
-            filter.authenticationDetailsSource.class == J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
-            filter.authenticationDetailsSource.j2eeMappableRoles == ["ROLE_USER", "ROLE_ADMIN"] as Set
-            authenticationManager.providers.find { it instanceof PreAuthenticatedAuthenticationProvider }.preAuthenticatedUserDetailsService.class == CustomUserService
-    }
+	def "http/jee@user-service-ref"() {
+		when:
+			loadConfig(JeeUserServiceRefConfig)
+			J2eePreAuthenticatedProcessingFilter filter = findFilter(J2eePreAuthenticatedProcessingFilter)
+			AuthenticationManager authenticationManager = ReflectionTestUtils.getField(filter,"authenticationManager")
+		then:
+			authenticationManager
+			filter.authenticationDetailsSource.class == J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
+			filter.authenticationDetailsSource.j2eeMappableRoles == ["ROLE_USER", "ROLE_ADMIN"] as Set
+			authenticationManager.providers.find { it instanceof PreAuthenticatedAuthenticationProvider }.preAuthenticatedUserDetailsService.class == CustomUserService
+	}
 
-    @EnableWebSecurity
-    public static class JeeUserServiceRefConfig extends WebSecurityConfigurerAdapter {
+	@EnableWebSecurity
+	public static class JeeUserServiceRefConfig extends WebSecurityConfigurerAdapter {
 
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .jee()
-                    .mappableAuthorities("ROLE_USER","ROLE_ADMIN")
-                    .authenticatedUserDetailsService(new CustomUserService());
-        }
-    }
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.jee()
+					.mappableAuthorities("ROLE_USER","ROLE_ADMIN")
+					.authenticatedUserDetailsService(new CustomUserService());
+		}
+	}
 
-    static class CustomUserService implements AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {
-        public UserDetails loadUserDetails(
-                PreAuthenticatedAuthenticationToken token)
-                throws UsernameNotFoundException {
-            return null;
-        }
-    }
+	static class CustomUserService implements AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {
+		public UserDetails loadUserDetails(
+				PreAuthenticatedAuthenticationToken token)
+				throws UsernameNotFoundException {
+			return null;
+		}
+	}
 }

+ 79 - 79
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.groovy

@@ -72,90 +72,90 @@ import org.springframework.security.web.util.matcher.RequestMatcher
  */
 public class NamespaceHttpLogoutTests extends BaseSpringSpec {
 
-    def "http/logout"() {
-        setup:
-            loadConfig(HttpLogoutConfig)
-            login()
-            request.servletPath = "/logout"
-            request.method = "POST"
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            !authenticated()
-            !request.getSession(false)
-            response.redirectedUrl == "/login?logout"
-            !response.getCookies()
-    }
+	def "http/logout"() {
+		setup:
+			loadConfig(HttpLogoutConfig)
+			login()
+			request.servletPath = "/logout"
+			request.method = "POST"
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			!authenticated()
+			!request.getSession(false)
+			response.redirectedUrl == "/login?logout"
+			!response.getCookies()
+	}
 
-    @Configuration
-    static class HttpLogoutConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-        }
-    }
+	@Configuration
+	static class HttpLogoutConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+		}
+	}
 
-    def "http/logout custom"() {
-        setup:
-            loadConfig(CustomHttpLogoutConfig)
-            login()
-            request.servletPath = "/custom-logout"
-            request.method = "POST"
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            !authenticated()
-            request.getSession(false)
-            response.redirectedUrl == "/logout-success"
-            response.getCookies().length == 1
-            response.getCookies()[0].name == "remove"
-            response.getCookies()[0].maxAge == 0
-    }
+	def "http/logout custom"() {
+		setup:
+			loadConfig(CustomHttpLogoutConfig)
+			login()
+			request.servletPath = "/custom-logout"
+			request.method = "POST"
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			!authenticated()
+			request.getSession(false)
+			response.redirectedUrl == "/logout-success"
+			response.getCookies().length == 1
+			response.getCookies()[0].name == "remove"
+			response.getCookies()[0].maxAge == 0
+	}
 
-    @Configuration
-    static class CustomHttpLogoutConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .logout()
-                    .deleteCookies("remove") // logout@delete-cookies
-                    .invalidateHttpSession(false) // logout@invalidate-session=false (default is true)
-                    .logoutUrl("/custom-logout") // logout@logout-url (default is /logout)
-                    .logoutSuccessUrl("/logout-success") // logout@success-url (default is /login?logout)
-        }
-    }
+	@Configuration
+	static class CustomHttpLogoutConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.logout()
+					.deleteCookies("remove") // logout@delete-cookies
+					.invalidateHttpSession(false) // logout@invalidate-session=false (default is true)
+					.logoutUrl("/custom-logout") // logout@logout-url (default is /logout)
+					.logoutSuccessUrl("/logout-success") // logout@success-url (default is /login?logout)
+		}
+	}
 
-    def "http/logout@success-handler-ref"() {
-        setup:
-            loadConfig(SuccessHandlerRefHttpLogoutConfig)
-            login()
-            request.servletPath = "/logout"
-            request.method = "POST"
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            !authenticated()
-            !request.getSession(false)
-            response.redirectedUrl == "/SuccessHandlerRefHttpLogoutConfig"
-            !response.getCookies()
-    }
+	def "http/logout@success-handler-ref"() {
+		setup:
+			loadConfig(SuccessHandlerRefHttpLogoutConfig)
+			login()
+			request.servletPath = "/logout"
+			request.method = "POST"
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			!authenticated()
+			!request.getSession(false)
+			response.redirectedUrl == "/SuccessHandlerRefHttpLogoutConfig"
+			!response.getCookies()
+	}
 
-    @Configuration
-    static class SuccessHandlerRefHttpLogoutConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            SimpleUrlLogoutSuccessHandler logoutSuccessHandler = new SimpleUrlLogoutSuccessHandler(defaultTargetUrl:"/SuccessHandlerRefHttpLogoutConfig")
-            http
-                .logout()
-                    .logoutSuccessHandler(logoutSuccessHandler)
-        }
-    }
+	@Configuration
+	static class SuccessHandlerRefHttpLogoutConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			SimpleUrlLogoutSuccessHandler logoutSuccessHandler = new SimpleUrlLogoutSuccessHandler(defaultTargetUrl:"/SuccessHandlerRefHttpLogoutConfig")
+			http
+				.logout()
+					.logoutSuccessHandler(logoutSuccessHandler)
+		}
+	}
 
-    def login(String username="user", String role="ROLE_USER") {
-        HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository()
-        HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
-        repo.loadContext(requestResponseHolder)
-        repo.saveContext(new SecurityContextImpl(authentication: new UsernamePasswordAuthenticationToken(username, null, AuthorityUtils.createAuthorityList(role))), requestResponseHolder.request, requestResponseHolder.response)
-    }
+	def login(String username="user", String role="ROLE_USER") {
+		HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository()
+		HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
+		repo.loadContext(requestResponseHolder)
+		repo.saveContext(new SecurityContextImpl(authentication: new UsernamePasswordAuthenticationToken(username, null, AuthorityUtils.createAuthorityList(role))), requestResponseHolder.request, requestResponseHolder.response)
+	}
 
-    def authenticated() {
-        HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
-        new HttpSessionSecurityContextRepository().loadContext(requestResponseHolder)?.authentication?.authenticated
-    }
+	def authenticated() {
+		HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
+		new HttpSessionSecurityContextRepository().loadContext(requestResponseHolder)?.authentication?.authenticated
+	}
 }

+ 181 - 181
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpOpenIDLoginTests.groovy

@@ -44,185 +44,185 @@ import org.springframework.security.web.authentication.WebAuthenticationDetailsS
  *
  */
 public class NamespaceHttpOpenIDLoginTests extends BaseSpringSpec {
-    def "http/openid-login"() {
-        when:
-            loadConfig(OpenIDLoginConfig)
-        then:
-            findFilter(OpenIDAuthenticationFilter).consumer.class == OpenID4JavaConsumer
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.getRedirectedUrl() == "http://localhost/login"
-        when: "fail to log in"
-            super.setup()
-            request.servletPath = "/login/openid"
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to login error page"
-            response.getRedirectedUrl() == "/login?error"
-    }
-
-    @Configuration
-    static class OpenIDLoginConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .openidLogin()
-                    .permitAll();
-        }
-    }
-
-    def "http/openid-login/attribute-exchange"() {
-        when:
-            loadConfig(OpenIDLoginAttributeExchangeConfig)
-            OpenID4JavaConsumer consumer = findFilter(OpenIDAuthenticationFilter).consumer
-        then:
-            consumer.class == OpenID4JavaConsumer
-
-            def googleAttrs = consumer.attributesToFetchFactory.createAttributeList("https://www.google.com/1")
-            googleAttrs[0].name == "email"
-            googleAttrs[0].type == "http://axschema.org/contact/email"
-            googleAttrs[0].required
-            googleAttrs[1].name == "firstname"
-            googleAttrs[1].type == "http://axschema.org/namePerson/first"
-            googleAttrs[1].required
-            googleAttrs[2].name == "lastname"
-            googleAttrs[2].type == "http://axschema.org/namePerson/last"
-            googleAttrs[2].required
-
-            def yahooAttrs = consumer.attributesToFetchFactory.createAttributeList("https://rwinch.yahoo.com/rwinch/id")
-            yahooAttrs[0].name == "email"
-            yahooAttrs[0].type == "http://schema.openid.net/contact/email"
-            yahooAttrs[0].required
-            yahooAttrs[1].name == "fullname"
-            yahooAttrs[1].type == "http://axschema.org/namePerson"
-            yahooAttrs[1].required
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.getRedirectedUrl() == "http://localhost/login"
-        when: "fail to log in"
-            super.setup()
-            request.servletPath = "/login/openid"
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to login error page"
-            response.getRedirectedUrl() == "/login?error"
-    }
-
-    @Configuration
-    static class OpenIDLoginAttributeExchangeConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .openidLogin()
-                    .attributeExchange("https://www.google.com/.*") // attribute-exchange@identifier-match
-                        .attribute("email") // openid-attribute@name
-                            .type("http://axschema.org/contact/email") // openid-attribute@type
-                            .required(true) // openid-attribute@required
-                            .count(1) // openid-attribute@count
-                            .and()
-                        .attribute("firstname")
-                            .type("http://axschema.org/namePerson/first")
-                            .required(true)
-                            .and()
-                        .attribute("lastname")
-                            .type("http://axschema.org/namePerson/last")
-                            .required(true)
-                            .and()
-                        .and()
-                    .attributeExchange(".*yahoo.com.*")
-                        .attribute("email")
-                            .type("http://schema.openid.net/contact/email")
-                            .required(true)
-                            .and()
-                        .attribute("fullname")
-                            .type("http://axschema.org/namePerson")
-                            .required(true)
-                            .and()
-                        .and()
-                    .permitAll();
-        }
-    }
-
-    def "http/openid-login custom"() {
-        setup:
-            loadConfig(OpenIDLoginCustomConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.getRedirectedUrl() == "http://localhost/authentication/login"
-        when: "fail to log in"
-            super.setup()
-            request.servletPath = "/authentication/login/process"
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to login error page"
-            response.getRedirectedUrl() == "/authentication/login?failed"
-    }
-
-    @Configuration
-    static class OpenIDLoginCustomConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            boolean alwaysUseDefaultSuccess = true;
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .openidLogin()
-                    .permitAll()
-                    .loginPage("/authentication/login") // openid-login@login-page
-                    .failureUrl("/authentication/login?failed") // openid-login@authentication-failure-url
-                    .loginProcessingUrl("/authentication/login/process") // openid-login@login-processing-url
-                    .defaultSuccessUrl("/default", alwaysUseDefaultSuccess) // openid-login@default-target-url / openid-login@always-use-default-target
-        }
-    }
-
-    def "http/openid-login custom refs"() {
-        when:
-            OpenIDLoginCustomRefsConfig.AUDS = Mock(AuthenticationUserDetailsService)
-            loadConfig(OpenIDLoginCustomRefsConfig)
-        then: "CustomWebAuthenticationDetailsSource is used"
-            findFilter(OpenIDAuthenticationFilter).authenticationDetailsSource.class == CustomWebAuthenticationDetailsSource
-            findAuthenticationProvider(OpenIDAuthenticationProvider).userDetailsService == OpenIDLoginCustomRefsConfig.AUDS
-        when: "fail to log in"
-            request.servletPath = "/login/openid"
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to login error page"
-            response.getRedirectedUrl() == "/custom/failure"
-    }
-
-    @Configuration
-    static class OpenIDLoginCustomRefsConfig extends BaseWebConfig {
-        static AuthenticationUserDetailsService AUDS
-
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .openidLogin()
-                    // if using UserDetailsService wrap with new UserDetailsByNameServiceWrapper<OpenIDAuthenticationToken>()
-                    .authenticationUserDetailsService(AUDS) // openid-login@user-service-ref
-                    .failureHandler(new SimpleUrlAuthenticationFailureHandler("/custom/failure")) // openid-login@authentication-failure-handler-ref
-                    .successHandler(new SavedRequestAwareAuthenticationSuccessHandler( defaultTargetUrl : "/custom/targetUrl" )) // openid-login@authentication-success-handler-ref
-                    .authenticationDetailsSource(new CustomWebAuthenticationDetailsSource()); // openid-login@authentication-details-source-ref
-        }
-
-        // only necessary to have easy access to the AuthenticationManager for testing/verification
-        @Bean
-        @Override
-        public AuthenticationManager authenticationManagerBean()
-                throws Exception {
-            return super.authenticationManagerBean();
-        }
-
-    }
-
-    static class CustomWebAuthenticationDetailsSource extends WebAuthenticationDetailsSource {}
+	def "http/openid-login"() {
+		when:
+			loadConfig(OpenIDLoginConfig)
+		then:
+			findFilter(OpenIDAuthenticationFilter).consumer.class == OpenID4JavaConsumer
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.getRedirectedUrl() == "http://localhost/login"
+		when: "fail to log in"
+			super.setup()
+			request.servletPath = "/login/openid"
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to login error page"
+			response.getRedirectedUrl() == "/login?error"
+	}
+
+	@Configuration
+	static class OpenIDLoginConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.openidLogin()
+					.permitAll();
+		}
+	}
+
+	def "http/openid-login/attribute-exchange"() {
+		when:
+			loadConfig(OpenIDLoginAttributeExchangeConfig)
+			OpenID4JavaConsumer consumer = findFilter(OpenIDAuthenticationFilter).consumer
+		then:
+			consumer.class == OpenID4JavaConsumer
+
+			def googleAttrs = consumer.attributesToFetchFactory.createAttributeList("https://www.google.com/1")
+			googleAttrs[0].name == "email"
+			googleAttrs[0].type == "http://axschema.org/contact/email"
+			googleAttrs[0].required
+			googleAttrs[1].name == "firstname"
+			googleAttrs[1].type == "http://axschema.org/namePerson/first"
+			googleAttrs[1].required
+			googleAttrs[2].name == "lastname"
+			googleAttrs[2].type == "http://axschema.org/namePerson/last"
+			googleAttrs[2].required
+
+			def yahooAttrs = consumer.attributesToFetchFactory.createAttributeList("https://rwinch.yahoo.com/rwinch/id")
+			yahooAttrs[0].name == "email"
+			yahooAttrs[0].type == "http://schema.openid.net/contact/email"
+			yahooAttrs[0].required
+			yahooAttrs[1].name == "fullname"
+			yahooAttrs[1].type == "http://axschema.org/namePerson"
+			yahooAttrs[1].required
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.getRedirectedUrl() == "http://localhost/login"
+		when: "fail to log in"
+			super.setup()
+			request.servletPath = "/login/openid"
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to login error page"
+			response.getRedirectedUrl() == "/login?error"
+	}
+
+	@Configuration
+	static class OpenIDLoginAttributeExchangeConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.openidLogin()
+					.attributeExchange("https://www.google.com/.*") // attribute-exchange@identifier-match
+						.attribute("email") // openid-attribute@name
+							.type("http://axschema.org/contact/email") // openid-attribute@type
+							.required(true) // openid-attribute@required
+							.count(1) // openid-attribute@count
+							.and()
+						.attribute("firstname")
+							.type("http://axschema.org/namePerson/first")
+							.required(true)
+							.and()
+						.attribute("lastname")
+							.type("http://axschema.org/namePerson/last")
+							.required(true)
+							.and()
+						.and()
+					.attributeExchange(".*yahoo.com.*")
+						.attribute("email")
+							.type("http://schema.openid.net/contact/email")
+							.required(true)
+							.and()
+						.attribute("fullname")
+							.type("http://axschema.org/namePerson")
+							.required(true)
+							.and()
+						.and()
+					.permitAll();
+		}
+	}
+
+	def "http/openid-login custom"() {
+		setup:
+			loadConfig(OpenIDLoginCustomConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.getRedirectedUrl() == "http://localhost/authentication/login"
+		when: "fail to log in"
+			super.setup()
+			request.servletPath = "/authentication/login/process"
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to login error page"
+			response.getRedirectedUrl() == "/authentication/login?failed"
+	}
+
+	@Configuration
+	static class OpenIDLoginCustomConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			boolean alwaysUseDefaultSuccess = true;
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.openidLogin()
+					.permitAll()
+					.loginPage("/authentication/login") // openid-login@login-page
+					.failureUrl("/authentication/login?failed") // openid-login@authentication-failure-url
+					.loginProcessingUrl("/authentication/login/process") // openid-login@login-processing-url
+					.defaultSuccessUrl("/default", alwaysUseDefaultSuccess) // openid-login@default-target-url / openid-login@always-use-default-target
+		}
+	}
+
+	def "http/openid-login custom refs"() {
+		when:
+			OpenIDLoginCustomRefsConfig.AUDS = Mock(AuthenticationUserDetailsService)
+			loadConfig(OpenIDLoginCustomRefsConfig)
+		then: "CustomWebAuthenticationDetailsSource is used"
+			findFilter(OpenIDAuthenticationFilter).authenticationDetailsSource.class == CustomWebAuthenticationDetailsSource
+			findAuthenticationProvider(OpenIDAuthenticationProvider).userDetailsService == OpenIDLoginCustomRefsConfig.AUDS
+		when: "fail to log in"
+			request.servletPath = "/login/openid"
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to login error page"
+			response.getRedirectedUrl() == "/custom/failure"
+	}
+
+	@Configuration
+	static class OpenIDLoginCustomRefsConfig extends BaseWebConfig {
+		static AuthenticationUserDetailsService AUDS
+
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.openidLogin()
+					// if using UserDetailsService wrap with new UserDetailsByNameServiceWrapper<OpenIDAuthenticationToken>()
+					.authenticationUserDetailsService(AUDS) // openid-login@user-service-ref
+					.failureHandler(new SimpleUrlAuthenticationFailureHandler("/custom/failure")) // openid-login@authentication-failure-handler-ref
+					.successHandler(new SavedRequestAwareAuthenticationSuccessHandler( defaultTargetUrl : "/custom/targetUrl" )) // openid-login@authentication-success-handler-ref
+					.authenticationDetailsSource(new CustomWebAuthenticationDetailsSource()); // openid-login@authentication-details-source-ref
+		}
+
+		// only necessary to have easy access to the AuthenticationManager for testing/verification
+		@Bean
+		@Override
+		public AuthenticationManager authenticationManagerBean()
+				throws Exception {
+			return super.authenticationManagerBean();
+		}
+
+	}
+
+	static class CustomWebAuthenticationDetailsSource extends WebAuthenticationDetailsSource {}
 }

+ 68 - 68
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpPortMappingsTests.groovy

@@ -38,78 +38,78 @@ import org.springframework.security.web.context.HttpSessionSecurityContextReposi
  *
  */
 public class NamespaceHttpPortMappingsTests extends BaseSpringSpec {
-    FilterChainProxy springSecurityFilterChain
-    MockHttpServletRequest request
-    MockHttpServletResponse response
-    MockFilterChain chain
+	FilterChainProxy springSecurityFilterChain
+	MockHttpServletRequest request
+	MockHttpServletResponse response
+	MockFilterChain chain
 
-    def setup() {
-        request = new MockHttpServletRequest()
-        request.setMethod("GET")
-        response = new MockHttpServletResponse()
-        chain = new MockFilterChain()
-    }
+	def setup() {
+		request = new MockHttpServletRequest()
+		request.setMethod("GET")
+		response = new MockHttpServletResponse()
+		chain = new MockFilterChain()
+	}
 
-    def "http/port-mapper works with http/intercept-url@requires-channel"() {
-        setup:
-            loadConfig(HttpInterceptUrlWithPortMapperConfig)
-            springSecurityFilterChain = context.getBean(FilterChainProxy)
-        when:
-            request.setServletPath("/login")
-            request.setRequestURI("/login")
-            request.setServerPort(9080);
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.redirectedUrl == "https://localhost:9443/login"
-        when:
-            setup()
-            request.setServletPath("/secured/a")
-            request.setRequestURI("/secured/a")
-            request.setServerPort(9080);
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.redirectedUrl == "https://localhost:9443/secured/a"
-        when:
-            setup()
-            request.setSecure(true)
-            request.setScheme("https")
-            request.setServerPort(9443);
-            request.setServletPath("/user")
-            request.setRequestURI("/user")
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.redirectedUrl == "http://localhost:9080/user"
-    }
+	def "http/port-mapper works with http/intercept-url@requires-channel"() {
+		setup:
+			loadConfig(HttpInterceptUrlWithPortMapperConfig)
+			springSecurityFilterChain = context.getBean(FilterChainProxy)
+		when:
+			request.setServletPath("/login")
+			request.setRequestURI("/login")
+			request.setServerPort(9080);
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.redirectedUrl == "https://localhost:9443/login"
+		when:
+			setup()
+			request.setServletPath("/secured/a")
+			request.setRequestURI("/secured/a")
+			request.setServerPort(9080);
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.redirectedUrl == "https://localhost:9443/secured/a"
+		when:
+			setup()
+			request.setSecure(true)
+			request.setScheme("https")
+			request.setServerPort(9443);
+			request.setServletPath("/user")
+			request.setRequestURI("/user")
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.redirectedUrl == "http://localhost:9080/user"
+	}
 
-    @EnableWebSecurity
-    static class HttpInterceptUrlWithPortMapperConfig extends WebSecurityConfigurerAdapter {
+	@EnableWebSecurity
+	static class HttpInterceptUrlWithPortMapperConfig extends WebSecurityConfigurerAdapter {
 
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .portMapper()
-                    .http(9080).mapsTo(9443)
-                    .and()
-                .requiresChannel()
-                    .antMatchers("/login","/secured/**").requiresSecure()
-                    .anyRequest().requiresInsecure()
-        }
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.portMapper()
+					.http(9080).mapsTo(9443)
+					.and()
+				.requiresChannel()
+					.antMatchers("/login","/secured/**").requiresSecure()
+					.anyRequest().requiresInsecure()
+		}
 
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER").and()
-                    .withUser("admin").password("password").roles("USER", "ADMIN")
-        }
-    }
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER").and()
+					.withUser("admin").password("password").roles("USER", "ADMIN")
+		}
+	}
 
-    def login(String username="user", String role="ROLE_USER") {
-        HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository()
-        HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
-        repo.loadContext(requestResponseHolder)
-        repo.saveContext(new SecurityContextImpl(authentication: new UsernamePasswordAuthenticationToken(username, null, AuthorityUtils.createAuthorityList(role))), requestResponseHolder.request, requestResponseHolder.response)
-    }
+	def login(String username="user", String role="ROLE_USER") {
+		HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository()
+		HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
+		repo.loadContext(requestResponseHolder)
+		repo.saveContext(new SecurityContextImpl(authentication: new UsernamePasswordAuthenticationToken(username, null, AuthorityUtils.createAuthorityList(role))), requestResponseHolder.request, requestResponseHolder.response)
+	}
 }

+ 28 - 28
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpRequestCacheTests.groovy

@@ -39,35 +39,35 @@ import org.springframework.security.web.savedrequest.RequestCache;
  *
  */
 public class NamespaceHttpRequestCacheTests extends BaseSpringSpec {
-    def "http/request-cache@ref"() {
-        setup:
-            RequestCacheRefConfig.REQUEST_CACHE = Mock(RequestCache)
-        when:
-            loadConfig(RequestCacheRefConfig)
-        then:
-            findFilter(ExceptionTranslationFilter).requestCache == RequestCacheRefConfig.REQUEST_CACHE
-    }
+	def "http/request-cache@ref"() {
+		setup:
+			RequestCacheRefConfig.REQUEST_CACHE = Mock(RequestCache)
+		when:
+			loadConfig(RequestCacheRefConfig)
+		then:
+			findFilter(ExceptionTranslationFilter).requestCache == RequestCacheRefConfig.REQUEST_CACHE
+	}
 
-    @Configuration
-    static class RequestCacheRefConfig extends BaseWebConfig {
-        static RequestCache REQUEST_CACHE
-        protected void configure(HttpSecurity http) {
-            http.
-                requestCache()
-                    .requestCache(REQUEST_CACHE)
-        }
-    }
+	@Configuration
+	static class RequestCacheRefConfig extends BaseWebConfig {
+		static RequestCache REQUEST_CACHE
+		protected void configure(HttpSecurity http) {
+			http.
+				requestCache()
+					.requestCache(REQUEST_CACHE)
+		}
+	}
 
-    def "http/request-cache@ref defaults to HttpSessionRequestCache"() {
-        when:
-            loadConfig(DefaultRequestCacheRefConfig)
-        then:
-            findFilter(ExceptionTranslationFilter).requestCache.class == HttpSessionRequestCache
-    }
+	def "http/request-cache@ref defaults to HttpSessionRequestCache"() {
+		when:
+			loadConfig(DefaultRequestCacheRefConfig)
+		then:
+			findFilter(ExceptionTranslationFilter).requestCache.class == HttpSessionRequestCache
+	}
 
-    @Configuration
-    static class DefaultRequestCacheRefConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) {
-        }
-    }
+	@Configuration
+	static class DefaultRequestCacheRefConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) {
+		}
+	}
 }

+ 197 - 197
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpX509Tests.groovy

@@ -55,201 +55,201 @@ import org.springframework.test.util.ReflectionTestUtils
  *
  */
 public class NamespaceHttpX509Tests extends BaseSpringSpec {
-    def "http/x509 can authenticate"() {
-        setup:
-            X509Certificate certificate = loadCert("rod.cer")
-            loadConfig(X509Config)
-        when:
-            request.setAttribute("javax.servlet.request.X509Certificate", [certificate] as X509Certificate[] )
-            springSecurityFilterChain.doFilter(request, response, chain);
-        then:
-            response.status == 200
-            authentication().name == 'rod'
-    }
-
-    def "http/x509"() {
-        when:
-            loadConfig(X509Config)
-            X509AuthenticationFilter filter = findFilter(X509AuthenticationFilter)
-            AuthenticationManager authenticationManager = ReflectionTestUtils.getField(filter,"authenticationManager")
-        then:
-            authenticationManager
-            filter.authenticationDetailsSource.class == WebAuthenticationDetailsSource
-            authenticationManager.providers.find { it instanceof PreAuthenticatedAuthenticationProvider }.preAuthenticatedUserDetailsService.class == UserDetailsByNameServiceWrapper
-    }
-
-    @EnableWebSecurity
-    public static class X509Config extends WebSecurityConfigurerAdapter {
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth.
-                inMemoryAuthentication()
-                    .withUser("rod").password("password").roles("USER","ADMIN");
-        }
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .x509();
-        }
-    }
-
-    def "http/x509@authentication-details-source-ref"() {
-        setup:
-            AuthenticationDetailsSourceRefConfig.AUTHENTICATION_DETAILS_SOURCE = Mock(AuthenticationDetailsSource)
-        when:
-            loadConfig(AuthenticationDetailsSourceRefConfig)
-            X509AuthenticationFilter filter = findFilter(X509AuthenticationFilter)
-            AuthenticationManager authenticationManager = ReflectionTestUtils.getField(filter,"authenticationManager")
-        then:
-            authenticationManager
-            filter.authenticationDetailsSource == AuthenticationDetailsSourceRefConfig.AUTHENTICATION_DETAILS_SOURCE
-            authenticationManager.providers.find { it instanceof PreAuthenticatedAuthenticationProvider }.preAuthenticatedUserDetailsService.class == UserDetailsByNameServiceWrapper
-    }
-
-    @EnableWebSecurity
-    public static class AuthenticationDetailsSourceRefConfig extends WebSecurityConfigurerAdapter {
-        static AuthenticationDetailsSource<HttpServletRequest, PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails> AUTHENTICATION_DETAILS_SOURCE
-
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth.
-                inMemoryAuthentication()
-                    .withUser("rod").password("password").roles("USER","ADMIN");
-        }
-
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .x509()
-                    .authenticationDetailsSource(AUTHENTICATION_DETAILS_SOURCE);
-        }
-    }
-
-    def "http/x509@subject-principal-regex"() {
-        setup:
-            X509Certificate certificate = loadCert("rodatexampledotcom.cer")
-            loadConfig(SubjectPrincipalRegexConfig)
-        when:
-            request.setAttribute("javax.servlet.request.X509Certificate", [certificate] as X509Certificate[] )
-            springSecurityFilterChain.doFilter(request, response, chain);
-        then:
-            response.status == 200
-            authentication().name == 'rod'
-    }
-
-    @EnableWebSecurity
-    public static class SubjectPrincipalRegexConfig extends WebSecurityConfigurerAdapter {
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth.
-                inMemoryAuthentication()
-                    .withUser("rod").password("password").roles("USER","ADMIN");
-        }
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .x509()
-                    .subjectPrincipalRegex('CN=(.*?)@example.com(?:,|$)');
-        }
-    }
-
-    def "http/x509@user-service-ref"() {
-        setup:
-            X509Certificate certificate = loadCert("rodatexampledotcom.cer")
-            loadConfig(UserDetailsServiceRefConfig)
-        when:
-            request.setAttribute("javax.servlet.request.X509Certificate", [certificate] as X509Certificate[] )
-            springSecurityFilterChain.doFilter(request, response, chain);
-        then:
-            response.status == 200
-            authentication().name == 'customuser'
-    }
-
-    @EnableWebSecurity
-    public static class UserDetailsServiceRefConfig extends WebSecurityConfigurerAdapter {
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth.
-                inMemoryAuthentication()
-                    .withUser("rod").password("password").roles("USER","ADMIN");
-        }
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .x509()
-                    .userDetailsService(new CustomUserDetailsService());
-        }
-    }
-
-    def "http/x509 custom AuthenticationUserDetailsService"() {
-        setup:
-            X509Certificate certificate = loadCert("rodatexampledotcom.cer")
-            loadConfig(AuthenticationUserDetailsServiceConfig)
-        when:
-            request.setAttribute("javax.servlet.request.X509Certificate", [certificate] as X509Certificate[] )
-            springSecurityFilterChain.doFilter(request, response, chain);
-        then:
-            response.status == 200
-            authentication().name == 'customuser'
-    }
-
-    @EnableWebSecurity
-    public static class AuthenticationUserDetailsServiceConfig extends WebSecurityConfigurerAdapter {
-        static AuthenticationDetailsSource<HttpServletRequest, PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails> AUTHENTICATION_DETAILS_SOURCE
-
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth.
-                inMemoryAuthentication()
-                    .withUser("rod").password("password").roles("USER","ADMIN");
-        }
-
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .x509()
-                    .userDetailsService(new CustomUserDetailsService());
-        }
-    }
-
-    def loadCert(String location) {
-        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
-        certFactory.generateCertificate(Thread.currentThread().contextClassLoader.getResourceAsStream(location))
-    }
-
-    static class CustomUserDetailsService implements UserDetailsService {
-
-        public UserDetails loadUserByUsername(String username)
-                throws UsernameNotFoundException {
-            return new User("customuser", "password", AuthorityUtils.createAuthorityList("ROLE_USER"));
-        }
-
-    }
-
-    static class CustomAuthenticationUserDetailsService implements AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {
-        public UserDetails loadUserDetails(
-                PreAuthenticatedAuthenticationToken token)
-                throws UsernameNotFoundException {
-            return new User("customuser", "password", AuthorityUtils.createAuthorityList("ROLE_USER"));
-        }
-    }
-
-    def authentication() {
-        HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
-        new HttpSessionSecurityContextRepository().loadContext(requestResponseHolder)?.authentication
-    }
+	def "http/x509 can authenticate"() {
+		setup:
+			X509Certificate certificate = loadCert("rod.cer")
+			loadConfig(X509Config)
+		when:
+			request.setAttribute("javax.servlet.request.X509Certificate", [certificate] as X509Certificate[] )
+			springSecurityFilterChain.doFilter(request, response, chain);
+		then:
+			response.status == 200
+			authentication().name == 'rod'
+	}
+
+	def "http/x509"() {
+		when:
+			loadConfig(X509Config)
+			X509AuthenticationFilter filter = findFilter(X509AuthenticationFilter)
+			AuthenticationManager authenticationManager = ReflectionTestUtils.getField(filter,"authenticationManager")
+		then:
+			authenticationManager
+			filter.authenticationDetailsSource.class == WebAuthenticationDetailsSource
+			authenticationManager.providers.find { it instanceof PreAuthenticatedAuthenticationProvider }.preAuthenticatedUserDetailsService.class == UserDetailsByNameServiceWrapper
+	}
+
+	@EnableWebSecurity
+	public static class X509Config extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth.
+				inMemoryAuthentication()
+					.withUser("rod").password("password").roles("USER","ADMIN");
+		}
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.x509();
+		}
+	}
+
+	def "http/x509@authentication-details-source-ref"() {
+		setup:
+			AuthenticationDetailsSourceRefConfig.AUTHENTICATION_DETAILS_SOURCE = Mock(AuthenticationDetailsSource)
+		when:
+			loadConfig(AuthenticationDetailsSourceRefConfig)
+			X509AuthenticationFilter filter = findFilter(X509AuthenticationFilter)
+			AuthenticationManager authenticationManager = ReflectionTestUtils.getField(filter,"authenticationManager")
+		then:
+			authenticationManager
+			filter.authenticationDetailsSource == AuthenticationDetailsSourceRefConfig.AUTHENTICATION_DETAILS_SOURCE
+			authenticationManager.providers.find { it instanceof PreAuthenticatedAuthenticationProvider }.preAuthenticatedUserDetailsService.class == UserDetailsByNameServiceWrapper
+	}
+
+	@EnableWebSecurity
+	public static class AuthenticationDetailsSourceRefConfig extends WebSecurityConfigurerAdapter {
+		static AuthenticationDetailsSource<HttpServletRequest, PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails> AUTHENTICATION_DETAILS_SOURCE
+
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth.
+				inMemoryAuthentication()
+					.withUser("rod").password("password").roles("USER","ADMIN");
+		}
+
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.x509()
+					.authenticationDetailsSource(AUTHENTICATION_DETAILS_SOURCE);
+		}
+	}
+
+	def "http/x509@subject-principal-regex"() {
+		setup:
+			X509Certificate certificate = loadCert("rodatexampledotcom.cer")
+			loadConfig(SubjectPrincipalRegexConfig)
+		when:
+			request.setAttribute("javax.servlet.request.X509Certificate", [certificate] as X509Certificate[] )
+			springSecurityFilterChain.doFilter(request, response, chain);
+		then:
+			response.status == 200
+			authentication().name == 'rod'
+	}
+
+	@EnableWebSecurity
+	public static class SubjectPrincipalRegexConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth.
+				inMemoryAuthentication()
+					.withUser("rod").password("password").roles("USER","ADMIN");
+		}
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.x509()
+					.subjectPrincipalRegex('CN=(.*?)@example.com(?:,|$)');
+		}
+	}
+
+	def "http/x509@user-service-ref"() {
+		setup:
+			X509Certificate certificate = loadCert("rodatexampledotcom.cer")
+			loadConfig(UserDetailsServiceRefConfig)
+		when:
+			request.setAttribute("javax.servlet.request.X509Certificate", [certificate] as X509Certificate[] )
+			springSecurityFilterChain.doFilter(request, response, chain);
+		then:
+			response.status == 200
+			authentication().name == 'customuser'
+	}
+
+	@EnableWebSecurity
+	public static class UserDetailsServiceRefConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth.
+				inMemoryAuthentication()
+					.withUser("rod").password("password").roles("USER","ADMIN");
+		}
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.x509()
+					.userDetailsService(new CustomUserDetailsService());
+		}
+	}
+
+	def "http/x509 custom AuthenticationUserDetailsService"() {
+		setup:
+			X509Certificate certificate = loadCert("rodatexampledotcom.cer")
+			loadConfig(AuthenticationUserDetailsServiceConfig)
+		when:
+			request.setAttribute("javax.servlet.request.X509Certificate", [certificate] as X509Certificate[] )
+			springSecurityFilterChain.doFilter(request, response, chain);
+		then:
+			response.status == 200
+			authentication().name == 'customuser'
+	}
+
+	@EnableWebSecurity
+	public static class AuthenticationUserDetailsServiceConfig extends WebSecurityConfigurerAdapter {
+		static AuthenticationDetailsSource<HttpServletRequest, PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails> AUTHENTICATION_DETAILS_SOURCE
+
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth.
+				inMemoryAuthentication()
+					.withUser("rod").password("password").roles("USER","ADMIN");
+		}
+
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.x509()
+					.userDetailsService(new CustomUserDetailsService());
+		}
+	}
+
+	def loadCert(String location) {
+		CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+		certFactory.generateCertificate(Thread.currentThread().contextClassLoader.getResourceAsStream(location))
+	}
+
+	static class CustomUserDetailsService implements UserDetailsService {
+
+		public UserDetails loadUserByUsername(String username)
+				throws UsernameNotFoundException {
+			return new User("customuser", "password", AuthorityUtils.createAuthorityList("ROLE_USER"));
+		}
+
+	}
+
+	static class CustomAuthenticationUserDetailsService implements AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {
+		public UserDetails loadUserDetails(
+				PreAuthenticatedAuthenticationToken token)
+				throws UsernameNotFoundException {
+			return new User("customuser", "password", AuthorityUtils.createAuthorityList("ROLE_USER"));
+		}
+	}
+
+	def authentication() {
+		HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
+		new HttpSessionSecurityContextRepository().loadContext(requestResponseHolder)?.authentication
+	}
 }

+ 329 - 329
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.groovy

@@ -55,333 +55,333 @@ import org.springframework.test.util.ReflectionTestUtils;
  */
 public class NamespaceRememberMeTests extends BaseSpringSpec {
 
-    def "http/remember-me"() {
-        setup:
-            loadConfig(RememberMeConfig)
-        when: "login with remember me"
-            super.setup()
-            request.servletPath = "/login"
-            request.method = "POST"
-            request.parameters.username = ["user"] as String[]
-            request.parameters.password = ["password"] as String[]
-            request.parameters.'remember-me' = ["true"] as String[]
-            springSecurityFilterChain.doFilter(request,response,chain)
-            Cookie rememberMeCookie = getRememberMeCookie()
-        then: "response contains remember me cookie"
-            rememberMeCookie != null
-        when: "session expires"
-            super.setup()
-            request.setCookies(rememberMeCookie)
-            request.requestURI = "/abc"
-            springSecurityFilterChain.doFilter(request,response,chain)
-            MockHttpSession session = request.getSession()
-        then: "initialized to RememberMeAuthenticationToken"
-            SecurityContext context = new HttpSessionSecurityContextRepository().loadContext(new HttpRequestResponseHolder(request, response))
-            context.getAuthentication() instanceof RememberMeAuthenticationToken
-        when: "logout"
-            super.setup()
-            request.setSession(session)
-            super.setupCsrf()
-            request.setCookies(rememberMeCookie)
-            request.servletPath = "/logout"
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-            rememberMeCookie = getRememberMeCookie()
-        then: "logout cookie expired"
-            response.getRedirectedUrl() == "/login?logout"
-            rememberMeCookie.maxAge == 0
-        when: "use remember me after logout"
-            super.setup()
-            request.setCookies(rememberMeCookie)
-            request.requestURI = "/abc"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to default login page"
-            response.getRedirectedUrl() == "http://localhost/login"
-    }
-
-    @Configuration
-    static class RememberMeConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .formLogin()
-                    .and()
-                .rememberMe()
-        }
-    }
-
-    def "http/remember-me@services-ref"() {
-        setup:
-            RememberMeServicesRefConfig.REMEMBER_ME_SERVICES = Mock(RememberMeServices)
-        when: "use custom remember-me services"
-            loadConfig(RememberMeServicesRefConfig)
-        then: "custom remember-me services used"
-            findFilter(RememberMeAuthenticationFilter).rememberMeServices == RememberMeServicesRefConfig.REMEMBER_ME_SERVICES
-            findFilter(UsernamePasswordAuthenticationFilter).rememberMeServices == RememberMeServicesRefConfig.REMEMBER_ME_SERVICES
-    }
-
-    @Configuration
-    static class RememberMeServicesRefConfig extends BaseWebConfig {
-        static RememberMeServices REMEMBER_ME_SERVICES
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .formLogin()
-                    .and()
-                .rememberMe()
-                    .rememberMeServices(REMEMBER_ME_SERVICES)
-        }
-    }
-
-    def "http/remember-me@authentication-success-handler-ref"() {
-        setup:
-            AuthSuccessConfig.SUCCESS_HANDLER = Mock(AuthenticationSuccessHandler)
-        when: "use custom success handler"
-            loadConfig(AuthSuccessConfig)
-        then: "custom remember-me success handler is used"
-            findFilter(RememberMeAuthenticationFilter).successHandler == AuthSuccessConfig.SUCCESS_HANDLER
-    }
-
-    @Configuration
-    static class AuthSuccessConfig extends BaseWebConfig {
-        static AuthenticationSuccessHandler SUCCESS_HANDLER
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .formLogin()
-                    .and()
-                .rememberMe()
-                    .authenticationSuccessHandler(SUCCESS_HANDLER)
-        }
-    }
-
-    // http/remember-me@data-source-ref is not supported directly. Instead use http/remember-me@token-repository-ref example
-
-    def "http/remember-me@key"() {
-        when: "use custom key"
-            loadConfig(KeyConfig)
-            AuthenticationManager authManager = context.getBean(AuthenticationManager)
-        then: "custom key services used"
-            findFilter(RememberMeAuthenticationFilter).rememberMeServices.key == "KeyConfig"
-            authManager.authenticate(new RememberMeAuthenticationToken("KeyConfig", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))
-    }
-
-    @Configuration
-    static class KeyConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .formLogin()
-                    .and()
-                .rememberMe()
-                    .key("KeyConfig")
-        }
-
-        @Bean
-        @Override
-        public AuthenticationManager authenticationManagerBean()
-                throws Exception {
-            return super.authenticationManagerBean();
-        }
-    }
-
-    // http/remember-me@services-alias is not supported use standard aliasing instead (i.e. @Bean("alias"))
-
-    def "http/remember-me@token-repository-ref"() {
-        setup:
-            TokenRepositoryRefConfig.TOKEN_REPOSITORY = Mock(PersistentTokenRepository)
-        when: "use custom token services"
-            loadConfig(TokenRepositoryRefConfig)
-        then: "custom token services used with PersistentTokenBasedRememberMeServices"
-            PersistentTokenBasedRememberMeServices rememberMeServices = findFilter(RememberMeAuthenticationFilter).rememberMeServices
-            findFilter(RememberMeAuthenticationFilter).rememberMeServices.tokenRepository == TokenRepositoryRefConfig.TOKEN_REPOSITORY
-    }
-
-    @Configuration
-    static class TokenRepositoryRefConfig extends BaseWebConfig {
-        static PersistentTokenRepository TOKEN_REPOSITORY
-        protected void configure(HttpSecurity http) throws Exception {
-            // JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl()
-            // tokenRepository.setDataSource(dataSource);
-            http
-                .formLogin()
-                    .and()
-                .rememberMe()
-                    .tokenRepository(TOKEN_REPOSITORY)
-        }
-    }
-
-    def "http/remember-me@token-validity-seconds"() {
-        when: "use token validity"
-            loadConfig(TokenValiditySecondsConfig)
-        then: "custom token validity used"
-            findFilter(RememberMeAuthenticationFilter).rememberMeServices.tokenValiditySeconds == 1
-    }
-
-    @Configuration
-    static class TokenValiditySecondsConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .formLogin()
-                    .and()
-                .rememberMe()
-                    .tokenValiditySeconds(1)
-        }
-    }
-
-    def "http/remember-me@token-validity-seconds default"() {
-        when: "use token validity"
-            loadConfig(DefaultTokenValiditySecondsConfig)
-        then: "custom token validity used"
-            findFilter(RememberMeAuthenticationFilter).rememberMeServices.tokenValiditySeconds == AbstractRememberMeServices.TWO_WEEKS_S
-    }
-
-    @Configuration
-    static class DefaultTokenValiditySecondsConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .formLogin()
-                    .and()
-                .rememberMe()
-        }
-    }
-
-    def "http/remember-me@use-secure-cookie"() {
-        when: "use secure cookies = true"
-            loadConfig(UseSecureCookieConfig)
-        then: "secure cookies will be used"
-            ReflectionTestUtils.getField(findFilter(RememberMeAuthenticationFilter).rememberMeServices, "useSecureCookie") == true
-    }
-
-    @Configuration
-    static class UseSecureCookieConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .formLogin()
-                    .and()
-                .rememberMe()
-                    .useSecureCookie(true)
-        }
-    }
-
-    def "http/remember-me@remember-me-parameter"() {
-        when: "use custom rememberMeParameter"
-            loadConfig(RememberMeParameterConfig)
-        then: "custom rememberMeParameter will be used"
-            findFilter(RememberMeAuthenticationFilter).rememberMeServices.parameter == "rememberMe"
-    }
-
-    @Configuration
-    static class RememberMeParameterConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .formLogin()
-                    .and()
-                .rememberMe()
-                    .rememberMeParameter("rememberMe")
-        }
-    }
-
-    // SEC-2880
-    def "http/remember-me@remember-me-cookie"() {
-        when: "use custom rememberMeCookieName"
-        loadConfig(RememberMeCookieNameConfig)
-        then: "custom rememberMeCookieName will be used"
-        findFilter(RememberMeAuthenticationFilter).rememberMeServices.cookieName == "rememberMe"
-    }
-
-    @Configuration
-    static class RememberMeCookieNameConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .formLogin()
-                    .and()
-                .rememberMe()
-                    .rememberMeCookieName("rememberMe")
-        }
-    }
-
-    def "http/remember-me@use-secure-cookie defaults"() {
-        when: "use secure cookies not specified"
-            loadConfig(DefaultUseSecureCookieConfig)
-        then: "secure cookies will be null (use secure if the request is secure)"
-            ReflectionTestUtils.getField(findFilter(RememberMeAuthenticationFilter).rememberMeServices, "useSecureCookie") == null
-    }
-
-    @Configuration
-    static class DefaultUseSecureCookieConfig extends BaseWebConfig {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .formLogin()
-                    .and()
-                .rememberMe()
-        }
-    }
-
-    def "http/remember-me defaults UserDetailsService with custom UserDetailsService"() {
-        setup:
-            DefaultsUserDetailsServiceWithDaoConfig.USERDETAILS_SERVICE = Mock(UserDetailsService)
-            loadConfig(DefaultsUserDetailsServiceWithDaoConfig)
-        when:
-            request.setCookies(createRememberMeCookie())
-            springSecurityFilterChain.doFilter(request, response, chain)
-        then: "RememberMeServices defaults to the custom UserDetailsService"
-           1 * DefaultsUserDetailsServiceWithDaoConfig.USERDETAILS_SERVICE.loadUserByUsername("user")
-    }
-
-    @EnableWebSecurity
-    static class DefaultsUserDetailsServiceWithDaoConfig extends WebSecurityConfigurerAdapter {
-        static UserDetailsService USERDETAILS_SERVICE
-
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .formLogin()
-                    .and()
-                .rememberMe()
-        }
-
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                    .userDetailsService(USERDETAILS_SERVICE);
-        }
-    }
-
-    def "http/remember-me@user-service-ref"() {
-        setup:
-            UserServiceRefConfig.USERDETAILS_SERVICE = Mock(UserDetailsService)
-        when: "use custom UserDetailsService"
-            loadConfig(UserServiceRefConfig)
-        then: "custom UserDetailsService is used"
-            ReflectionTestUtils.getField(findFilter(RememberMeAuthenticationFilter).rememberMeServices, "userDetailsService") == UserServiceRefConfig.USERDETAILS_SERVICE
-    }
-
-    @Configuration
-    static class UserServiceRefConfig extends BaseWebConfig {
-        static UserDetailsService USERDETAILS_SERVICE
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .formLogin()
-                    .and()
-                .rememberMe()
-                    .userDetailsService(USERDETAILS_SERVICE)
-        }
-    }
-
-    Cookie createRememberMeCookie() {
-        MockHttpServletRequest request = new MockHttpServletRequest()
-        MockHttpServletResponse response = new MockHttpServletResponse()
-        super.setupCsrf("CSRF_TOKEN", request, response)
-
-        MockFilterChain chain = new MockFilterChain()
-        request.servletPath = "/login"
-        request.method = "POST"
-        request.parameters.username = ["user"] as String[]
-        request.parameters.password = ["password"] as String[]
-        request.parameters.'remember-me' = ["true"] as String[]
-        springSecurityFilterChain.doFilter(request, response, chain)
-        response.getCookie("remember-me")
-    }
-
-    Cookie getRememberMeCookie(String cookieName="remember-me") {
-        response.getCookie(cookieName)
-    }
+	def "http/remember-me"() {
+		setup:
+			loadConfig(RememberMeConfig)
+		when: "login with remember me"
+			super.setup()
+			request.servletPath = "/login"
+			request.method = "POST"
+			request.parameters.username = ["user"] as String[]
+			request.parameters.password = ["password"] as String[]
+			request.parameters.'remember-me' = ["true"] as String[]
+			springSecurityFilterChain.doFilter(request,response,chain)
+			Cookie rememberMeCookie = getRememberMeCookie()
+		then: "response contains remember me cookie"
+			rememberMeCookie != null
+		when: "session expires"
+			super.setup()
+			request.setCookies(rememberMeCookie)
+			request.requestURI = "/abc"
+			springSecurityFilterChain.doFilter(request,response,chain)
+			MockHttpSession session = request.getSession()
+		then: "initialized to RememberMeAuthenticationToken"
+			SecurityContext context = new HttpSessionSecurityContextRepository().loadContext(new HttpRequestResponseHolder(request, response))
+			context.getAuthentication() instanceof RememberMeAuthenticationToken
+		when: "logout"
+			super.setup()
+			request.setSession(session)
+			super.setupCsrf()
+			request.setCookies(rememberMeCookie)
+			request.servletPath = "/logout"
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+			rememberMeCookie = getRememberMeCookie()
+		then: "logout cookie expired"
+			response.getRedirectedUrl() == "/login?logout"
+			rememberMeCookie.maxAge == 0
+		when: "use remember me after logout"
+			super.setup()
+			request.setCookies(rememberMeCookie)
+			request.requestURI = "/abc"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to default login page"
+			response.getRedirectedUrl() == "http://localhost/login"
+	}
+
+	@Configuration
+	static class RememberMeConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin()
+					.and()
+				.rememberMe()
+		}
+	}
+
+	def "http/remember-me@services-ref"() {
+		setup:
+			RememberMeServicesRefConfig.REMEMBER_ME_SERVICES = Mock(RememberMeServices)
+		when: "use custom remember-me services"
+			loadConfig(RememberMeServicesRefConfig)
+		then: "custom remember-me services used"
+			findFilter(RememberMeAuthenticationFilter).rememberMeServices == RememberMeServicesRefConfig.REMEMBER_ME_SERVICES
+			findFilter(UsernamePasswordAuthenticationFilter).rememberMeServices == RememberMeServicesRefConfig.REMEMBER_ME_SERVICES
+	}
+
+	@Configuration
+	static class RememberMeServicesRefConfig extends BaseWebConfig {
+		static RememberMeServices REMEMBER_ME_SERVICES
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.formLogin()
+					.and()
+				.rememberMe()
+					.rememberMeServices(REMEMBER_ME_SERVICES)
+		}
+	}
+
+	def "http/remember-me@authentication-success-handler-ref"() {
+		setup:
+			AuthSuccessConfig.SUCCESS_HANDLER = Mock(AuthenticationSuccessHandler)
+		when: "use custom success handler"
+			loadConfig(AuthSuccessConfig)
+		then: "custom remember-me success handler is used"
+			findFilter(RememberMeAuthenticationFilter).successHandler == AuthSuccessConfig.SUCCESS_HANDLER
+	}
+
+	@Configuration
+	static class AuthSuccessConfig extends BaseWebConfig {
+		static AuthenticationSuccessHandler SUCCESS_HANDLER
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.formLogin()
+					.and()
+				.rememberMe()
+					.authenticationSuccessHandler(SUCCESS_HANDLER)
+		}
+	}
+
+	// http/remember-me@data-source-ref is not supported directly. Instead use http/remember-me@token-repository-ref example
+
+	def "http/remember-me@key"() {
+		when: "use custom key"
+			loadConfig(KeyConfig)
+			AuthenticationManager authManager = context.getBean(AuthenticationManager)
+		then: "custom key services used"
+			findFilter(RememberMeAuthenticationFilter).rememberMeServices.key == "KeyConfig"
+			authManager.authenticate(new RememberMeAuthenticationToken("KeyConfig", "user", AuthorityUtils.createAuthorityList("ROLE_USER")))
+	}
+
+	@Configuration
+	static class KeyConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.formLogin()
+					.and()
+				.rememberMe()
+					.key("KeyConfig")
+		}
+
+		@Bean
+		@Override
+		public AuthenticationManager authenticationManagerBean()
+				throws Exception {
+			return super.authenticationManagerBean();
+		}
+	}
+
+	// http/remember-me@services-alias is not supported use standard aliasing instead (i.e. @Bean("alias"))
+
+	def "http/remember-me@token-repository-ref"() {
+		setup:
+			TokenRepositoryRefConfig.TOKEN_REPOSITORY = Mock(PersistentTokenRepository)
+		when: "use custom token services"
+			loadConfig(TokenRepositoryRefConfig)
+		then: "custom token services used with PersistentTokenBasedRememberMeServices"
+			PersistentTokenBasedRememberMeServices rememberMeServices = findFilter(RememberMeAuthenticationFilter).rememberMeServices
+			findFilter(RememberMeAuthenticationFilter).rememberMeServices.tokenRepository == TokenRepositoryRefConfig.TOKEN_REPOSITORY
+	}
+
+	@Configuration
+	static class TokenRepositoryRefConfig extends BaseWebConfig {
+		static PersistentTokenRepository TOKEN_REPOSITORY
+		protected void configure(HttpSecurity http) throws Exception {
+			// JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl()
+			// tokenRepository.setDataSource(dataSource);
+			http
+				.formLogin()
+					.and()
+				.rememberMe()
+					.tokenRepository(TOKEN_REPOSITORY)
+		}
+	}
+
+	def "http/remember-me@token-validity-seconds"() {
+		when: "use token validity"
+			loadConfig(TokenValiditySecondsConfig)
+		then: "custom token validity used"
+			findFilter(RememberMeAuthenticationFilter).rememberMeServices.tokenValiditySeconds == 1
+	}
+
+	@Configuration
+	static class TokenValiditySecondsConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.formLogin()
+					.and()
+				.rememberMe()
+					.tokenValiditySeconds(1)
+		}
+	}
+
+	def "http/remember-me@token-validity-seconds default"() {
+		when: "use token validity"
+			loadConfig(DefaultTokenValiditySecondsConfig)
+		then: "custom token validity used"
+			findFilter(RememberMeAuthenticationFilter).rememberMeServices.tokenValiditySeconds == AbstractRememberMeServices.TWO_WEEKS_S
+	}
+
+	@Configuration
+	static class DefaultTokenValiditySecondsConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.formLogin()
+					.and()
+				.rememberMe()
+		}
+	}
+
+	def "http/remember-me@use-secure-cookie"() {
+		when: "use secure cookies = true"
+			loadConfig(UseSecureCookieConfig)
+		then: "secure cookies will be used"
+			ReflectionTestUtils.getField(findFilter(RememberMeAuthenticationFilter).rememberMeServices, "useSecureCookie") == true
+	}
+
+	@Configuration
+	static class UseSecureCookieConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.formLogin()
+					.and()
+				.rememberMe()
+					.useSecureCookie(true)
+		}
+	}
+
+	def "http/remember-me@remember-me-parameter"() {
+		when: "use custom rememberMeParameter"
+			loadConfig(RememberMeParameterConfig)
+		then: "custom rememberMeParameter will be used"
+			findFilter(RememberMeAuthenticationFilter).rememberMeServices.parameter == "rememberMe"
+	}
+
+	@Configuration
+	static class RememberMeParameterConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.formLogin()
+					.and()
+				.rememberMe()
+					.rememberMeParameter("rememberMe")
+		}
+	}
+
+	// SEC-2880
+	def "http/remember-me@remember-me-cookie"() {
+		when: "use custom rememberMeCookieName"
+		loadConfig(RememberMeCookieNameConfig)
+		then: "custom rememberMeCookieName will be used"
+		findFilter(RememberMeAuthenticationFilter).rememberMeServices.cookieName == "rememberMe"
+	}
+
+	@Configuration
+	static class RememberMeCookieNameConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.formLogin()
+					.and()
+				.rememberMe()
+					.rememberMeCookieName("rememberMe")
+		}
+	}
+
+	def "http/remember-me@use-secure-cookie defaults"() {
+		when: "use secure cookies not specified"
+			loadConfig(DefaultUseSecureCookieConfig)
+		then: "secure cookies will be null (use secure if the request is secure)"
+			ReflectionTestUtils.getField(findFilter(RememberMeAuthenticationFilter).rememberMeServices, "useSecureCookie") == null
+	}
+
+	@Configuration
+	static class DefaultUseSecureCookieConfig extends BaseWebConfig {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.formLogin()
+					.and()
+				.rememberMe()
+		}
+	}
+
+	def "http/remember-me defaults UserDetailsService with custom UserDetailsService"() {
+		setup:
+			DefaultsUserDetailsServiceWithDaoConfig.USERDETAILS_SERVICE = Mock(UserDetailsService)
+			loadConfig(DefaultsUserDetailsServiceWithDaoConfig)
+		when:
+			request.setCookies(createRememberMeCookie())
+			springSecurityFilterChain.doFilter(request, response, chain)
+		then: "RememberMeServices defaults to the custom UserDetailsService"
+		   1 * DefaultsUserDetailsServiceWithDaoConfig.USERDETAILS_SERVICE.loadUserByUsername("user")
+	}
+
+	@EnableWebSecurity
+	static class DefaultsUserDetailsServiceWithDaoConfig extends WebSecurityConfigurerAdapter {
+		static UserDetailsService USERDETAILS_SERVICE
+
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.formLogin()
+					.and()
+				.rememberMe()
+		}
+
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+					.userDetailsService(USERDETAILS_SERVICE);
+		}
+	}
+
+	def "http/remember-me@user-service-ref"() {
+		setup:
+			UserServiceRefConfig.USERDETAILS_SERVICE = Mock(UserDetailsService)
+		when: "use custom UserDetailsService"
+			loadConfig(UserServiceRefConfig)
+		then: "custom UserDetailsService is used"
+			ReflectionTestUtils.getField(findFilter(RememberMeAuthenticationFilter).rememberMeServices, "userDetailsService") == UserServiceRefConfig.USERDETAILS_SERVICE
+	}
+
+	@Configuration
+	static class UserServiceRefConfig extends BaseWebConfig {
+		static UserDetailsService USERDETAILS_SERVICE
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.formLogin()
+					.and()
+				.rememberMe()
+					.userDetailsService(USERDETAILS_SERVICE)
+		}
+	}
+
+	Cookie createRememberMeCookie() {
+		MockHttpServletRequest request = new MockHttpServletRequest()
+		MockHttpServletResponse response = new MockHttpServletResponse()
+		super.setupCsrf("CSRF_TOKEN", request, response)
+
+		MockFilterChain chain = new MockFilterChain()
+		request.servletPath = "/login"
+		request.method = "POST"
+		request.parameters.username = ["user"] as String[]
+		request.parameters.password = ["password"] as String[]
+		request.parameters.'remember-me' = ["true"] as String[]
+		springSecurityFilterChain.doFilter(request, response, chain)
+		response.getCookie("remember-me")
+	}
+
+	Cookie getRememberMeCookie(String cookieName="remember-me") {
+		response.getCookie(cookieName)
+	}
 }

+ 31 - 31
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/PermitAllSupportTests.groovy

@@ -30,40 +30,40 @@ import org.springframework.security.web.util.matcher.RequestMatcher
  *
  */
 class PermitAllSupportTests extends BaseSpringSpec {
-    def "PermitAllSupport.ExactUrlRequestMatcher"() {
-        expect:
-            RequestMatcher matcher = new PermitAllSupport.ExactUrlRequestMatcher(processUrl)
-            matcher.matches(new MockHttpServletRequest(requestURI:requestURI,contextPath:contextPath,queryString: query)) == matches
-        where:
-           processUrl             | requestURI            | contextPath        | query      | matches
-            "/login"              | "/sample/login"       | "/sample"          | null       | true
-            "/login"              | "/sample/login"       | "/sample"          | "error"    | false
-            "/login?error"        | "/sample/login"       | "/sample"          | "error"    | true
-    }
+	def "PermitAllSupport.ExactUrlRequestMatcher"() {
+		expect:
+			RequestMatcher matcher = new PermitAllSupport.ExactUrlRequestMatcher(processUrl)
+			matcher.matches(new MockHttpServletRequest(requestURI:requestURI,contextPath:contextPath,queryString: query)) == matches
+		where:
+		   processUrl             | requestURI            | contextPath        | query      | matches
+			"/login"              | "/sample/login"       | "/sample"          | null       | true
+			"/login"              | "/sample/login"       | "/sample"          | "error"    | false
+			"/login?error"        | "/sample/login"       | "/sample"          | "error"    | true
+	}
 
-    def "PermitAllSupport throws Exception when authorizedUrls() not invoked"() {
-        when:
-            loadConfig(NoAuthorizedUrlsConfig)
-        then:
-            BeanCreationException e = thrown()
-            e.message.contains "permitAll only works with HttpSecurity.authorizeRequests"
+	def "PermitAllSupport throws Exception when authorizedUrls() not invoked"() {
+		when:
+			loadConfig(NoAuthorizedUrlsConfig)
+		then:
+			BeanCreationException e = thrown()
+			e.message.contains "permitAll only works with HttpSecurity.authorizeRequests"
 
-    }
+	}
 
-    @EnableWebSecurity
-    static class NoAuthorizedUrlsConfig extends WebSecurityConfigurerAdapter {
+	@EnableWebSecurity
+	static class NoAuthorizedUrlsConfig extends WebSecurityConfigurerAdapter {
 
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-        }
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+		}
 
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .formLogin()
-                    .permitAll()
-        }
-    }
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.formLogin()
+					.permitAll()
+		}
+	}
 }

+ 23 - 23
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurerTests.groovy

@@ -36,28 +36,28 @@ import org.springframework.security.web.session.SessionManagementFilter
  */
 class PortMapperConfigurerTests extends BaseSpringSpec {
 
-    def "invoke portMapper twice does not override"() {
-        setup:
-            loadConfig(InvokeTwiceDoesNotOverride)
-            request.setServerPort(543)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.redirectedUrl == "https://localhost:123"
-    }
+	def "invoke portMapper twice does not override"() {
+		setup:
+			loadConfig(InvokeTwiceDoesNotOverride)
+			request.setServerPort(543)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.redirectedUrl == "https://localhost:123"
+	}
 
-    @EnableWebSecurity
-    static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .requiresChannel()
-                    .anyRequest().requiresSecure()
-                    .and()
-                .portMapper()
-                    .http(543).mapsTo(123)
-                    .and()
-                .portMapper()
-        }
-    }
+	@EnableWebSecurity
+	static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.requiresChannel()
+					.anyRequest().requiresSecure()
+					.and()
+				.portMapper()
+					.http(543).mapsTo(123)
+					.and()
+				.portMapper()
+		}
+	}
 }

+ 147 - 147
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.groovy

@@ -48,151 +48,151 @@ import org.springframework.security.web.context.HttpSessionSecurityContextReposi
  */
 public class RememberMeConfigurerTests extends BaseSpringSpec {
 
-    def "rememberMe() null UserDetailsService provides meaningful error"() {
-        setup: "Load Config without UserDetailsService specified"
-            loadConfig(NullUserDetailsConfig)
-        when:
-            request.setCookies(createRememberMeCookie())
-            springSecurityFilterChain.doFilter(request, response, chain)
-        then: "A good error message is provided"
-            Exception success = thrown()
-            success.message.contains "UserDetailsService is required"
-    }
-
-    @EnableWebSecurity
-    static class NullUserDetailsConfig extends WebSecurityConfigurerAdapter {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .formLogin()
-                    .and()
-                .rememberMe()
-        }
-
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            User user = new User("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"))
-            DaoAuthenticationProvider provider = new DaoAuthenticationProvider()
-            provider.userDetailsService = new InMemoryUserDetailsManager([user])
-            auth
-                .authenticationProvider(provider)
-        }
-    }
-
-    def "rememberMe ObjectPostProcessor"() {
-        setup:
-            AnyObjectPostProcessor opp = Mock()
-            HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
-            UserDetailsService uds = authenticationBldr.getDefaultUserDetailsService()
-        when:
-            http
-                .rememberMe()
-                    .userDetailsService(authenticationBldr.getDefaultUserDetailsService())
-                    .and()
-                .build()
-
-        then: "RememberMeAuthenticationFilter is registered with LifecycleManager"
-            1 * opp.postProcess(_ as RememberMeAuthenticationFilter) >> {RememberMeAuthenticationFilter o -> o}
-    }
-
-    def "invoke rememberMe twice does not reset"() {
-        setup:
-            AnyObjectPostProcessor opp = Mock()
-            HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
-            UserDetailsService uds = authenticationBldr.getDefaultUserDetailsService()
-        when:
-            http
-                .rememberMe()
-                    .userDetailsService(authenticationBldr.getDefaultUserDetailsService())
-                    .and()
-                .rememberMe()
-        then: "RememberMeAuthenticationFilter is registered with LifecycleManager"
-            http.getConfigurer(RememberMeConfigurer).userDetailsService != null
-    }
-
-
-    def "http/remember-me with Global AuthenticationManagerBuilder"() {
-        setup:
-            loadConfig(RememberMeConfig)
-        when: "login with remember me"
-            super.setup()
-            request.servletPath = "/login"
-            request.method = "POST"
-            request.parameters.username = ["user"] as String[]
-            request.parameters.password = ["password"] as String[]
-            request.parameters.'remember-me' = ["true"] as String[]
-            springSecurityFilterChain.doFilter(request,response,chain)
-            Cookie rememberMeCookie = getRememberMeCookie()
-        then: "response contains remember me cookie"
-            rememberMeCookie != null
-        when: "session expires"
-            super.setup()
-            request.setCookies(rememberMeCookie)
-            request.requestURI = "/abc"
-            springSecurityFilterChain.doFilter(request,response,chain)
-            MockHttpSession session = request.getSession()
-        then: "initialized to RememberMeAuthenticationToken"
-            SecurityContext context = new HttpSessionSecurityContextRepository().loadContext(new HttpRequestResponseHolder(request, response))
-            context.getAuthentication() instanceof RememberMeAuthenticationToken
-        when: "logout"
-            super.setup()
-            request.setSession(session)
-            super.setupCsrf()
-            request.setCookies(rememberMeCookie)
-            request.servletPath = "/logout"
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-            rememberMeCookie = getRememberMeCookie()
-        then: "logout cookie expired"
-            response.getRedirectedUrl() == "/login?logout"
-            rememberMeCookie.maxAge == 0
-        when: "use remember me after logout"
-            super.setup()
-            request.setCookies(rememberMeCookie)
-            request.requestURI = "/abc"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to default login page"
-            response.getRedirectedUrl() == "http://localhost/login"
-    }
-
-    @EnableWebSecurity
-    static class RememberMeConfig extends WebSecurityConfigurerAdapter {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().hasRole("USER")
-                    .and()
-                .formLogin()
-                    .and()
-                .rememberMe()
-        }
-
-        @Autowired
-        public void configureGlobal(AuthenticationManagerBuilder auth) {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER");
-        }
-    }
-
-    Cookie createRememberMeCookie() {
-        MockHttpServletRequest request = new MockHttpServletRequest()
-        MockHttpServletResponse response = new MockHttpServletResponse()
-        super.setupCsrf("CSRF_TOKEN", request, response)
-
-        MockFilterChain chain = new MockFilterChain()
-        request.servletPath = "/login"
-        request.method = "POST"
-        request.parameters.username = ["user"] as String[]
-        request.parameters.password = ["password"] as String[]
-        request.parameters.'remember-me' = ["true"] as String[]
-        springSecurityFilterChain.doFilter(request, response, chain)
-        response.getCookie("remember-me")
-    }
-
-    Cookie getRememberMeCookie(String cookieName="remember-me") {
-        response.getCookie(cookieName)
-    }
+	def "rememberMe() null UserDetailsService provides meaningful error"() {
+		setup: "Load Config without UserDetailsService specified"
+			loadConfig(NullUserDetailsConfig)
+		when:
+			request.setCookies(createRememberMeCookie())
+			springSecurityFilterChain.doFilter(request, response, chain)
+		then: "A good error message is provided"
+			Exception success = thrown()
+			success.message.contains "UserDetailsService is required"
+	}
+
+	@EnableWebSecurity
+	static class NullUserDetailsConfig extends WebSecurityConfigurerAdapter {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin()
+					.and()
+				.rememberMe()
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			User user = new User("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"))
+			DaoAuthenticationProvider provider = new DaoAuthenticationProvider()
+			provider.userDetailsService = new InMemoryUserDetailsManager([user])
+			auth
+				.authenticationProvider(provider)
+		}
+	}
+
+	def "rememberMe ObjectPostProcessor"() {
+		setup:
+			AnyObjectPostProcessor opp = Mock()
+			HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
+			UserDetailsService uds = authenticationBldr.getDefaultUserDetailsService()
+		when:
+			http
+				.rememberMe()
+					.userDetailsService(authenticationBldr.getDefaultUserDetailsService())
+					.and()
+				.build()
+
+		then: "RememberMeAuthenticationFilter is registered with LifecycleManager"
+			1 * opp.postProcess(_ as RememberMeAuthenticationFilter) >> {RememberMeAuthenticationFilter o -> o}
+	}
+
+	def "invoke rememberMe twice does not reset"() {
+		setup:
+			AnyObjectPostProcessor opp = Mock()
+			HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
+			UserDetailsService uds = authenticationBldr.getDefaultUserDetailsService()
+		when:
+			http
+				.rememberMe()
+					.userDetailsService(authenticationBldr.getDefaultUserDetailsService())
+					.and()
+				.rememberMe()
+		then: "RememberMeAuthenticationFilter is registered with LifecycleManager"
+			http.getConfigurer(RememberMeConfigurer).userDetailsService != null
+	}
+
+
+	def "http/remember-me with Global AuthenticationManagerBuilder"() {
+		setup:
+			loadConfig(RememberMeConfig)
+		when: "login with remember me"
+			super.setup()
+			request.servletPath = "/login"
+			request.method = "POST"
+			request.parameters.username = ["user"] as String[]
+			request.parameters.password = ["password"] as String[]
+			request.parameters.'remember-me' = ["true"] as String[]
+			springSecurityFilterChain.doFilter(request,response,chain)
+			Cookie rememberMeCookie = getRememberMeCookie()
+		then: "response contains remember me cookie"
+			rememberMeCookie != null
+		when: "session expires"
+			super.setup()
+			request.setCookies(rememberMeCookie)
+			request.requestURI = "/abc"
+			springSecurityFilterChain.doFilter(request,response,chain)
+			MockHttpSession session = request.getSession()
+		then: "initialized to RememberMeAuthenticationToken"
+			SecurityContext context = new HttpSessionSecurityContextRepository().loadContext(new HttpRequestResponseHolder(request, response))
+			context.getAuthentication() instanceof RememberMeAuthenticationToken
+		when: "logout"
+			super.setup()
+			request.setSession(session)
+			super.setupCsrf()
+			request.setCookies(rememberMeCookie)
+			request.servletPath = "/logout"
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+			rememberMeCookie = getRememberMeCookie()
+		then: "logout cookie expired"
+			response.getRedirectedUrl() == "/login?logout"
+			rememberMeCookie.maxAge == 0
+		when: "use remember me after logout"
+			super.setup()
+			request.setCookies(rememberMeCookie)
+			request.requestURI = "/abc"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to default login page"
+			response.getRedirectedUrl() == "http://localhost/login"
+	}
+
+	@EnableWebSecurity
+	static class RememberMeConfig extends WebSecurityConfigurerAdapter {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().hasRole("USER")
+					.and()
+				.formLogin()
+					.and()
+				.rememberMe()
+		}
+
+		@Autowired
+		public void configureGlobal(AuthenticationManagerBuilder auth) {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER");
+		}
+	}
+
+	Cookie createRememberMeCookie() {
+		MockHttpServletRequest request = new MockHttpServletRequest()
+		MockHttpServletResponse response = new MockHttpServletResponse()
+		super.setupCsrf("CSRF_TOKEN", request, response)
+
+		MockFilterChain chain = new MockFilterChain()
+		request.servletPath = "/login"
+		request.method = "POST"
+		request.parameters.username = ["user"] as String[]
+		request.parameters.password = ["password"] as String[]
+		request.parameters.'remember-me' = ["true"] as String[]
+		springSecurityFilterChain.doFilter(request, response, chain)
+		response.getCookie("remember-me")
+	}
+
+	Cookie getRememberMeCookie(String cookieName="remember-me") {
+		response.getCookie(cookieName)
+	}
 }

+ 145 - 145
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.groovy

@@ -36,149 +36,149 @@ import spock.lang.Unroll;
  */
 class RequestCacheConfigurerTests extends BaseSpringSpec {
 
-    def "requestCache ObjectPostProcessor"() {
-        setup:
-            AnyObjectPostProcessor opp = Mock()
-            HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
-        when:
-            http
-                .requestCache()
-                    .and()
-                .build()
-
-        then: "RequestCacheAwareFilter is registered with LifecycleManager"
-            1 * opp.postProcess(_ as RequestCacheAwareFilter) >> {RequestCacheAwareFilter o -> o}
-    }
-
-    def "invoke requestCache twice does not reset"() {
-        setup:
-            RequestCache RC = Mock()
-            AnyObjectPostProcessor opp = Mock()
-            HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
-        when:
-            http
-                .requestCache()
-                    .requestCache(RC)
-                    .and()
-                .requestCache()
-
-        then:
-            http.getSharedObject(RequestCache) == RC
-    }
-
-    def "RequestCache disables faviocon.ico"() {
-        setup:
-            loadConfig(RequestCacheDefautlsConfig)
-            request.servletPath = "/favicon.ico"
-            request.requestURI = "/favicon.ico"
-            request.method = "GET"
-        when: "request favicon.ico"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to the login page"
-            response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-            response.redirectedUrl == "http://localhost/login"
-        when: "authenticate successfully"
-            super.setupWeb(request.session)
-            request.servletPath = "/login"
-            request.setParameter("username","user")
-            request.setParameter("password","password")
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to default URL since it was favicon.ico"
-            response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-            response.redirectedUrl == "/"
-    }
-
-    def "SEC-2321: RequestCache disables application/json"() {
-        setup:
-            loadConfig(RequestCacheDefautlsConfig)
-            request.addHeader("Accept", MediaType.APPLICATION_JSON_VALUE)
-            request.method = "GET"
-            request.servletPath = "/messages"
-            request.requestURI = "/messages"
-        when: "request application/json"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to the login page"
-            response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-            response.redirectedUrl == "http://localhost/login"
-        when: "authenticate successfully"
-            super.setupWeb(request.session)
-            request.servletPath = "/login"
-            request.setParameter("username","user")
-            request.setParameter("password","password")
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to default URL since it was application/json. This is desirable since JSON requests are typically not invoked directly from the browser and we don't want the browser to replay them"
-            response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-            response.redirectedUrl == "/"
-    }
-
-    def "SEC-2321: RequestCache disables X-Requested-With"() {
-        setup:
-            loadConfig(RequestCacheDefautlsConfig)
-            request.addHeader("X-Requested-With", "XMLHttpRequest")
-            request.method = "GET"
-            request.servletPath = "/messages"
-            request.requestURI = "/messages"
-        when: "request X-Requested-With"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to the login page"
-            response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-            response.redirectedUrl == "http://localhost/login"
-        when: "authenticate successfully"
-            super.setupWeb(request.session)
-            request.servletPath = "/login"
-            request.setParameter("username","user")
-            request.setParameter("password","password")
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to default URL since it was X-Requested-With"
-            response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-            response.redirectedUrl == "/"
-    }
-
-    @Unroll
-    def "RequestCache saves #headerName: #headerValue"() {
-        setup:
-            loadConfig(RequestCacheDefautlsConfig)
-            request.addHeader(headerName, headerValue)
-            request.method = "GET"
-            request.servletPath = "/messages"
-            request.requestURI = "/messages"
-        when: "request content type"
-            springSecurityFilterChain.doFilter(request,response,chain)
-            super.setupWeb(request.session)
-            request.servletPath = "/login"
-            request.setParameter("username","user")
-            request.setParameter("password","password")
-            request.method = "POST"
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then: "sent to saved URL"
-            response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-            response.redirectedUrl == "http://localhost/messages"
-        where:
-            headerName << ["Accept", "Accept", "Accept", "X-Requested-With"]
-            headerValue << [MediaType.ALL_VALUE, MediaType.TEXT_HTML, "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8","com.android"]
-
-    }
-
-    @EnableWebSecurity
-    static class RequestCacheDefautlsConfig extends WebSecurityConfigurerAdapter {
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().authenticated()
-                    .and()
-                .formLogin()
-        }
-
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER")
-        }
-    }
+	def "requestCache ObjectPostProcessor"() {
+		setup:
+			AnyObjectPostProcessor opp = Mock()
+			HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
+		when:
+			http
+				.requestCache()
+					.and()
+				.build()
+
+		then: "RequestCacheAwareFilter is registered with LifecycleManager"
+			1 * opp.postProcess(_ as RequestCacheAwareFilter) >> {RequestCacheAwareFilter o -> o}
+	}
+
+	def "invoke requestCache twice does not reset"() {
+		setup:
+			RequestCache RC = Mock()
+			AnyObjectPostProcessor opp = Mock()
+			HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
+		when:
+			http
+				.requestCache()
+					.requestCache(RC)
+					.and()
+				.requestCache()
+
+		then:
+			http.getSharedObject(RequestCache) == RC
+	}
+
+	def "RequestCache disables faviocon.ico"() {
+		setup:
+			loadConfig(RequestCacheDefautlsConfig)
+			request.servletPath = "/favicon.ico"
+			request.requestURI = "/favicon.ico"
+			request.method = "GET"
+		when: "request favicon.ico"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to the login page"
+			response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
+			response.redirectedUrl == "http://localhost/login"
+		when: "authenticate successfully"
+			super.setupWeb(request.session)
+			request.servletPath = "/login"
+			request.setParameter("username","user")
+			request.setParameter("password","password")
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to default URL since it was favicon.ico"
+			response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
+			response.redirectedUrl == "/"
+	}
+
+	def "SEC-2321: RequestCache disables application/json"() {
+		setup:
+			loadConfig(RequestCacheDefautlsConfig)
+			request.addHeader("Accept", MediaType.APPLICATION_JSON_VALUE)
+			request.method = "GET"
+			request.servletPath = "/messages"
+			request.requestURI = "/messages"
+		when: "request application/json"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to the login page"
+			response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
+			response.redirectedUrl == "http://localhost/login"
+		when: "authenticate successfully"
+			super.setupWeb(request.session)
+			request.servletPath = "/login"
+			request.setParameter("username","user")
+			request.setParameter("password","password")
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to default URL since it was application/json. This is desirable since JSON requests are typically not invoked directly from the browser and we don't want the browser to replay them"
+			response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
+			response.redirectedUrl == "/"
+	}
+
+	def "SEC-2321: RequestCache disables X-Requested-With"() {
+		setup:
+			loadConfig(RequestCacheDefautlsConfig)
+			request.addHeader("X-Requested-With", "XMLHttpRequest")
+			request.method = "GET"
+			request.servletPath = "/messages"
+			request.requestURI = "/messages"
+		when: "request X-Requested-With"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to the login page"
+			response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
+			response.redirectedUrl == "http://localhost/login"
+		when: "authenticate successfully"
+			super.setupWeb(request.session)
+			request.servletPath = "/login"
+			request.setParameter("username","user")
+			request.setParameter("password","password")
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to default URL since it was X-Requested-With"
+			response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
+			response.redirectedUrl == "/"
+	}
+
+	@Unroll
+	def "RequestCache saves #headerName: #headerValue"() {
+		setup:
+			loadConfig(RequestCacheDefautlsConfig)
+			request.addHeader(headerName, headerValue)
+			request.method = "GET"
+			request.servletPath = "/messages"
+			request.requestURI = "/messages"
+		when: "request content type"
+			springSecurityFilterChain.doFilter(request,response,chain)
+			super.setupWeb(request.session)
+			request.servletPath = "/login"
+			request.setParameter("username","user")
+			request.setParameter("password","password")
+			request.method = "POST"
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then: "sent to saved URL"
+			response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
+			response.redirectedUrl == "http://localhost/messages"
+		where:
+			headerName << ["Accept", "Accept", "Accept", "X-Requested-With"]
+			headerValue << [MediaType.ALL_VALUE, MediaType.TEXT_HTML, "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8","com.android"]
+
+	}
+
+	@EnableWebSecurity
+	static class RequestCacheDefautlsConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().authenticated()
+					.and()
+				.formLogin()
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER")
+		}
+	}
 }

+ 28 - 28
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/RequestMatcherConfigurerTests.groovy

@@ -51,34 +51,34 @@ import spock.lang.Unroll;
 class RequestMatcherConfigurerTests extends BaseSpringSpec {
 
 
-    @Unroll
-    def "SEC-2908 - multiple invocations of authorizeRequests() chains #path"(def path) {
-        setup:
-            loadConfig(Sec2908Config)
-            request.servletPath = path
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.status == HttpServletResponse.SC_FORBIDDEN
-        where:
-            path << ['/oauth/abc','/api/abc']
-    }
+	@Unroll
+	def "SEC-2908 - multiple invocations of authorizeRequests() chains #path"(def path) {
+		setup:
+			loadConfig(Sec2908Config)
+			request.servletPath = path
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.status == HttpServletResponse.SC_FORBIDDEN
+		where:
+			path << ['/oauth/abc','/api/abc']
+	}
 
-    @Configuration
-    @EnableWebSecurity
-    static class Sec2908Config extends WebSecurityConfigurerAdapter {
+	@Configuration
+	@EnableWebSecurity
+	static class Sec2908Config extends WebSecurityConfigurerAdapter {
 
-         @Override
-         protected void configure(HttpSecurity http) throws Exception {
-             http
-                .requestMatchers()
-                    .antMatchers("/api/**")
-                    .and()
-                 .requestMatchers()
-                    .antMatchers("/oauth/**")
-                    .and()
-                 .authorizeRequests()
-                    .anyRequest().denyAll();
-        }
-    }
+		 @Override
+		 protected void configure(HttpSecurity http) throws Exception {
+			 http
+				.requestMatchers()
+					.antMatchers("/api/**")
+					.and()
+				 .requestMatchers()
+					.antMatchers("/oauth/**")
+					.and()
+				 .authorizeRequests()
+					.anyRequest().denyAll();
+		}
+	}
 }

+ 32 - 32
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurerTests.groovy

@@ -31,40 +31,40 @@ import org.springframework.security.web.context.SecurityContextRepository
  */
 class SecurityContextConfigurerTests extends BaseSpringSpec {
 
-    def "securityContext ObjectPostProcessor"() {
-        setup:
-            AnyObjectPostProcessor opp = Mock()
-            HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
-        when:
-            http
-                .securityContext()
-                    .and()
-                .build()
+	def "securityContext ObjectPostProcessor"() {
+		setup:
+			AnyObjectPostProcessor opp = Mock()
+			HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
+		when:
+			http
+				.securityContext()
+					.and()
+				.build()
 
-        then: "SecurityContextPersistenceFilter is registered with LifecycleManager"
-            1 * opp.postProcess(_ as SecurityContextPersistenceFilter) >> {SecurityContextPersistenceFilter o -> o}
-    }
+		then: "SecurityContextPersistenceFilter is registered with LifecycleManager"
+			1 * opp.postProcess(_ as SecurityContextPersistenceFilter) >> {SecurityContextPersistenceFilter o -> o}
+	}
 
-    def "invoke securityContext twice does not override"() {
-        setup:
-            InvokeTwiceDoesNotOverrideConfig.SCR = Mock(SecurityContextRepository)
-        when:
-            loadConfig(InvokeTwiceDoesNotOverrideConfig)
-        then:
-            findFilter(SecurityContextPersistenceFilter).repo == InvokeTwiceDoesNotOverrideConfig.SCR
-    }
+	def "invoke securityContext twice does not override"() {
+		setup:
+			InvokeTwiceDoesNotOverrideConfig.SCR = Mock(SecurityContextRepository)
+		when:
+			loadConfig(InvokeTwiceDoesNotOverrideConfig)
+		then:
+			findFilter(SecurityContextPersistenceFilter).repo == InvokeTwiceDoesNotOverrideConfig.SCR
+	}
 
-    @EnableWebSecurity
-    static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
-        static SecurityContextRepository SCR
+	@EnableWebSecurity
+	static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
+		static SecurityContextRepository SCR
 
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .securityContext()
-                    .securityContextRepository(SCR)
-                    .and()
-                .securityContext()
-        }
-    }
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.securityContext()
+					.securityContextRepository(SCR)
+					.and()
+				.securityContext()
+		}
+	}
 }

+ 112 - 112
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurerTests.groovy

@@ -36,116 +36,116 @@ import org.springframework.security.web.servletapi.SecurityContextHolderAwareReq
  */
 class ServletApiConfigurerTests extends BaseSpringSpec {
 
-    def "servletApi ObjectPostProcessor"() {
-        setup:
-            AnyObjectPostProcessor opp = Mock()
-            HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
-        when:
-            http
-                .servletApi()
-                    .and()
-                .build()
-
-        then: "SecurityContextHolderAwareRequestFilter is registered with LifecycleManager"
-            1 * opp.postProcess(_ as SecurityContextHolderAwareRequestFilter) >> {SecurityContextHolderAwareRequestFilter o -> o}
-    }
-
-    def "SecurityContextHolderAwareRequestFilter properties set"() {
-        when:
-            loadConfig(ServletApiConfig)
-            SecurityContextHolderAwareRequestFilter filter = findFilter(SecurityContextHolderAwareRequestFilter)
-        then: "SEC-2215: authenticationManager != null"
-            filter.authenticationManager != null
-        and: "authenticationEntryPoint != null"
-            filter.authenticationEntryPoint != null
-        and: "requestFactory != null"
-            filter.requestFactory != null
-        and: "logoutHandlers populated"
-            filter.logoutHandlers.collect { it.class } == [CsrfLogoutHandler, SecurityContextLogoutHandler]
-    }
-
-    @CompileStatic
-    @EnableWebSecurity
-    static class ServletApiConfig extends WebSecurityConfigurerAdapter {
-
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER")
-        }
-    }
-
-    def "SecurityContextHolderAwareRequestFilter.authenticationEntryPoint = customEntryPoint"() {
-        setup:
-            CustomEntryPointConfig.ENTRYPOINT = Mock(AuthenticationEntryPoint)
-        when: "load config with customEntryPoint"
-            loadConfig(CustomEntryPointConfig)
-        then: "SecurityContextHolderAwareRequestFilter.authenticationEntryPoint == customEntryPoint"
-            findFilter(SecurityContextHolderAwareRequestFilter).authenticationEntryPoint == CustomEntryPointConfig.ENTRYPOINT
-    }
-
-    @EnableWebSecurity
-    static class CustomEntryPointConfig extends WebSecurityConfigurerAdapter {
-        static AuthenticationEntryPoint ENTRYPOINT
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .exceptionHandling()
-                    .authenticationEntryPoint(ENTRYPOINT)
-                    .and()
-                .formLogin()
-        }
-
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER")
-        }
-    }
-
-    def "invoke servletApi twice does not override"() {
-        setup:
-            InvokeTwiceDoesNotOverrideConfig.ENTRYPOINT = Mock(AuthenticationEntryPoint)
-        when:
-            loadConfig(InvokeTwiceDoesNotOverrideConfig)
-        then:
-            findFilter(SecurityContextHolderAwareRequestFilter).authenticationEntryPoint == InvokeTwiceDoesNotOverrideConfig.ENTRYPOINT
-    }
-
-    @EnableWebSecurity
-    static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
-        static AuthenticationEntryPoint ENTRYPOINT
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .exceptionHandling()
-                    .authenticationEntryPoint(ENTRYPOINT)
-                    .and()
-                .exceptionHandling()
-        }
-    }
-
-    def "use sharedObject trustResolver"() {
-        setup:
-            SharedTrustResolverConfig.TR = Mock(AuthenticationTrustResolver)
-        when:
-            loadConfig(SharedTrustResolverConfig)
-        then:
-            findFilter(SecurityContextHolderAwareRequestFilter).trustResolver == SharedTrustResolverConfig.TR
-    }
-
-    @EnableWebSecurity
-    static class SharedTrustResolverConfig extends WebSecurityConfigurerAdapter {
-        static AuthenticationTrustResolver TR
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .setSharedObject(AuthenticationTrustResolver, TR)
-        }
-    }
+	def "servletApi ObjectPostProcessor"() {
+		setup:
+			AnyObjectPostProcessor opp = Mock()
+			HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
+		when:
+			http
+				.servletApi()
+					.and()
+				.build()
+
+		then: "SecurityContextHolderAwareRequestFilter is registered with LifecycleManager"
+			1 * opp.postProcess(_ as SecurityContextHolderAwareRequestFilter) >> {SecurityContextHolderAwareRequestFilter o -> o}
+	}
+
+	def "SecurityContextHolderAwareRequestFilter properties set"() {
+		when:
+			loadConfig(ServletApiConfig)
+			SecurityContextHolderAwareRequestFilter filter = findFilter(SecurityContextHolderAwareRequestFilter)
+		then: "SEC-2215: authenticationManager != null"
+			filter.authenticationManager != null
+		and: "authenticationEntryPoint != null"
+			filter.authenticationEntryPoint != null
+		and: "requestFactory != null"
+			filter.requestFactory != null
+		and: "logoutHandlers populated"
+			filter.logoutHandlers.collect { it.class } == [CsrfLogoutHandler, SecurityContextLogoutHandler]
+	}
+
+	@CompileStatic
+	@EnableWebSecurity
+	static class ServletApiConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER")
+		}
+	}
+
+	def "SecurityContextHolderAwareRequestFilter.authenticationEntryPoint = customEntryPoint"() {
+		setup:
+			CustomEntryPointConfig.ENTRYPOINT = Mock(AuthenticationEntryPoint)
+		when: "load config with customEntryPoint"
+			loadConfig(CustomEntryPointConfig)
+		then: "SecurityContextHolderAwareRequestFilter.authenticationEntryPoint == customEntryPoint"
+			findFilter(SecurityContextHolderAwareRequestFilter).authenticationEntryPoint == CustomEntryPointConfig.ENTRYPOINT
+	}
+
+	@EnableWebSecurity
+	static class CustomEntryPointConfig extends WebSecurityConfigurerAdapter {
+		static AuthenticationEntryPoint ENTRYPOINT
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.exceptionHandling()
+					.authenticationEntryPoint(ENTRYPOINT)
+					.and()
+				.formLogin()
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER")
+		}
+	}
+
+	def "invoke servletApi twice does not override"() {
+		setup:
+			InvokeTwiceDoesNotOverrideConfig.ENTRYPOINT = Mock(AuthenticationEntryPoint)
+		when:
+			loadConfig(InvokeTwiceDoesNotOverrideConfig)
+		then:
+			findFilter(SecurityContextHolderAwareRequestFilter).authenticationEntryPoint == InvokeTwiceDoesNotOverrideConfig.ENTRYPOINT
+	}
+
+	@EnableWebSecurity
+	static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
+		static AuthenticationEntryPoint ENTRYPOINT
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.exceptionHandling()
+					.authenticationEntryPoint(ENTRYPOINT)
+					.and()
+				.exceptionHandling()
+		}
+	}
+
+	def "use sharedObject trustResolver"() {
+		setup:
+			SharedTrustResolverConfig.TR = Mock(AuthenticationTrustResolver)
+		when:
+			loadConfig(SharedTrustResolverConfig)
+		then:
+			findFilter(SecurityContextHolderAwareRequestFilter).trustResolver == SharedTrustResolverConfig.TR
+	}
+
+	@EnableWebSecurity
+	static class SharedTrustResolverConfig extends WebSecurityConfigurerAdapter {
+		static AuthenticationTrustResolver TR
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.setSharedObject(AuthenticationTrustResolver, TR)
+		}
+	}
 }

+ 39 - 39
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationsTests.groovy

@@ -32,48 +32,48 @@ import org.springframework.security.web.access.intercept.FilterSecurityIntercept
  */
 public class UrlAuthorizationsTests extends BaseSpringSpec {
 
-    def "hasAnyAuthority('ROLE_USER')"() {
-        when:
-            def expression = UrlAuthorizationConfigurer.hasAnyAuthority("ROLE_USER")
-        then:
-            expression == ["ROLE_USER"]
-    }
+	def "hasAnyAuthority('ROLE_USER')"() {
+		when:
+			def expression = UrlAuthorizationConfigurer.hasAnyAuthority("ROLE_USER")
+		then:
+			expression == ["ROLE_USER"]
+	}
 
-    def "hasAnyAuthority('ROLE_USER','ROLE_ADMIN')"() {
-        when:
-            def expression =  UrlAuthorizationConfigurer.hasAnyAuthority("ROLE_USER","ROLE_ADMIN")
-        then:
-            expression == ["ROLE_USER","ROLE_ADMIN"]
-    }
+	def "hasAnyAuthority('ROLE_USER','ROLE_ADMIN')"() {
+		when:
+			def expression =  UrlAuthorizationConfigurer.hasAnyAuthority("ROLE_USER","ROLE_ADMIN")
+		then:
+			expression == ["ROLE_USER","ROLE_ADMIN"]
+	}
 
-    def "hasAnyRole('USER')"() {
-        when:
-            def expression = UrlAuthorizationConfigurer.hasAnyRole("USER")
-        then:
-            expression == ["ROLE_USER"]
-    }
+	def "hasAnyRole('USER')"() {
+		when:
+			def expression = UrlAuthorizationConfigurer.hasAnyRole("USER")
+		then:
+			expression == ["ROLE_USER"]
+	}
 
-    def "hasAnyRole('ROLE_USER','ROLE_ADMIN')"() {
-        when:
-            def expression =  UrlAuthorizationConfigurer.hasAnyRole("USER","ADMIN")
-        then:
-            expression == ["ROLE_USER","ROLE_ADMIN"]
-    }
+	def "hasAnyRole('ROLE_USER','ROLE_ADMIN')"() {
+		when:
+			def expression =  UrlAuthorizationConfigurer.hasAnyRole("USER","ADMIN")
+		then:
+			expression == ["ROLE_USER","ROLE_ADMIN"]
+	}
 
-    def "uses AffirmativeBased AccessDecisionManager"() {
-        when: "Load Config with no specific AccessDecisionManager"
-            loadConfig(NoSpecificAccessDecessionManagerConfig)
-        then: "AccessDecessionManager matches the HttpSecurityBuilder's default"
-            findFilter(FilterSecurityInterceptor).accessDecisionManager.class == AffirmativeBased
-    }
+	def "uses AffirmativeBased AccessDecisionManager"() {
+		when: "Load Config with no specific AccessDecisionManager"
+			loadConfig(NoSpecificAccessDecessionManagerConfig)
+		then: "AccessDecessionManager matches the HttpSecurityBuilder's default"
+			findFilter(FilterSecurityInterceptor).accessDecisionManager.class == AffirmativeBased
+	}
 
-    @EnableWebSecurity
-    static class NoSpecificAccessDecessionManagerConfig extends WebSecurityConfigurerAdapter {
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .apply(new UrlAuthorizationConfigurer()).getRegistry()
-                    .antMatchers("/a").hasRole("ADMIN")
-                    .anyRequest().hasRole("USER")
-        }
-    }
+	@EnableWebSecurity
+	static class NoSpecificAccessDecessionManagerConfig extends WebSecurityConfigurerAdapter {
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.apply(new UrlAuthorizationConfigurer()).getRegistry()
+					.antMatchers("/a").hasRole("ADMIN")
+					.anyRequest().hasRole("USER")
+		}
+	}
 }

+ 25 - 25
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/X509ConfigurerTests.groovy

@@ -30,31 +30,31 @@ import org.springframework.security.web.authentication.preauth.x509.X509Authenti
  */
 class X509ConfigurerTests extends BaseSpringSpec {
 
-    def "x509 ObjectPostProcessor"() {
-        setup:
-            AnyObjectPostProcessor opp = Mock()
-            HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
-        when:
-            http
-                .x509()
-                    .and()
-                .build()
+	def "x509 ObjectPostProcessor"() {
+		setup:
+			AnyObjectPostProcessor opp = Mock()
+			HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
+		when:
+			http
+				.x509()
+					.and()
+				.build()
 
-        then: "X509AuthenticationFilter is registered with LifecycleManager"
-            1 * opp.postProcess(_ as X509AuthenticationFilter) >> {X509AuthenticationFilter o -> o}
-    }
+		then: "X509AuthenticationFilter is registered with LifecycleManager"
+			1 * opp.postProcess(_ as X509AuthenticationFilter) >> {X509AuthenticationFilter o -> o}
+	}
 
-    def "invoke x509 twice does not override"() {
-        setup:
-            AnyObjectPostProcessor opp = Mock()
-            HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
-        when:
-            http
-                .x509()
-                    .subjectPrincipalRegex(".*")
-                    .and()
-                .x509()
-        then:
-            http.getConfigurer(X509Configurer).subjectPrincipalRegex == ".*"
-    }
+	def "invoke x509 twice does not override"() {
+		setup:
+			AnyObjectPostProcessor opp = Mock()
+			HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
+		when:
+			http
+				.x509()
+					.subjectPrincipalRegex(".*")
+					.and()
+				.x509()
+		then:
+			http.getConfigurer(X509Configurer).subjectPrincipalRegex == ".*"
+	}
 }

+ 43 - 43
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/openid/OpenIDLoginConfigurerTests.groovy

@@ -34,53 +34,53 @@ import org.springframework.security.openid.OpenIDAuthenticationToken
  */
 class OpenIDLoginConfigurerTests extends BaseSpringSpec {
 
-    def "openidLogin ObjectPostProcessor"() {
-        setup:
-            AnyObjectPostProcessor opp = Mock()
-            HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
-            UserDetailsService uds = authenticationBldr.getDefaultUserDetailsService()
-        when:
-            http
-                .openidLogin()
-                    .authenticationUserDetailsService(new UserDetailsByNameServiceWrapper<OpenIDAuthenticationToken>(uds))
-                    .and()
-                .build()
+	def "openidLogin ObjectPostProcessor"() {
+		setup:
+			AnyObjectPostProcessor opp = Mock()
+			HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
+			UserDetailsService uds = authenticationBldr.getDefaultUserDetailsService()
+		when:
+			http
+				.openidLogin()
+					.authenticationUserDetailsService(new UserDetailsByNameServiceWrapper<OpenIDAuthenticationToken>(uds))
+					.and()
+				.build()
 
-        then: "OpenIDAuthenticationFilter is registered with LifecycleManager"
-            1 * opp.postProcess(_ as OpenIDAuthenticationFilter) >> {OpenIDAuthenticationFilter o -> o}
-        and: "OpenIDAuthenticationProvider is registered with LifecycleManager"
-            1 * opp.postProcess(_ as OpenIDAuthenticationProvider) >> {OpenIDAuthenticationProvider o -> o}
-    }
+		then: "OpenIDAuthenticationFilter is registered with LifecycleManager"
+			1 * opp.postProcess(_ as OpenIDAuthenticationFilter) >> {OpenIDAuthenticationFilter o -> o}
+		and: "OpenIDAuthenticationProvider is registered with LifecycleManager"
+			1 * opp.postProcess(_ as OpenIDAuthenticationProvider) >> {OpenIDAuthenticationProvider o -> o}
+	}
 
-    def "invoke openidLogin twice does not override"() {
-        setup:
-            loadConfig(InvokeTwiceDoesNotOverrideConfig)
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.redirectedUrl.endsWith("/login/custom")
+	def "invoke openidLogin twice does not override"() {
+		setup:
+			loadConfig(InvokeTwiceDoesNotOverrideConfig)
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.redirectedUrl.endsWith("/login/custom")
 
-    }
+	}
 
-    @EnableWebSecurity
-    static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
+	@EnableWebSecurity
+	static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
 
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
-            auth
-                .inMemoryAuthentication()
-        }
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+		}
 
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .authorizeRequests()
-                    .anyRequest().authenticated()
-                    .and()
-                .openidLogin()
-                    .loginPage("/login/custom")
-                    .and()
-                .openidLogin()
-        }
-    }
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().authenticated()
+					.and()
+				.openidLogin()
+					.loginPage("/login/custom")
+					.and()
+				.openidLogin()
+		}
+	}
 }

+ 14 - 14
config/src/test/groovy/org/springframework/security/config/debug/SecurityDebugBeanFactoryPostProcessorTest.groovy

@@ -22,18 +22,18 @@ import org.springframework.security.web.debug.DebugFilter;
 
 class SecurityDebugBeanFactoryPostProcessorTest extends AbstractHttpConfigTests {
 
-    // SEC-1885
-    def 'SEC-1885 - SecurityDebugBeanFactoryPostProcessor works when dependencies have Autowired constructor'() {
-        when: 'debug used and FilterChainProxy has dependency with @Autowired constructor'
-        xml.debug()
-        httpAutoConfig {}
-        xml.'authentication-manager'() {
-            'authentication-provider'('ref': 'authProvider')
-        }
-        xml.'context:component-scan'('base-package':'org.springframework.security.config.debug')
-        createAppContext('')
-        then: 'TestAuthenticationProvider.<init>() is not thrown'
-        appContext.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN) instanceof DebugFilter
-        appContext.getBean(BeanIds.FILTER_CHAIN_PROXY) instanceof FilterChainProxy
-    }
+	// SEC-1885
+	def 'SEC-1885 - SecurityDebugBeanFactoryPostProcessor works when dependencies have Autowired constructor'() {
+		when: 'debug used and FilterChainProxy has dependency with @Autowired constructor'
+		xml.debug()
+		httpAutoConfig {}
+		xml.'authentication-manager'() {
+			'authentication-provider'('ref': 'authProvider')
+		}
+		xml.'context:component-scan'('base-package':'org.springframework.security.config.debug')
+		createAppContext('')
+		then: 'TestAuthenticationProvider.<init>() is not thrown'
+		appContext.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN) instanceof DebugFilter
+		appContext.getBean(BeanIds.FILTER_CHAIN_PROXY) instanceof FilterChainProxy
+	}
 }

+ 75 - 75
config/src/test/groovy/org/springframework/security/config/http/FormLoginBeanDefinitionParserTests.groovy

@@ -10,104 +10,104 @@ import org.springframework.mock.web.MockHttpServletResponse
  */
 class FormLoginBeanDefinitionParserTests extends AbstractHttpConfigTests {
 
-    def 'form-login default login page'() {
-        setup:
-            MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            MockFilterChain chain = new MockFilterChain()
-            httpAutoConfig {
-                csrf(disabled:true)
-            }
-            createAppContext()
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
+	def 'form-login default login page'() {
+		setup:
+			MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			MockFilterChain chain = new MockFilterChain()
+			httpAutoConfig {
+				csrf(disabled:true)
+			}
+			createAppContext()
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
 <h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
  <table>
-    <tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
-    <tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
-    <tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
+	<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
+	<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
+	<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
   </table>
 </form></body></html>"""
-    }
+	}
 
-    def 'form-login default login page custom attributes'() {
-        setup:
-            MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            MockFilterChain chain = new MockFilterChain()
-            httpAutoConfig {
-                'form-login'('login-processing-url':'/login_custom','username-parameter':'custom_user','password-parameter':'custom_password')
-                csrf(disabled:true)
-            }
-            createAppContext()
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.custom_user.focus();'>
+	def 'form-login default login page custom attributes'() {
+		setup:
+			MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			MockFilterChain chain = new MockFilterChain()
+			httpAutoConfig {
+				'form-login'('login-processing-url':'/login_custom','username-parameter':'custom_user','password-parameter':'custom_password')
+				csrf(disabled:true)
+			}
+			createAppContext()
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.custom_user.focus();'>
 <h3>Login with Username and Password</h3><form name='f' action='/login_custom' method='POST'>
  <table>
-    <tr><td>User:</td><td><input type='text' name='custom_user' value=''></td></tr>
-    <tr><td>Password:</td><td><input type='password' name='custom_password'/></td></tr>
-    <tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
+	<tr><td>User:</td><td><input type='text' name='custom_user' value=''></td></tr>
+	<tr><td>Password:</td><td><input type='password' name='custom_password'/></td></tr>
+	<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
   </table>
 </form></body></html>"""
-    }
+	}
 
-    def 'openid-login default login page'() {
-        setup:
-            MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            MockFilterChain chain = new MockFilterChain()
-            httpAutoConfig {
-                'openid-login'()
-                csrf(disabled:true)
-            }
-            createAppContext()
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
+	def 'openid-login default login page'() {
+		setup:
+			MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			MockFilterChain chain = new MockFilterChain()
+			httpAutoConfig {
+				'openid-login'()
+				csrf(disabled:true)
+			}
+			createAppContext()
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
 <h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
  <table>
-    <tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
-    <tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
-    <tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
+	<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
+	<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
+	<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
   </table>
 </form><h3>Login with OpenID Identity</h3><form name='oidf' action='/login/openid' method='POST'>
  <table>
-    <tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
-    <tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
+	<tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
+	<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
   </table>
 </form></body></html>"""
-    }
+	}
 
-    def 'openid-login default login page custom attributes'() {
-        setup:
-            MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
-            MockHttpServletResponse response = new MockHttpServletResponse()
-            MockFilterChain chain = new MockFilterChain()
-            httpAutoConfig {
-                'openid-login'('login-processing-url':'/login_custom')
-                csrf(disabled:true)
-            }
-            createAppContext()
-        when:
-            springSecurityFilterChain.doFilter(request,response,chain)
-        then:
-            response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
+	def 'openid-login default login page custom attributes'() {
+		setup:
+			MockHttpServletRequest request = new MockHttpServletRequest(method:'GET',requestURI:'/login')
+			MockHttpServletResponse response = new MockHttpServletResponse()
+			MockFilterChain chain = new MockFilterChain()
+			httpAutoConfig {
+				'openid-login'('login-processing-url':'/login_custom')
+				csrf(disabled:true)
+			}
+			createAppContext()
+		when:
+			springSecurityFilterChain.doFilter(request,response,chain)
+		then:
+			response.getContentAsString() == """<html><head><title>Login Page</title></head><body onload='document.f.username.focus();'>
 <h3>Login with Username and Password</h3><form name='f' action='/login' method='POST'>
  <table>
-    <tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
-    <tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
-    <tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
+	<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
+	<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
+	<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
   </table>
 </form><h3>Login with OpenID Identity</h3><form name='oidf' action='/login_custom' method='POST'>
  <table>
-    <tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
-    <tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
+	<tr><td>Identity:</td><td><input type='text' size='30' name='openid_identifier'/></td></tr>
+	<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
   </table>
 </form></body></html>"""
-    }
+	}
 }

+ 97 - 97
config/src/test/groovy/org/springframework/security/config/http/SecurityContextHolderAwareRequestConfigTests.groovy

@@ -45,101 +45,101 @@ import org.springframework.security.web.servletapi.SecurityContextHolderAwareReq
  */
 class SecurityContextHolderAwareRequestConfigTests extends AbstractHttpConfigTests {
 
-    def withAutoConfig() {
-        httpAutoConfig () {
-            csrf(disabled:true)
-        }
-        createAppContext(AUTH_PROVIDER_XML)
-
-        def securityContextAwareFilter = getFilter(SecurityContextHolderAwareRequestFilter)
-
-        expect:
-        securityContextAwareFilter.authenticationEntryPoint.loginFormUrl == getFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl
-        securityContextAwareFilter.authenticationManager == getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
-        securityContextAwareFilter.logoutHandlers.size() == 1
-        securityContextAwareFilter.logoutHandlers[0].class == SecurityContextLogoutHandler
-    }
-
-    def explicitEntryPoint() {
-        xml.http() {
-            'http-basic'('entry-point-ref': 'ep')
-        }
-        bean('ep', BasicAuthenticationEntryPoint.class.name, ['realmName':'whocares'],[:])
-        createAppContext(AUTH_PROVIDER_XML)
-
-        def securityContextAwareFilter = getFilter(SecurityContextHolderAwareRequestFilter)
-
-        expect:
-        securityContextAwareFilter.authenticationEntryPoint == getFilter(ExceptionTranslationFilter).authenticationEntryPoint
-        securityContextAwareFilter.authenticationManager == getFilter(BasicAuthenticationFilter).authenticationManager
-        securityContextAwareFilter.logoutHandlers == null
-    }
-
-    def formLogin() {
-        xml.http() {
-            'form-login'()
-        }
-        createAppContext(AUTH_PROVIDER_XML)
-
-        def securityContextAwareFilter = getFilter(SecurityContextHolderAwareRequestFilter)
-
-        expect:
-        securityContextAwareFilter.authenticationEntryPoint.loginFormUrl == getFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl
-        securityContextAwareFilter.authenticationManager == getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
-        securityContextAwareFilter.logoutHandlers == null
-    }
-
-    def multiHttp() {
-        xml.http('authentication-manager-ref' : 'authManager', 'pattern' : '/first/**') {
-            'form-login'('login-page' : '/login')
-            'logout'('invalidate-session' : 'true')
-            csrf(disabled:true)
-        }
-        xml.http('authentication-manager-ref' : 'authManager2') {
-            'form-login'('login-page' : '/login2')
-            'logout'('invalidate-session' : 'false')
-            csrf(disabled:true)
-        }
-
-        String secondAuthManager = AUTH_PROVIDER_XML.replace("alias='authManager'", "id='authManager2'")
-        createAppContext(AUTH_PROVIDER_XML + secondAuthManager)
-
-        def securityContextAwareFilter = getFilters('/first/filters').find { it instanceof SecurityContextHolderAwareRequestFilter }
-        def secondSecurityContextAwareFilter = getFilter(SecurityContextHolderAwareRequestFilter)
-
-        expect:
-        securityContextAwareFilter.authenticationEntryPoint.loginFormUrl == '/login'
-        securityContextAwareFilter.authenticationManager == getFilters('/first/filters').find { it instanceof UsernamePasswordAuthenticationFilter}.authenticationManager
-        securityContextAwareFilter.authenticationManager.parent == appContext.getBean('authManager')
-        securityContextAwareFilter.logoutHandlers.size() == 1
-        securityContextAwareFilter.logoutHandlers[0].class == SecurityContextLogoutHandler
-        securityContextAwareFilter.logoutHandlers[0].invalidateHttpSession == true
-
-        secondSecurityContextAwareFilter.authenticationEntryPoint.loginFormUrl == '/login2'
-        secondSecurityContextAwareFilter.authenticationManager == getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
-        secondSecurityContextAwareFilter.authenticationManager.parent == appContext.getBean('authManager2')
-        securityContextAwareFilter.logoutHandlers.size() == 1
-        secondSecurityContextAwareFilter.logoutHandlers[0].class == SecurityContextLogoutHandler
-        secondSecurityContextAwareFilter.logoutHandlers[0].invalidateHttpSession == false
-    }
-
-    def logoutCustom() {
-        xml.http() {
-            'form-login'('login-page' : '/login')
-            'logout'('invalidate-session' : 'false', 'logout-success-url' : '/login?logout', 'delete-cookies' : 'JSESSIONID')
-            csrf(disabled:true)
-        }
-        createAppContext(AUTH_PROVIDER_XML)
-
-        def securityContextAwareFilter = getFilter(SecurityContextHolderAwareRequestFilter)
-
-        expect:
-        securityContextAwareFilter.authenticationEntryPoint.loginFormUrl == getFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl
-        securityContextAwareFilter.authenticationManager == getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
-        securityContextAwareFilter.logoutHandlers.size() == 2
-        securityContextAwareFilter.logoutHandlers[0].class == SecurityContextLogoutHandler
-        securityContextAwareFilter.logoutHandlers[0].invalidateHttpSession == false
-        securityContextAwareFilter.logoutHandlers[1].class == CookieClearingLogoutHandler
-        securityContextAwareFilter.logoutHandlers[1].cookiesToClear == ['JSESSIONID']
-    }
+	def withAutoConfig() {
+		httpAutoConfig () {
+			csrf(disabled:true)
+		}
+		createAppContext(AUTH_PROVIDER_XML)
+
+		def securityContextAwareFilter = getFilter(SecurityContextHolderAwareRequestFilter)
+
+		expect:
+		securityContextAwareFilter.authenticationEntryPoint.loginFormUrl == getFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl
+		securityContextAwareFilter.authenticationManager == getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
+		securityContextAwareFilter.logoutHandlers.size() == 1
+		securityContextAwareFilter.logoutHandlers[0].class == SecurityContextLogoutHandler
+	}
+
+	def explicitEntryPoint() {
+		xml.http() {
+			'http-basic'('entry-point-ref': 'ep')
+		}
+		bean('ep', BasicAuthenticationEntryPoint.class.name, ['realmName':'whocares'],[:])
+		createAppContext(AUTH_PROVIDER_XML)
+
+		def securityContextAwareFilter = getFilter(SecurityContextHolderAwareRequestFilter)
+
+		expect:
+		securityContextAwareFilter.authenticationEntryPoint == getFilter(ExceptionTranslationFilter).authenticationEntryPoint
+		securityContextAwareFilter.authenticationManager == getFilter(BasicAuthenticationFilter).authenticationManager
+		securityContextAwareFilter.logoutHandlers == null
+	}
+
+	def formLogin() {
+		xml.http() {
+			'form-login'()
+		}
+		createAppContext(AUTH_PROVIDER_XML)
+
+		def securityContextAwareFilter = getFilter(SecurityContextHolderAwareRequestFilter)
+
+		expect:
+		securityContextAwareFilter.authenticationEntryPoint.loginFormUrl == getFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl
+		securityContextAwareFilter.authenticationManager == getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
+		securityContextAwareFilter.logoutHandlers == null
+	}
+
+	def multiHttp() {
+		xml.http('authentication-manager-ref' : 'authManager', 'pattern' : '/first/**') {
+			'form-login'('login-page' : '/login')
+			'logout'('invalidate-session' : 'true')
+			csrf(disabled:true)
+		}
+		xml.http('authentication-manager-ref' : 'authManager2') {
+			'form-login'('login-page' : '/login2')
+			'logout'('invalidate-session' : 'false')
+			csrf(disabled:true)
+		}
+
+		String secondAuthManager = AUTH_PROVIDER_XML.replace("alias='authManager'", "id='authManager2'")
+		createAppContext(AUTH_PROVIDER_XML + secondAuthManager)
+
+		def securityContextAwareFilter = getFilters('/first/filters').find { it instanceof SecurityContextHolderAwareRequestFilter }
+		def secondSecurityContextAwareFilter = getFilter(SecurityContextHolderAwareRequestFilter)
+
+		expect:
+		securityContextAwareFilter.authenticationEntryPoint.loginFormUrl == '/login'
+		securityContextAwareFilter.authenticationManager == getFilters('/first/filters').find { it instanceof UsernamePasswordAuthenticationFilter}.authenticationManager
+		securityContextAwareFilter.authenticationManager.parent == appContext.getBean('authManager')
+		securityContextAwareFilter.logoutHandlers.size() == 1
+		securityContextAwareFilter.logoutHandlers[0].class == SecurityContextLogoutHandler
+		securityContextAwareFilter.logoutHandlers[0].invalidateHttpSession == true
+
+		secondSecurityContextAwareFilter.authenticationEntryPoint.loginFormUrl == '/login2'
+		secondSecurityContextAwareFilter.authenticationManager == getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
+		secondSecurityContextAwareFilter.authenticationManager.parent == appContext.getBean('authManager2')
+		securityContextAwareFilter.logoutHandlers.size() == 1
+		secondSecurityContextAwareFilter.logoutHandlers[0].class == SecurityContextLogoutHandler
+		secondSecurityContextAwareFilter.logoutHandlers[0].invalidateHttpSession == false
+	}
+
+	def logoutCustom() {
+		xml.http() {
+			'form-login'('login-page' : '/login')
+			'logout'('invalidate-session' : 'false', 'logout-success-url' : '/login?logout', 'delete-cookies' : 'JSESSIONID')
+			csrf(disabled:true)
+		}
+		createAppContext(AUTH_PROVIDER_XML)
+
+		def securityContextAwareFilter = getFilter(SecurityContextHolderAwareRequestFilter)
+
+		expect:
+		securityContextAwareFilter.authenticationEntryPoint.loginFormUrl == getFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl
+		securityContextAwareFilter.authenticationManager == getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
+		securityContextAwareFilter.logoutHandlers.size() == 2
+		securityContextAwareFilter.logoutHandlers[0].class == SecurityContextLogoutHandler
+		securityContextAwareFilter.logoutHandlers[0].invalidateHttpSession == false
+		securityContextAwareFilter.logoutHandlers[1].class == CookieClearingLogoutHandler
+		securityContextAwareFilter.logoutHandlers[1].cookiesToClear == ['JSESSIONID']
+	}
 }

+ 17 - 17
config/src/test/resources/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessorTests-aopconfig.xml

@@ -1,23 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xmlns:aop="http://www.springframework.org/schema/aop"
-    xmlns:p="http://www.springframework.org/schema/p"
-    xmlns:context="http://www.springframework.org/schema/context"
-    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
-        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
-        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:aop="http://www.springframework.org/schema/aop"
+	xmlns:p="http://www.springframework.org/schema/p"
+	xmlns:context="http://www.springframework.org/schema/context"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
+		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
 
-    <context:annotation-config/>
+	<context:annotation-config/>
 
-    <bean class="org.springframework.security.config.annotation.configuration.AutowireBeanFactoryObjectPostProcessorTests$WithBanNameAutoProxyCreatorConfig"/>
+	<bean class="org.springframework.security.config.annotation.configuration.AutowireBeanFactoryObjectPostProcessorTests$WithBanNameAutoProxyCreatorConfig"/>
 
-    <bean id="interceptor" class="org.springframework.security.config.annotation.configuration.AroundMethodInterceptor"/>
-    <bean id="myBean" class="org.springframework.security.config.annotation.configuration.MyAdvisedBean"/>
-    <bean id="autoProxy" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"
-        p:beanNames="myBean"
-        p:interceptorNames="interceptor"/>
-       <bean id="pointcutAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"
-           p:mappedName="doStuff"
-           p:advice-ref="interceptor"/>
+	<bean id="interceptor" class="org.springframework.security.config.annotation.configuration.AroundMethodInterceptor"/>
+	<bean id="myBean" class="org.springframework.security.config.annotation.configuration.MyAdvisedBean"/>
+	<bean id="autoProxy" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"
+		p:beanNames="myBean"
+		p:interceptorNames="interceptor"/>
+	   <bean id="pointcutAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"
+		   p:mappedName="doStuff"
+		   p:advice-ref="interceptor"/>
 </beans>

+ 36 - 36
core/src/test/resources/org/springframework/security/authentication/jaas/DefaultJaasAuthenticationProviderTests.xml

@@ -1,41 +1,41 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
-    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
 
-    <bean id="jaasAuthProvider"
-        class="org.springframework.security.authentication.jaas.DefaultJaasAuthenticationProvider">
-        <property name="configuration">
-            <bean
-                class="org.springframework.security.authentication.jaas.memory.InMemoryConfiguration">
-                <constructor-arg>
-                    <map>
-                        <entry key="SPRINGSECURITY">
-                            <array>
-                                <bean
-                                    class="javax.security.auth.login.AppConfigurationEntry">
-                                    <constructor-arg
-                                        value="org.springframework.security.authentication.jaas.TestLoginModule" />
-                                    <constructor-arg>
-                                        <util:constant
-                                            static-field="javax.security.auth.login.AppConfigurationEntry$LoginModuleControlFlag.REQUIRED" />
-                                    </constructor-arg>
-                                    <constructor-arg>
-                                        <map></map>
-                                    </constructor-arg>
-                                </bean>
-                            </array>
-                        </entry>
-                    </map>
-                </constructor-arg>
-            </bean>
-        </property>
-        <property name="authorityGranters">
-            <list>
-                <bean
-                    class="org.springframework.security.authentication.jaas.TestAuthorityGranter" />
-            </list>
-        </property>
-    </bean>
+	<bean id="jaasAuthProvider"
+		class="org.springframework.security.authentication.jaas.DefaultJaasAuthenticationProvider">
+		<property name="configuration">
+			<bean
+				class="org.springframework.security.authentication.jaas.memory.InMemoryConfiguration">
+				<constructor-arg>
+					<map>
+						<entry key="SPRINGSECURITY">
+							<array>
+								<bean
+									class="javax.security.auth.login.AppConfigurationEntry">
+									<constructor-arg
+										value="org.springframework.security.authentication.jaas.TestLoginModule" />
+									<constructor-arg>
+										<util:constant
+											static-field="javax.security.auth.login.AppConfigurationEntry$LoginModuleControlFlag.REQUIRED" />
+									</constructor-arg>
+									<constructor-arg>
+										<map></map>
+									</constructor-arg>
+								</bean>
+							</array>
+						</entry>
+					</map>
+				</constructor-arg>
+			</bean>
+		</property>
+		<property name="authorityGranters">
+			<list>
+				<bean
+					class="org.springframework.security.authentication.jaas.TestAuthorityGranter" />
+			</list>
+		</property>
+	</bean>
 </beans>

+ 4 - 4
itest/context/src/integration-test/resources/logback-test.xml

@@ -1,15 +1,15 @@
 <configuration>
   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
+	<encoder>
+	  <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+	</encoder>
   </appender>
 
   <logger name="org.springframework.security" level="${sec.log.level}:-WARN"/>
   <logger name="org.apache.directory" level="ERROR"/>
 
   <root level="${root.level}:-WARN">
-    <appender-ref ref="STDOUT" />
+	<appender-ref ref="STDOUT" />
   </root>
 
 </configuration>

+ 23 - 23
itest/context/src/integration-test/resources/sec-933-app-context.xml

@@ -1,32 +1,32 @@
 <beans xmlns="http://www.springframework.org/schema/beans"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xmlns:aop="http://www.springframework.org/schema/aop"
-    xmlns:tx="http://www.springframework.org/schema/tx"
-    xmlns:security="http://www.springframework.org/schema/security"
-    xsi:schemaLocation="
-    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
-    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
-    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
-    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:aop="http://www.springframework.org/schema/aop"
+	xmlns:tx="http://www.springframework.org/schema/tx"
+	xmlns:security="http://www.springframework.org/schema/security"
+	xsi:schemaLocation="
+	http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+	http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
+	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
+	http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
 
 
-    <bean id="userRepository" class="org.springframework.security.integration.StubUserRepository"/>
+	<bean id="userRepository" class="org.springframework.security.integration.StubUserRepository"/>
 
-    <security:authentication-manager>
-        <security:authentication-provider
-        user-service-ref="userDetailsService" />
-    </security:authentication-manager>
+	<security:authentication-manager>
+		<security:authentication-provider
+		user-service-ref="userDetailsService" />
+	</security:authentication-manager>
 
-    <bean id="userDetailsService" class="org.springframework.security.integration.UserDetailsServiceImpl">
-        <property name="userRepository" ref="userRepository"/>
-    </bean>
+	<bean id="userDetailsService" class="org.springframework.security.integration.UserDetailsServiceImpl">
+		<property name="userRepository" ref="userRepository"/>
+	</bean>
 
-    <security:global-method-security>
-        <security:protect-pointcut
-            expression="execution(* org.springframework.security.integration.*Repository+.*(..))"
-            access="ROLE_LOGGEDIN" />
-    </security:global-method-security>
+	<security:global-method-security>
+		<security:protect-pointcut
+			expression="execution(* org.springframework.security.integration.*Repository+.*(..))"
+			access="ROLE_LOGGEDIN" />
+	</security:global-method-security>
 
-    <aop:aspectj-autoproxy/>
+	<aop:aspectj-autoproxy/>
 
 </beans>

+ 46 - 46
itest/context/src/integration-test/resources/sec-936-app-context.xml

@@ -1,54 +1,54 @@
 <beans xmlns="http://www.springframework.org/schema/beans"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xmlns:util="http://www.springframework.org/schema/util"
-    xmlns:security="http://www.springframework.org/schema/security"
-    xsi:schemaLocation="
-    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
-    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
-    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:util="http://www.springframework.org/schema/util"
+	xmlns:security="http://www.springframework.org/schema/security"
+	xsi:schemaLocation="
+	http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
+	http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
 
-    <security:authentication-manager alias="authenticationManager">
-        <security:authentication-provider>
-            <security:user-service>
-                <security:user name="bob" password="bobspassword" authorities="ROLE_A,ROLE_B"/>
-            </security:user-service>
-        </security:authentication-provider>
-    </security:authentication-manager>
+	<security:authentication-manager alias="authenticationManager">
+		<security:authentication-provider>
+			<security:user-service>
+				<security:user name="bob" password="bobspassword" authorities="ROLE_A,ROLE_B"/>
+			</security:user-service>
+		</security:authentication-provider>
+	</security:authentication-manager>
 
-    <bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
-        <constructor-arg>
-            <util:list>
-                <bean class="org.springframework.security.access.vote.RoleVoter" />
-                <bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
-            </util:list>
-        </constructor-arg>
-        <property name="allowIfAllAbstainDecisions" value="false"/>
-    </bean>
+	<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
+		<constructor-arg>
+			<util:list>
+				<bean class="org.springframework.security.access.vote.RoleVoter" />
+				<bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
+			</util:list>
+		</constructor-arg>
+		<property name="allowIfAllAbstainDecisions" value="false"/>
+	</bean>
 
-    <bean id="securityInterceptor" class="org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor">
-        <property name="validateConfigAttributes" value="true"/>
-        <property name="rejectPublicInvocations" value="true"/>
-        <property name="authenticationManager" ref="authenticationManager"/>
-        <property name="accessDecisionManager" ref="accessDecisionManager"/>
-        <property name="securityMetadataSource">
-            <security:method-security-metadata-source>
-                <security:protect method="org.springframework.security.core.session.SessionRegistry.get*" access="ROLE_C" />
-            </security:method-security-metadata-source>
-        </property>
-    </bean>
+	<bean id="securityInterceptor" class="org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor">
+		<property name="validateConfigAttributes" value="true"/>
+		<property name="rejectPublicInvocations" value="true"/>
+		<property name="authenticationManager" ref="authenticationManager"/>
+		<property name="accessDecisionManager" ref="accessDecisionManager"/>
+		<property name="securityMetadataSource">
+			<security:method-security-metadata-source>
+				<security:protect method="org.springframework.security.core.session.SessionRegistry.get*" access="ROLE_C" />
+			</security:method-security-metadata-source>
+		</property>
+	</bean>
 
-    <bean id="httpRemoteService" class="org.springframework.aop.framework.ProxyFactoryBean">
-        <property name="proxyInterfaces" value="org.springframework.security.core.session.SessionRegistry"/>
-        <property name="interceptorNames">
-            <list>
-                <value>securityInterceptor</value>
-                <value>httpInvokerClientInterceptor</value>
-            </list>
-        </property>
-    </bean>
+	<bean id="httpRemoteService" class="org.springframework.aop.framework.ProxyFactoryBean">
+		<property name="proxyInterfaces" value="org.springframework.security.core.session.SessionRegistry"/>
+		<property name="interceptorNames">
+			<list>
+				<value>securityInterceptor</value>
+				<value>httpInvokerClientInterceptor</value>
+			</list>
+		</property>
+	</bean>
 
-    <bean id="httpInvokerClientInterceptor" class="org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor">
-        <property name="serviceUrl" value="http://somehost/someUrl"/>
-    </bean>
+	<bean id="httpInvokerClientInterceptor" class="org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor">
+		<property name="serviceUrl" value="http://somehost/someUrl"/>
+	</bean>
 
 </beans>

+ 180 - 180
itest/misc/src/integration-test/java/org/springframework/security/concurrent/SessionRegistryImplMTTests.java

@@ -28,185 +28,185 @@ import java.util.Random;
  * @author Luke Taylor
  */
 public class SessionRegistryImplMTTests extends TestCase {
-    private static final Random rnd = new Random();
-    private static boolean errorOccurred;
-
-    protected void setUp() throws Exception {
-        errorOccurred = false;
-    }
-
-    /**
-     * Reproduces the NPE mentioned in SEC-484 where a sessionId is removed from
-     * the set of sessions before it is removed from the list of sessions for a principal.
-     * getAllSessions(principal, false) then finds the sessionId in the principal's session list
-     * but reads null for the SessionInformation with the same Id.
-     * Note that this is not guaranteed to produce the error but is a good testing point. Increasing the number
-     * of sessions makes a failure more likely, but slows the test considerably.
-     * Inserting temporary sleep statements in SessionRegistryClassImpl will also help.
-     */
-    public void testConcurrencyOfReadAndRemoveIsSafe() {
-        Object principal = "Joe Principal";
-        SessionRegistryImpl sessionregistry = new SessionRegistryImpl();
-        Set sessions = Collections.synchronizedSet(new HashSet());
-        // Register some sessions
-        for (int i = 0; i < 50; i++) {
-            String sessionId = Integer.toString(i);
-            sessions.add(sessionId);
-            sessionregistry.registerNewSession(sessionId, principal);
-        }
-
-        // Pile of readers to hammer the getAllSessions method.
-        for (int i=0; i < 10; i++) {
-            Thread reader = new Thread(new SessionRegistryReader(principal, sessionregistry));
-            reader.start();
-        }
-
-        Thread remover = new Thread(new SessionRemover("remover", sessionregistry, sessions));
-
-        remover.start();
-
-        while(remover.isAlive()) {
-            pause(250);
-        }
-
-        assertFalse("Thread errors detected; review log output for details", errorOccurred);
-    }
-
-    public void testConcurrentRemovalIsSafe() {
-        Object principal = "Some principal object";
-        SessionRegistryImpl sessionregistry = new SessionRegistryImpl();
-        // The session list (effectivelly the containers sessions).
-        Set sessions = Collections.synchronizedSet(new HashSet());
-        Thread registerer = new Thread(new SessionRegisterer(principal, sessionregistry, 100, sessions));
-
-        registerer.start();
-
-        int nRemovers = 4;
-
-        SessionRemover[] removers = new SessionRemover[nRemovers];
-        Thread[] removerThreads = new Thread[nRemovers];
-
-        for (int i = 0; i < removers.length; i++) {
-            removers[i] = new SessionRemover("remover" + i, sessionregistry, sessions);
-            removerThreads[i] = new Thread(removers[i], "remover" + i);
-            removerThreads[i].start();
-        }
-
-        while (stillRunning(removerThreads)) {
-            pause(500);
-        }
-    }
-
-    private boolean stillRunning(Thread[] threads) {
-        for (int i = 0; i < threads.length; i++) {
-            if (threads[i].isAlive()) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    private static class SessionRegisterer implements Runnable {
-        private SessionRegistry sessionregistry;
-        private int nIterations;
-        private Set sessionList;
-        private Object principal;
-
-        public SessionRegisterer(Object principal, SessionRegistry sessionregistry, int nIterations, Set sessionList) {
-            this.sessionregistry = sessionregistry;
-            this.nIterations = nIterations;
-            this.sessionList = sessionList;
-            this.principal = principal;
-        }
-
-        public void run() {
-            for (int i=0; i < nIterations && !errorOccurred; i++) {
-                String sessionId = Integer.toString(i);
-                sessionList.add(sessionId);
-                try {
-                    sessionregistry.registerNewSession(sessionId,principal);
-                    pause(20);
-                    Thread.yield();
-                } catch(Exception e) {
-                    e.printStackTrace();
-                    errorOccurred = true;
-                }
-            }
-        }
-    }
-
-    private static class SessionRegistryReader implements Runnable {
-        private SessionRegistry sessionRegistry;
-        private Object principal;
-
-        public SessionRegistryReader(Object principal, SessionRegistry sessionregistry) {
-            this.sessionRegistry = sessionregistry;
-            this.principal = principal;
-        }
-
-        public void run() {
-            while (!errorOccurred) {
-                try {
-                    sessionRegistry.getAllSessions(principal, false);
-                    sessionRegistry.getAllPrincipals();
-                    sessionRegistry.getAllSessions(principal, true);
-                    Thread.yield();
-                } catch (Exception e) {
-                    e.printStackTrace();
-                    errorOccurred = true;
-                }
-            }
-        }
-    }
-
-    private static class SessionRemover implements Runnable {
-        private SessionRegistry sessionregistry;
-        private Set sessionList;
-        private String name;
-
-        public SessionRemover(String name, SessionRegistry sessionregistry, Set sessionList) {
-            this.name = name;
-            this.sessionregistry = sessionregistry;
-            this.sessionList = sessionList;
-        }
-
-        public void run() {
-            boolean finished = false;
-
-            while (!finished && !errorOccurred) {
-                if (sessionList.isEmpty()) {
-                    finished = true;
-                    // List of sessions appears to be empty but give it a chance to fill up again
-                    System.out.println(name + ": Session list empty. Waiting.");
-                    pause(500);
-                }
-
-                Object[] sessions = sessionList.toArray();
-
-                if (sessions.length > 0) {
-                    finished = false;
-                    String sessionId = (String) sessions[0];
+	private static final Random rnd = new Random();
+	private static boolean errorOccurred;
+
+	protected void setUp() throws Exception {
+		errorOccurred = false;
+	}
+
+	/**
+	 * Reproduces the NPE mentioned in SEC-484 where a sessionId is removed from
+	 * the set of sessions before it is removed from the list of sessions for a principal.
+	 * getAllSessions(principal, false) then finds the sessionId in the principal's session list
+	 * but reads null for the SessionInformation with the same Id.
+	 * Note that this is not guaranteed to produce the error but is a good testing point. Increasing the number
+	 * of sessions makes a failure more likely, but slows the test considerably.
+	 * Inserting temporary sleep statements in SessionRegistryClassImpl will also help.
+	 */
+	public void testConcurrencyOfReadAndRemoveIsSafe() {
+		Object principal = "Joe Principal";
+		SessionRegistryImpl sessionregistry = new SessionRegistryImpl();
+		Set sessions = Collections.synchronizedSet(new HashSet());
+		// Register some sessions
+		for (int i = 0; i < 50; i++) {
+			String sessionId = Integer.toString(i);
+			sessions.add(sessionId);
+			sessionregistry.registerNewSession(sessionId, principal);
+		}
+
+		// Pile of readers to hammer the getAllSessions method.
+		for (int i=0; i < 10; i++) {
+			Thread reader = new Thread(new SessionRegistryReader(principal, sessionregistry));
+			reader.start();
+		}
+
+		Thread remover = new Thread(new SessionRemover("remover", sessionregistry, sessions));
+
+		remover.start();
+
+		while(remover.isAlive()) {
+			pause(250);
+		}
+
+		assertFalse("Thread errors detected; review log output for details", errorOccurred);
+	}
+
+	public void testConcurrentRemovalIsSafe() {
+		Object principal = "Some principal object";
+		SessionRegistryImpl sessionregistry = new SessionRegistryImpl();
+		// The session list (effectivelly the containers sessions).
+		Set sessions = Collections.synchronizedSet(new HashSet());
+		Thread registerer = new Thread(new SessionRegisterer(principal, sessionregistry, 100, sessions));
+
+		registerer.start();
+
+		int nRemovers = 4;
+
+		SessionRemover[] removers = new SessionRemover[nRemovers];
+		Thread[] removerThreads = new Thread[nRemovers];
+
+		for (int i = 0; i < removers.length; i++) {
+			removers[i] = new SessionRemover("remover" + i, sessionregistry, sessions);
+			removerThreads[i] = new Thread(removers[i], "remover" + i);
+			removerThreads[i].start();
+		}
+
+		while (stillRunning(removerThreads)) {
+			pause(500);
+		}
+	}
+
+	private boolean stillRunning(Thread[] threads) {
+		for (int i = 0; i < threads.length; i++) {
+			if (threads[i].isAlive()) {
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+	private static class SessionRegisterer implements Runnable {
+		private SessionRegistry sessionregistry;
+		private int nIterations;
+		private Set sessionList;
+		private Object principal;
+
+		public SessionRegisterer(Object principal, SessionRegistry sessionregistry, int nIterations, Set sessionList) {
+			this.sessionregistry = sessionregistry;
+			this.nIterations = nIterations;
+			this.sessionList = sessionList;
+			this.principal = principal;
+		}
+
+		public void run() {
+			for (int i=0; i < nIterations && !errorOccurred; i++) {
+				String sessionId = Integer.toString(i);
+				sessionList.add(sessionId);
+				try {
+					sessionregistry.registerNewSession(sessionId,principal);
+					pause(20);
+					Thread.yield();
+				} catch(Exception e) {
+					e.printStackTrace();
+					errorOccurred = true;
+				}
+			}
+		}
+	}
+
+	private static class SessionRegistryReader implements Runnable {
+		private SessionRegistry sessionRegistry;
+		private Object principal;
+
+		public SessionRegistryReader(Object principal, SessionRegistry sessionregistry) {
+			this.sessionRegistry = sessionregistry;
+			this.principal = principal;
+		}
+
+		public void run() {
+			while (!errorOccurred) {
+				try {
+					sessionRegistry.getAllSessions(principal, false);
+					sessionRegistry.getAllPrincipals();
+					sessionRegistry.getAllSessions(principal, true);
+					Thread.yield();
+				} catch (Exception e) {
+					e.printStackTrace();
+					errorOccurred = true;
+				}
+			}
+		}
+	}
+
+	private static class SessionRemover implements Runnable {
+		private SessionRegistry sessionregistry;
+		private Set sessionList;
+		private String name;
+
+		public SessionRemover(String name, SessionRegistry sessionregistry, Set sessionList) {
+			this.name = name;
+			this.sessionregistry = sessionregistry;
+			this.sessionList = sessionList;
+		}
+
+		public void run() {
+			boolean finished = false;
+
+			while (!finished && !errorOccurred) {
+				if (sessionList.isEmpty()) {
+					finished = true;
+					// List of sessions appears to be empty but give it a chance to fill up again
+					System.out.println(name + ": Session list empty. Waiting.");
+					pause(500);
+				}
+
+				Object[] sessions = sessionList.toArray();
+
+				if (sessions.length > 0) {
+					finished = false;
+					String sessionId = (String) sessions[0];
 //                    System.out.println(name + ": removing " + sessionId);
-                    try {
-                        sessionregistry.removeSessionInformation(sessionId);
-
-                        pause(rnd.nextInt(100));
-
-                        sessionList.remove(sessionId);
-                        Thread.yield();
-                    } catch (Exception e) {
-                        e.printStackTrace();
-                        errorOccurred = true;
-                    }
-                }
-            }
-        }
-    }
-
-    private static void pause(int length) {
-        try {
-            Thread.sleep(length);
-        } catch (InterruptedException ignore) {}
-    }
+					try {
+						sessionregistry.removeSessionInformation(sessionId);
+
+						pause(rnd.nextInt(100));
+
+						sessionList.remove(sessionId);
+						Thread.yield();
+					} catch (Exception e) {
+						e.printStackTrace();
+						errorOccurred = true;
+					}
+				}
+			}
+		}
+	}
+
+	private static void pause(int length) {
+		try {
+			Thread.sleep(length);
+		} catch (InterruptedException ignore) {}
+	}
 }

+ 197 - 197
itest/misc/src/integration-test/java/org/springframework/security/context/SecurityContextHolderMTTests.java

@@ -16,201 +16,201 @@ import org.springframework.security.providers.UsernamePasswordAuthenticationToke
  * @Author Luke Taylor
  */
 public class SecurityContextHolderMTTests extends TestCase{
-    private int errors = 0;
-
-    private static final int NUM_OPS = 25;
-    private static final int NUM_THREADS = 25;
-
-    public final void setUp() throws Exception {
-        SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
-    }
-
-    public void testSynchronizationCustomStrategyLoading() {
-        SecurityContextHolder.setStrategyName(InheritableThreadLocalSecurityContextHolderStrategy.class.getName());
-        assertTrue(new SecurityContextHolder().toString()
-                                              .lastIndexOf("SecurityContextHolder[strategy='org.springframework.security.context.InheritableThreadLocalSecurityContextHolderStrategy'") != -1);
-        loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, false, true);
-        assertEquals("Thread errors detected; review log output for details", 0, errors);
-    }
-
-    public void testSynchronizationGlobal() throws Exception {
-        SecurityContextHolder.clearContext();
-        SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_GLOBAL);
-        loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, true, false);
-        assertEquals("Thread errors detected; review log output for details", 0, errors);
-    }
-
-    public void testSynchronizationInheritableThreadLocal()
-        throws Exception {
-        SecurityContextHolder.clearContext();
-        SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
-        loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, false, true);
-        assertEquals("Thread errors detected; review log output for details", 0, errors);
-    }
-
-    public void testSynchronizationThreadLocal() throws Exception {
-        SecurityContextHolder.clearContext();
-        SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_THREADLOCAL);
-        loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, false, false);
-        assertEquals("Thread errors detected; review log output for details", 0, errors);
-    }
-
-    private void startAndRun(Thread[] threads) {
-        // Start them up
-        for (int i = 0; i < threads.length; i++) {
-            threads[i].start();
-        }
-
-        // Wait for them to finish
-        while (stillRunning(threads)) {
-            try {
-                Thread.sleep(250);
-            } catch (InterruptedException ignore) {}
-        }
-    }
-
-    private boolean stillRunning(Thread[] threads) {
-        for (int i = 0; i < threads.length; i++) {
-            if (threads[i].isAlive()) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    private void loadStartAndWaitForThreads(boolean topLevelThread, String prefix, int createThreads,
-            boolean expectAllThreadsToUseIdenticalAuthentication, boolean expectChildrenToShareAuthenticationWithParent) {
-        Thread[] threads = new Thread[createThreads];
-        errors = 0;
-
-        if (topLevelThread) {
-            // PARENT (TOP-LEVEL) THREAD CREATION
-            if (expectChildrenToShareAuthenticationWithParent) {
-                // An InheritableThreadLocal
-                for (int i = 0; i < threads.length; i++) {
-                    if ((i % 2) == 0) {
-                        // Don't inject auth into current thread; neither current thread or child will have authentication
-                        threads[i] = makeThread(prefix + "Unauth_Parent_" + i, true, false, false, true, null);
-                    } else {
-                        // Inject auth into current thread, but not child; current thread will have auth, child will also have auth
-                        threads[i] = makeThread(prefix + "Auth_Parent_" + i, true, true, false, true,
-                                prefix + "Auth_Parent_" + i);
-                    }
-                }
-            } else if (expectAllThreadsToUseIdenticalAuthentication) {
-                // A global
-                SecurityContextHolder.getContext()
-                                     .setAuthentication(new UsernamePasswordAuthenticationToken("GLOBAL_USERNAME",
-                        "pass"));
-
-                for (int i = 0; i < threads.length; i++) {
-                    if ((i % 2) == 0) {
-                        // Don't inject auth into current thread;both current thread and child will have same authentication
-                        threads[i] = makeThread(prefix + "Unauth_Parent_" + i, true, false, true, true,
-                                "GLOBAL_USERNAME");
-                    } else {
-                        // Inject auth into current thread; current thread will have auth, child will also have auth
-                        threads[i] = makeThread(prefix + "Auth_Parent_" + i, true, true, true, true, "GLOBAL_USERNAME");
-                    }
-                }
-            } else {
-                // A standard ThreadLocal
-                for (int i = 0; i < threads.length; i++) {
-                    if ((i % 2) == 0) {
-                        // Don't inject auth into current thread; neither current thread or child will have authentication
-                        threads[i] = makeThread(prefix + "Unauth_Parent_" + i, true, false, false, false, null);
-                    } else {
-                        // Inject auth into current thread, but not child; current thread will have auth, child will not have auth
-                        threads[i] = makeThread(prefix + "Auth_Parent_" + i, true, true, false, false,
-                                prefix + "Auth_Parent_" + i);
-                    }
-                }
-            }
-        } else {
-            // CHILD THREAD CREATION
-            if (expectChildrenToShareAuthenticationWithParent || expectAllThreadsToUseIdenticalAuthentication) {
-                // The children being created are all expected to have security (ie an InheritableThreadLocal/global AND auth was injected into parent)
-                for (int i = 0; i < threads.length; i++) {
-                    String expectedUsername = prefix;
-
-                    if (expectAllThreadsToUseIdenticalAuthentication) {
-                        expectedUsername = "GLOBAL_USERNAME";
-                    }
-
-                    // Don't inject auth into current thread; the current thread will obtain auth from its parent
-                    // NB: As topLevelThread = true, no further child threads will be created
-                    threads[i] = makeThread(prefix + "->child->Inherited_Auth_Child_" + i, false, false,
-                            expectAllThreadsToUseIdenticalAuthentication, false, expectedUsername);
-                }
-            } else {
-                // The children being created are NOT expected to have security (ie not an InheritableThreadLocal OR auth was not injected into parent)
-                for (int i = 0; i < threads.length; i++) {
-                    // Don't inject auth into current thread; neither current thread or child will have authentication
-                    // NB: As topLevelThread = true, no further child threads will be created
-                    threads[i] = makeThread(prefix + "->child->Unauth_Child_" + i, false, false, false, false, null);
-                }
-            }
-        }
-
-        // Start and execute the threads
-        startAndRun(threads);
-    }
-
-    private Thread makeThread(final String threadIdentifier, final boolean topLevelThread,
-        final boolean injectAuthIntoCurrentThread, final boolean expectAllThreadsToUseIdenticalAuthentication,
-        final boolean expectChildrenToShareAuthenticationWithParent, final String expectedUsername) {
-        final Random rnd = new Random();
-
-        Thread t = new Thread(new Runnable() {
-               public void run() {
-                    if (injectAuthIntoCurrentThread) {
-                        // Set authentication in this thread
-                        SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(
-                                expectedUsername, "pass"));
-
-                        //System.out.println(threadIdentifier + " - set to " + SecurityContextHolder.getContext().getAuthentication());
-                    } else {
-                        //System.out.println(threadIdentifier + " - not set (currently " + SecurityContextHolder.getContext().getAuthentication() + ")");
-                    }
-
-                    // Do some operations in current thread, checking authentication is as expected in the current thread (ie another thread doesn't change it)
-                    for (int i = 0; i < NUM_OPS; i++) {
-                        String currentUsername = (SecurityContextHolder.getContext().getAuthentication() == null)
-                            ? null : SecurityContextHolder.getContext().getAuthentication().getName();
-
-                        if ((i % 7) == 0) {
-                            System.out.println(threadIdentifier + " at " + i + " username " + currentUsername);
-                        }
-
-                        try {
-                            assertEquals("Failed on iteration " + i + "; Authentication was '"
-                                + currentUsername + "' but principal was expected to contain username '"
-                                + expectedUsername + "'", expectedUsername, currentUsername);
-                        } catch (ComparisonFailure err) {
-                            errors++;
-                            throw err;
-                        }
-
-                        try {
-                            Thread.sleep(rnd.nextInt(250));
-                        } catch (InterruptedException ignore) {}
-                    }
-
-                    // Load some children threads, checking the authentication is as expected in the children (ie another thread doesn't change it)
-                    if (topLevelThread) {
-                        // Make four children, but we don't want the children to have any more children (so anti-nature, huh?)
-                        if (injectAuthIntoCurrentThread && expectChildrenToShareAuthenticationWithParent) {
-                            loadStartAndWaitForThreads(false, threadIdentifier, 4,
-                                expectAllThreadsToUseIdenticalAuthentication, true);
-                        } else {
-                            loadStartAndWaitForThreads(false, threadIdentifier, 4,
-                                expectAllThreadsToUseIdenticalAuthentication, false);
-                        }
-                    }
-                }
-            }, threadIdentifier);
-
-        return t;
-    }
+	private int errors = 0;
+
+	private static final int NUM_OPS = 25;
+	private static final int NUM_THREADS = 25;
+
+	public final void setUp() throws Exception {
+		SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
+	}
+
+	public void testSynchronizationCustomStrategyLoading() {
+		SecurityContextHolder.setStrategyName(InheritableThreadLocalSecurityContextHolderStrategy.class.getName());
+		assertTrue(new SecurityContextHolder().toString()
+											.lastIndexOf("SecurityContextHolder[strategy='org.springframework.security.context.InheritableThreadLocalSecurityContextHolderStrategy'") != -1);
+		loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, false, true);
+		assertEquals("Thread errors detected; review log output for details", 0, errors);
+	}
+
+	public void testSynchronizationGlobal() throws Exception {
+		SecurityContextHolder.clearContext();
+		SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_GLOBAL);
+		loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, true, false);
+		assertEquals("Thread errors detected; review log output for details", 0, errors);
+	}
+
+	public void testSynchronizationInheritableThreadLocal()
+		throws Exception {
+		SecurityContextHolder.clearContext();
+		SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
+		loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, false, true);
+		assertEquals("Thread errors detected; review log output for details", 0, errors);
+	}
+
+	public void testSynchronizationThreadLocal() throws Exception {
+		SecurityContextHolder.clearContext();
+		SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_THREADLOCAL);
+		loadStartAndWaitForThreads(true, "Main_", NUM_THREADS, false, false);
+		assertEquals("Thread errors detected; review log output for details", 0, errors);
+	}
+
+	private void startAndRun(Thread[] threads) {
+		// Start them up
+		for (int i = 0; i < threads.length; i++) {
+			threads[i].start();
+		}
+
+		// Wait for them to finish
+		while (stillRunning(threads)) {
+			try {
+				Thread.sleep(250);
+			} catch (InterruptedException ignore) {}
+		}
+	}
+
+	private boolean stillRunning(Thread[] threads) {
+		for (int i = 0; i < threads.length; i++) {
+			if (threads[i].isAlive()) {
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+	private void loadStartAndWaitForThreads(boolean topLevelThread, String prefix, int createThreads,
+			boolean expectAllThreadsToUseIdenticalAuthentication, boolean expectChildrenToShareAuthenticationWithParent) {
+		Thread[] threads = new Thread[createThreads];
+		errors = 0;
+
+		if (topLevelThread) {
+			// PARENT (TOP-LEVEL) THREAD CREATION
+			if (expectChildrenToShareAuthenticationWithParent) {
+				// An InheritableThreadLocal
+				for (int i = 0; i < threads.length; i++) {
+					if ((i % 2) == 0) {
+						// Don't inject auth into current thread; neither current thread or child will have authentication
+						threads[i] = makeThread(prefix + "Unauth_Parent_" + i, true, false, false, true, null);
+					} else {
+						// Inject auth into current thread, but not child; current thread will have auth, child will also have auth
+						threads[i] = makeThread(prefix + "Auth_Parent_" + i, true, true, false, true,
+								prefix + "Auth_Parent_" + i);
+					}
+				}
+			} else if (expectAllThreadsToUseIdenticalAuthentication) {
+				// A global
+				SecurityContextHolder.getContext()
+									.setAuthentication(new UsernamePasswordAuthenticationToken("GLOBAL_USERNAME",
+						"pass"));
+
+				for (int i = 0; i < threads.length; i++) {
+					if ((i % 2) == 0) {
+						// Don't inject auth into current thread;both current thread and child will have same authentication
+						threads[i] = makeThread(prefix + "Unauth_Parent_" + i, true, false, true, true,
+								"GLOBAL_USERNAME");
+					} else {
+						// Inject auth into current thread; current thread will have auth, child will also have auth
+						threads[i] = makeThread(prefix + "Auth_Parent_" + i, true, true, true, true, "GLOBAL_USERNAME");
+					}
+				}
+			} else {
+				// A standard ThreadLocal
+				for (int i = 0; i < threads.length; i++) {
+					if ((i % 2) == 0) {
+						// Don't inject auth into current thread; neither current thread or child will have authentication
+						threads[i] = makeThread(prefix + "Unauth_Parent_" + i, true, false, false, false, null);
+					} else {
+						// Inject auth into current thread, but not child; current thread will have auth, child will not have auth
+						threads[i] = makeThread(prefix + "Auth_Parent_" + i, true, true, false, false,
+								prefix + "Auth_Parent_" + i);
+					}
+				}
+			}
+		} else {
+			// CHILD THREAD CREATION
+			if (expectChildrenToShareAuthenticationWithParent || expectAllThreadsToUseIdenticalAuthentication) {
+				// The children being created are all expected to have security (ie an InheritableThreadLocal/global AND auth was injected into parent)
+				for (int i = 0; i < threads.length; i++) {
+					String expectedUsername = prefix;
+
+					if (expectAllThreadsToUseIdenticalAuthentication) {
+						expectedUsername = "GLOBAL_USERNAME";
+					}
+
+					// Don't inject auth into current thread; the current thread will obtain auth from its parent
+					// NB: As topLevelThread = true, no further child threads will be created
+					threads[i] = makeThread(prefix + "->child->Inherited_Auth_Child_" + i, false, false,
+							expectAllThreadsToUseIdenticalAuthentication, false, expectedUsername);
+				}
+			} else {
+				// The children being created are NOT expected to have security (ie not an InheritableThreadLocal OR auth was not injected into parent)
+				for (int i = 0; i < threads.length; i++) {
+					// Don't inject auth into current thread; neither current thread or child will have authentication
+					// NB: As topLevelThread = true, no further child threads will be created
+					threads[i] = makeThread(prefix + "->child->Unauth_Child_" + i, false, false, false, false, null);
+				}
+			}
+		}
+
+		// Start and execute the threads
+		startAndRun(threads);
+	}
+
+	private Thread makeThread(final String threadIdentifier, final boolean topLevelThread,
+		final boolean injectAuthIntoCurrentThread, final boolean expectAllThreadsToUseIdenticalAuthentication,
+		final boolean expectChildrenToShareAuthenticationWithParent, final String expectedUsername) {
+		final Random rnd = new Random();
+
+		Thread t = new Thread(new Runnable() {
+			public void run() {
+					if (injectAuthIntoCurrentThread) {
+						// Set authentication in this thread
+						SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(
+								expectedUsername, "pass"));
+
+						//System.out.println(threadIdentifier + " - set to " + SecurityContextHolder.getContext().getAuthentication());
+					} else {
+						//System.out.println(threadIdentifier + " - not set (currently " + SecurityContextHolder.getContext().getAuthentication() + ")");
+					}
+
+					// Do some operations in current thread, checking authentication is as expected in the current thread (ie another thread doesn't change it)
+					for (int i = 0; i < NUM_OPS; i++) {
+						String currentUsername = (SecurityContextHolder.getContext().getAuthentication() == null)
+							? null : SecurityContextHolder.getContext().getAuthentication().getName();
+
+						if ((i % 7) == 0) {
+							System.out.println(threadIdentifier + " at " + i + " username " + currentUsername);
+						}
+
+						try {
+							assertEquals("Failed on iteration " + i + "; Authentication was '"
+								+ currentUsername + "' but principal was expected to contain username '"
+								+ expectedUsername + "'", expectedUsername, currentUsername);
+						} catch (ComparisonFailure err) {
+							errors++;
+							throw err;
+						}
+
+						try {
+							Thread.sleep(rnd.nextInt(250));
+						} catch (InterruptedException ignore) {}
+					}
+
+					// Load some children threads, checking the authentication is as expected in the children (ie another thread doesn't change it)
+					if (topLevelThread) {
+						// Make four children, but we don't want the children to have any more children (so anti-nature, huh?)
+						if (injectAuthIntoCurrentThread && expectChildrenToShareAuthenticationWithParent) {
+							loadStartAndWaitForThreads(false, threadIdentifier, 4,
+								expectAllThreadsToUseIdenticalAuthentication, true);
+						} else {
+							loadStartAndWaitForThreads(false, threadIdentifier, 4,
+								expectAllThreadsToUseIdenticalAuthentication, false);
+						}
+					}
+				}
+			}, threadIdentifier);
+
+		return t;
+	}
 }

+ 4 - 4
itest/web/src/integration-test/resources/logback-test.xml

@@ -1,15 +1,15 @@
 <configuration>
   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
+	<encoder>
+	  <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+	</encoder>
   </appender>
 
   <logger name="org.springframework.security" level="${sec.log.level}:-WARN"/>
   <logger name="org.apache.directory" level="ERROR"/>
 
   <root level="${root.level}:-WARN">
-    <appender-ref ref="STDOUT" />
+	<appender-ref ref="STDOUT" />
   </root>
 
 </configuration>

+ 8 - 8
itest/web/src/main/webapp/WEB-INF/http-security-basic.xml

@@ -1,14 +1,14 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <beans:beans xmlns="http://www.springframework.org/schema/security"
-    xmlns:beans="http://www.springframework.org/schema/beans"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
-                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
+	xmlns:beans="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+						http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
 
-    <http use-expressions="false">
-        <intercept-url pattern="/**" access="ROLE_DEVELOPER,ROLE_USER" />
-        <http-basic />
-    </http>
+	<http use-expressions="false">
+		<intercept-url pattern="/**" access="ROLE_DEVELOPER,ROLE_USER" />
+		<http-basic />
+	</http>
 
 </beans:beans>

+ 22 - 22
itest/web/src/main/webapp/WEB-INF/http-security-concurrency.xml

@@ -1,34 +1,34 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <beans:beans xmlns="http://www.springframework.org/schema/security"
-    xmlns:beans="http://www.springframework.org/schema/beans"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
-                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
+	xmlns:beans="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+						http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
 
-    <debug />
+	<debug />
 
-    <!--
-       Http App Context to test form login, remember-me and concurrent session control.
-       Needs to be supplemented with authentication provider(s)
-    -->
-    <http pattern="/login.jsp" security="none" />
+	<!--
+	   Http App Context to test form login, remember-me and concurrent session control.
+	   Needs to be supplemented with authentication provider(s)
+	-->
+	<http pattern="/login.jsp" security="none" />
 
-    <http>
-        <intercept-url pattern="/secure/**" access="hasAnyRole('ROLE_DEVELOPER','ROLE_USER')" />
-        <intercept-url pattern="/**" access="hasAnyRole('ROLE_DEVELOPER','ROLE_USER')" />
+	<http>
+		<intercept-url pattern="/secure/**" access="hasAnyRole('ROLE_DEVELOPER','ROLE_USER')" />
+		<intercept-url pattern="/**" access="hasAnyRole('ROLE_DEVELOPER','ROLE_USER')" />
 
-        <form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error=true"/>
-        <http-basic/>
+		<form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error=true"/>
+		<http-basic/>
 
-        <!-- Default logout configuration -->
-        <logout logout-url="/logout"/>
+		<!-- Default logout configuration -->
+		<logout logout-url="/logout"/>
 
-        <session-management>
-            <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
-        </session-management>
+		<session-management>
+			<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
+		</session-management>
 
-        <csrf disabled="true"/>
-    </http>
+		<csrf disabled="true"/>
+	</http>
 
 </beans:beans>

+ 51 - 51
itest/web/src/main/webapp/WEB-INF/http-security-custom-concurrency.xml

@@ -1,56 +1,56 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <beans:beans xmlns="http://www.springframework.org/schema/security"
-    xmlns:beans="http://www.springframework.org/schema/beans"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
-                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
-
-    <http pattern="/login.jsp" security="none" />
-
-    <http entry-point-ref="aep" use-expressions="false">
-        <intercept-url pattern="/**" access="ROLE_DEVELOPER,ROLE_USER" />
-
-        <session-management session-authentication-strategy-ref="sas"/>
-        <logout />
-
-        <custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
-        <custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter" />
-
-        <csrf disabled="true"/>
-    </http>
-
-    <beans:bean id="aep" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
-        <beans:constructor-arg value="/login.jsp" />
-    </beans:bean>
-
-    <beans:bean id="myAuthFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
-        <beans:property name="sessionAuthenticationStrategy" ref="sas" />
-        <beans:property name="authenticationManager" ref="authenticationManager" />
-    </beans:bean>
-
-    <beans:bean id="concurrencyFilter" class="org.springframework.security.web.session.ConcurrentSessionFilter">
-        <beans:constructor-arg ref="sessionRegistry" />
-        <beans:constructor-arg value="/session-expired.htm" />
-    </beans:bean>
-
-    <beans:bean id="sas" class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy">
-        <beans:constructor-arg>
-            <beans:list>
-                <beans:bean class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">
-                    <beans:constructor-arg ref="sessionRegistry"/>
-                    <beans:property name="maximumSessions" value="1" />
-                    <beans:property name="exceptionIfMaximumExceeded" value="true" />
-                </beans:bean>
-                <beans:bean class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy">
-                </beans:bean>
-                <beans:bean class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy">
-                    <beans:constructor-arg ref="sessionRegistry"/>
-                </beans:bean>
-            </beans:list>
-        </beans:constructor-arg>
-    </beans:bean>
-
-    <beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
+	xmlns:beans="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+						http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
+
+	<http pattern="/login.jsp" security="none" />
+
+	<http entry-point-ref="aep" use-expressions="false">
+		<intercept-url pattern="/**" access="ROLE_DEVELOPER,ROLE_USER" />
+
+		<session-management session-authentication-strategy-ref="sas"/>
+		<logout />
+
+		<custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
+		<custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter" />
+
+		<csrf disabled="true"/>
+	</http>
+
+	<beans:bean id="aep" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
+		<beans:constructor-arg value="/login.jsp" />
+	</beans:bean>
+
+	<beans:bean id="myAuthFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
+		<beans:property name="sessionAuthenticationStrategy" ref="sas" />
+		<beans:property name="authenticationManager" ref="authenticationManager" />
+	</beans:bean>
+
+	<beans:bean id="concurrencyFilter" class="org.springframework.security.web.session.ConcurrentSessionFilter">
+		<beans:constructor-arg ref="sessionRegistry" />
+		<beans:constructor-arg value="/session-expired.htm" />
+	</beans:bean>
+
+	<beans:bean id="sas" class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy">
+		<beans:constructor-arg>
+			<beans:list>
+				<beans:bean class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">
+					<beans:constructor-arg ref="sessionRegistry"/>
+					<beans:property name="maximumSessions" value="1" />
+					<beans:property name="exceptionIfMaximumExceeded" value="true" />
+				</beans:bean>
+				<beans:bean class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy">
+				</beans:bean>
+				<beans:bean class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy">
+					<beans:constructor-arg ref="sessionRegistry"/>
+				</beans:bean>
+			</beans:list>
+		</beans:constructor-arg>
+	</beans:bean>
+
+	<beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
 
 </beans:beans>

+ 15 - 15
itest/web/src/main/webapp/WEB-INF/in-memory-provider.xml

@@ -1,21 +1,21 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <beans:beans xmlns="http://www.springframework.org/schema/security"
-    xmlns:beans="http://www.springframework.org/schema/beans"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
-                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
+	xmlns:beans="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+						http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
 
-    <authentication-manager alias="authenticationManager">
-        <authentication-provider>
-            <user-service>
-              <user name="miles" password="milespassword" authorities="ROLE_USER,ROLE_JAZZ,ROLE_TRUMPETER"/>
-              <user name="johnc" password="johncspassword" authorities="ROLE_USER,ROLE_JAZZ,ROLE_SAXOPHONIST"/>
-              <user name="jimi" password="jimispassword" authorities="ROLE_USER,ROLE_ROCK,ROLE_GUITARIST"/>
-              <user name="bessie" password="bessiespassword" authorities="ROLE_USER,ROLE_JAZZ,ROLE_SINGER"/>
-              <user name="theescapist&lt;&gt;&amp;." password="theescapistspassword" authorities="ROLE_USER"/>
-            </user-service>
-        </authentication-provider>
-    </authentication-manager>
+	<authentication-manager alias="authenticationManager">
+		<authentication-provider>
+			<user-service>
+			  <user name="miles" password="milespassword" authorities="ROLE_USER,ROLE_JAZZ,ROLE_TRUMPETER"/>
+			  <user name="johnc" password="johncspassword" authorities="ROLE_USER,ROLE_JAZZ,ROLE_SAXOPHONIST"/>
+			  <user name="jimi" password="jimispassword" authorities="ROLE_USER,ROLE_ROCK,ROLE_GUITARIST"/>
+			  <user name="bessie" password="bessiespassword" authorities="ROLE_USER,ROLE_JAZZ,ROLE_SINGER"/>
+			  <user name="theescapist&lt;&gt;&amp;." password="theescapistspassword" authorities="ROLE_USER"/>
+			</user-service>
+		</authentication-provider>
+	</authentication-manager>
 
 </beans:beans>

+ 37 - 37
samples/aspectj-xml/src/main/resources/aspectj-context.xml

@@ -1,48 +1,48 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xmlns:sec="http://www.springframework.org/schema/security"
-    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
-                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:sec="http://www.springframework.org/schema/security"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+						http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
 
-    <sec:global-method-security secured-annotations="enabled" mode="aspectj" />
+	<sec:global-method-security secured-annotations="enabled" mode="aspectj" />
 <!--
-    <bean id="aspectJSecurityInterceptor"
-        class="org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor">
-        <property name="authenticationManager" ref="authenticationManager" />
-        <property name="accessDecisionManager" ref="accessDecisionManager" />
-        <property name="securityMetadataSource">
-            <bean
-                class="org.springframework.security.access.annotation.SecuredAnnotationSecurityMetadataSource" />
-        </property>
-    </bean>
+	<bean id="aspectJSecurityInterceptor"
+		class="org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor">
+		<property name="authenticationManager" ref="authenticationManager" />
+		<property name="accessDecisionManager" ref="accessDecisionManager" />
+		<property name="securityMetadataSource">
+			<bean
+				class="org.springframework.security.access.annotation.SecuredAnnotationSecurityMetadataSource" />
+		</property>
+	</bean>
 
-    <bean id="authenticationManager"
-        class="org.springframework.security.authentication.ProviderManager">
-        <property name="providers">
-            <bean
-                class="org.springframework.security.authentication.TestingAuthenticationProvider" />
-        </property>
-    </bean>
+	<bean id="authenticationManager"
+		class="org.springframework.security.authentication.ProviderManager">
+		<property name="providers">
+			<bean
+				class="org.springframework.security.authentication.TestingAuthenticationProvider" />
+		</property>
+	</bean>
 
-    <bean id="accessDecisionManager"
-        class="org.springframework.security.access.vote.AffirmativeBased">
-        <property name="decisionVoters">
-            <list>
-                <bean
-                    class="org.springframework.security.access.vote.RoleVoter" />
-            </list>
-        </property>
-    </bean>
+	<bean id="accessDecisionManager"
+		class="org.springframework.security.access.vote.AffirmativeBased">
+		<property name="decisionVoters">
+			<list>
+				<bean
+					class="org.springframework.security.access.vote.RoleVoter" />
+			</list>
+		</property>
+	</bean>
 
-    <bean
-        class="org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect"
-        factory-method="aspectOf">
-        <property name="securityInterceptor" ref="aspectJSecurityInterceptor" />
-    </bean>
+	<bean
+		class="org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect"
+		factory-method="aspectOf">
+		<property name="securityInterceptor" ref="aspectJSecurityInterceptor" />
+	</bean>
  -->
-    <bean class="sample.aspectj.Service" />
+	<bean class="sample.aspectj.Service" />
 
-    <bean class="sample.aspectj.SecuredService" />
+	<bean class="sample.aspectj.SecuredService" />
 
 </beans>

+ 4 - 4
samples/aspectj-xml/src/test/resources/logback-test.xml

@@ -1,14 +1,14 @@
 <configuration>
   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
+	<encoder>
+	  <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+	</encoder>
   </appender>
 
   <logger name="org.springframework.security" level="${sec.log.level}:-WARN"/>
 
   <root level="${root.level}:-WARN">
-    <appender-ref ref="STDOUT" />
+	<appender-ref ref="STDOUT" />
   </root>
 
 </configuration>

+ 77 - 77
samples/cas/sample-xml/src/integration-test/groovy/org/springframework/security/samples/cas/CasSampleProxyTests.groovy

@@ -33,90 +33,90 @@ import spock.lang.*
  */
 @Stepwise
 class CasSampleProxyTests extends AbstractCasTests {
-    HttpClient client = new HttpClient()
-    @Shared String casServerUrl = LoginPage.url.replaceFirst('/login','')
-    @Shared JettyCasService service = new JettyCasService().init(casServerUrl)
-    @Shared Cas20ProxyRetriever retriever = new Cas20ProxyRetriever(casServerUrl,'UTF-8')
-    @Shared String pt
+	HttpClient client = new HttpClient()
+	@Shared String casServerUrl = LoginPage.url.replaceFirst('/login','')
+	@Shared JettyCasService service = new JettyCasService().init(casServerUrl)
+	@Shared Cas20ProxyRetriever retriever = new Cas20ProxyRetriever(casServerUrl,'UTF-8')
+	@Shared String pt
 
-    def cleanupSpec() {
-        service.stop()
-    }
+	def cleanupSpec() {
+		service.stop()
+	}
 
-    def 'access secure page succeeds with ROLE_USER'() {
-        setup: 'Obtain a pgt for a user with ROLE_USER'
-        driver.get LoginPage.url+"?service="+service.serviceUrl()
-        at LoginPage
-        login 'scott'
-        when: 'User with ROLE_USER accesses the secure page'
-        def content = getSecured(getBaseUrl()+SecurePage.url).responseBodyAsString
-        then: 'The secure page is returned'
-        content.contains('<h1>Secure Page</h1>')
-    }
+	def 'access secure page succeeds with ROLE_USER'() {
+		setup: 'Obtain a pgt for a user with ROLE_USER'
+		driver.get LoginPage.url+"?service="+service.serviceUrl()
+		at LoginPage
+		login 'scott'
+		when: 'User with ROLE_USER accesses the secure page'
+		def content = getSecured(getBaseUrl()+SecurePage.url).responseBodyAsString
+		then: 'The secure page is returned'
+		content.contains('<h1>Secure Page</h1>')
+	}
 
-    def 'access proxy ticket sample succeeds with ROLE_USER'() {
-        when: 'a proxy ticket is used to create another proxy ticket'
-        def content = getSecured(getBaseUrl()+ProxyTicketSamplePage.url).responseBodyAsString
-        then: 'The proxy ticket sample page is returned'
-        content.contains('<h1>Secure Page using a Proxy Ticket</h1>')
-    }
+	def 'access proxy ticket sample succeeds with ROLE_USER'() {
+		when: 'a proxy ticket is used to create another proxy ticket'
+		def content = getSecured(getBaseUrl()+ProxyTicketSamplePage.url).responseBodyAsString
+		then: 'The proxy ticket sample page is returned'
+		content.contains('<h1>Secure Page using a Proxy Ticket</h1>')
+	}
 
-    def 'access extremely secure page with ROLE_USER is denied'() {
-        when: 'User with ROLE_USER accesses the extremely secure page'
-        GetMethod method = getSecured(getBaseUrl()+ExtremelySecurePage.url)
-        then: 'access is denied'
-        assert method.responseBodyAsString =~ /(?i)403.*?Denied/
-        assert 403 == method.statusCode
-    }
+	def 'access extremely secure page with ROLE_USER is denied'() {
+		when: 'User with ROLE_USER accesses the extremely secure page'
+		GetMethod method = getSecured(getBaseUrl()+ExtremelySecurePage.url)
+		then: 'access is denied'
+		assert method.responseBodyAsString =~ /(?i)403.*?Denied/
+		assert 403 == method.statusCode
+	}
 
-    def 'access secure page with ROLE_SUPERVISOR succeeds'() {
-        setup: 'Obtain pgt for user with ROLE_SUPERVISOR'
-        to LocalLogoutPage
-        casServerLogout.click()
-        driver.get(LoginPage.url+"?service="+service.serviceUrl())
-        at LoginPage
-        login 'rod'
-        when: 'User with ROLE_SUPERVISOR accesses the secure page'
-        def content = getSecured(getBaseUrl()+ExtremelySecurePage.url).responseBodyAsString
-        then: 'The secure page is returned'
-        content.contains('<h1>VERY Secure Page</h1>')
-    }
+	def 'access secure page with ROLE_SUPERVISOR succeeds'() {
+		setup: 'Obtain pgt for user with ROLE_SUPERVISOR'
+		to LocalLogoutPage
+		casServerLogout.click()
+		driver.get(LoginPage.url+"?service="+service.serviceUrl())
+		at LoginPage
+		login 'rod'
+		when: 'User with ROLE_SUPERVISOR accesses the secure page'
+		def content = getSecured(getBaseUrl()+ExtremelySecurePage.url).responseBodyAsString
+		then: 'The secure page is returned'
+		content.contains('<h1>VERY Secure Page</h1>')
+	}
 
-    def 'access extremely secure page with ROLE_SUPERVISOR reusing pt succeeds (stateless mode works)'() {
-        when: 'User with ROLE_SUPERVISOR accesses extremely secure page with used pt'
-        def content = getSecured(getBaseUrl()+ExtremelySecurePage.url,pt).responseBodyAsString
-        then: 'The extremely secure page is returned'
-        content.contains('<h1>VERY Secure Page</h1>')
-    }
+	def 'access extremely secure page with ROLE_SUPERVISOR reusing pt succeeds (stateless mode works)'() {
+		when: 'User with ROLE_SUPERVISOR accesses extremely secure page with used pt'
+		def content = getSecured(getBaseUrl()+ExtremelySecurePage.url,pt).responseBodyAsString
+		then: 'The extremely secure page is returned'
+		content.contains('<h1>VERY Secure Page</h1>')
+	}
 
-    def 'access secure page with invalid proxy ticket fails'() {
-        when: 'Invalid ticket is used to access secure page'
-        GetMethod method = getSecured(getBaseUrl()+SecurePage.url,'invalidticket')
-        then: 'Authentication fails'
-        method.statusCode == 401
-    }
+	def 'access secure page with invalid proxy ticket fails'() {
+		when: 'Invalid ticket is used to access secure page'
+		GetMethod method = getSecured(getBaseUrl()+SecurePage.url,'invalidticket')
+		then: 'Authentication fails'
+		method.statusCode == 401
+	}
 
-    /**
-     * Gets the result of calling a url with a proxy ticket
-     * @param targetUrl the absolute url to attempt to access
-     * @param pt the proxy ticket to use. Defaults to {@link #getPt(String)} with targetUrl specified for the targetUrl.
-     * @return the GetMethod after calling a url with a specified proxy ticket
-     */
-    GetMethod getSecured(String targetUrl,String pt=getPt(targetUrl)) {
-        assert pt != null
-        GetMethod method = new GetMethod(targetUrl+"?ticket="+pt)
-        int status = client.executeMethod(method)
-        method
-    }
+	/**
+	 * Gets the result of calling a url with a proxy ticket
+	 * @param targetUrl the absolute url to attempt to access
+	 * @param pt the proxy ticket to use. Defaults to {@link #getPt(String)} with targetUrl specified for the targetUrl.
+	 * @return the GetMethod after calling a url with a specified proxy ticket
+	 */
+	GetMethod getSecured(String targetUrl,String pt=getPt(targetUrl)) {
+		assert pt != null
+		GetMethod method = new GetMethod(targetUrl+"?ticket="+pt)
+		int status = client.executeMethod(method)
+		method
+	}
 
-    /**
-     * Obtains a proxy ticket using the pgt from the {@link #service}.
-     * @param targetService the targetService that the proxy ticket will be valid for
-     * @return a proxy ticket for targetService
-     */
-    String getPt(String targetService) {
-        assert service.pgt != null
-        pt = retriever.getProxyTicketIdFor(service.pgt, targetService)
-        pt
-    }
+	/**
+	 * Obtains a proxy ticket using the pgt from the {@link #service}.
+	 * @param targetService the targetService that the proxy ticket will be valid for
+	 * @return a proxy ticket for targetService
+	 */
+	String getPt(String targetService) {
+		assert service.pgt != null
+		pt = retriever.getProxyTicketIdFor(service.pgt, targetService)
+		pt
+	}
 }

+ 98 - 98
samples/cas/sample-xml/src/integration-test/groovy/org/springframework/security/samples/cas/CasSampleTests.groovy

@@ -34,102 +34,102 @@ import spock.lang.Stepwise;
  */
 @Stepwise
 class CasSampleTests extends AbstractCasTests {
-    @Shared String casServerLogoutUrl = LoginPage.url.replaceFirst('/login','/logout')
-
-    def 'access home page with unauthenticated user succeeds'() {
-        when: 'Unauthenticated user accesses the Home Page'
-        to HomePage
-        then: 'The home page succeeds'
-        at HomePage
-    }
-
-    def 'access extremely secure page with unauthenitcated user requires login'() {
-        when: 'Unauthenticated user accesses the extremely secure page'
-        via ExtremelySecurePage
-        then: 'The login page is displayed'
-        at LoginPage
-    }
-
-    def 'authenticate attempt with invaid ticket fails'() {
-        when: 'present invalid ticket'
-        go "login/cas?ticket=invalid"
-        then: 'the login failed page is displayed'
-        $("h2").text() == 'Login to CAS failed!'
-    }
-
-    def 'access secure page with unauthenticated user requires login'() {
-        when: 'Unauthenticated user accesses the secure page'
-        via SecurePage
-        then: 'The login page is displayed'
-        at LoginPage
-    }
-
-    def 'saved request is used for secure page'() {
-        when: 'login with ROLE_USER after requesting the secure page'
-        login 'scott'
-        then: 'the secure page is displayed'
-        at SecurePage
-    }
-
-    def 'access proxy ticket sample with ROLE_USER is allowed'() {
-        when: 'user with ROLE_USER requests the proxy ticket sample page'
-        to ProxyTicketSamplePage
-        then: 'the proxy ticket sample page is displayed'
-        at ProxyTicketSamplePage
-    }
-
-    def 'access extremely secure page with ROLE_USER is denied'() {
-        when: 'User with ROLE_USER accesses extremely secure page'
-        via ExtremelySecurePage
-        then: 'the access denied page is displayed'
-        at AccessDeniedPage
-    }
-
-    def 'clicking local logout link displays local logout page'() {
-        setup: 'Navigate to page with logout link'
-        to SecurePage
-        when: 'Local logout link is clicked'
-        navModule.logout.click()
-        then: 'the local logout page is displayed'
-        at LocalLogoutPage
-    }
-
-    def 'clicking cas server logout link successfully performs logout'() {
-        when: 'the cas server logout link is clicked and the secure page is requested'
-        casServerLogout.click()
-        via SecurePage
-        then: 'the login page is displayed'
-        at LoginPage
-    }
-
-    def 'access extremely secure page with ROLE_SUPERVISOR succeeds'() {
-        setup: 'login with ROLE_SUPERVISOR'
-        login 'rod'
-        when: 'access extremely secure page'
-        to ExtremelySecurePage
-        then: 'extremely secure page is displayed'
-        at ExtremelySecurePage
-    }
-
-    def 'after logout extremely secure page requires login'() {
-        when: 'logout and request extremely secure page'
-        navModule.logout.click()
-        casServerLogout.click()
-        via ExtremelySecurePage
-        then: 'login page is displayed'
-        at LoginPage
-    }
-
-    def 'logging out of the cas server successfully logs out of the cas sample application'() {
-        setup: 'login with ROLE_USER'
-        via SecurePage
-        at LoginPage
-        login 'rod'
-        at SecurePage
-        when: 'logout of the CAS Server'
-        go casServerLogoutUrl
-        via SecurePage
-        then: 'user is logged out of the CAS Service'
-        at LoginPage
-    }
+	@Shared String casServerLogoutUrl = LoginPage.url.replaceFirst('/login','/logout')
+
+	def 'access home page with unauthenticated user succeeds'() {
+		when: 'Unauthenticated user accesses the Home Page'
+		to HomePage
+		then: 'The home page succeeds'
+		at HomePage
+	}
+
+	def 'access extremely secure page with unauthenitcated user requires login'() {
+		when: 'Unauthenticated user accesses the extremely secure page'
+		via ExtremelySecurePage
+		then: 'The login page is displayed'
+		at LoginPage
+	}
+
+	def 'authenticate attempt with invaid ticket fails'() {
+		when: 'present invalid ticket'
+		go "login/cas?ticket=invalid"
+		then: 'the login failed page is displayed'
+		$("h2").text() == 'Login to CAS failed!'
+	}
+
+	def 'access secure page with unauthenticated user requires login'() {
+		when: 'Unauthenticated user accesses the secure page'
+		via SecurePage
+		then: 'The login page is displayed'
+		at LoginPage
+	}
+
+	def 'saved request is used for secure page'() {
+		when: 'login with ROLE_USER after requesting the secure page'
+		login 'scott'
+		then: 'the secure page is displayed'
+		at SecurePage
+	}
+
+	def 'access proxy ticket sample with ROLE_USER is allowed'() {
+		when: 'user with ROLE_USER requests the proxy ticket sample page'
+		to ProxyTicketSamplePage
+		then: 'the proxy ticket sample page is displayed'
+		at ProxyTicketSamplePage
+	}
+
+	def 'access extremely secure page with ROLE_USER is denied'() {
+		when: 'User with ROLE_USER accesses extremely secure page'
+		via ExtremelySecurePage
+		then: 'the access denied page is displayed'
+		at AccessDeniedPage
+	}
+
+	def 'clicking local logout link displays local logout page'() {
+		setup: 'Navigate to page with logout link'
+		to SecurePage
+		when: 'Local logout link is clicked'
+		navModule.logout.click()
+		then: 'the local logout page is displayed'
+		at LocalLogoutPage
+	}
+
+	def 'clicking cas server logout link successfully performs logout'() {
+		when: 'the cas server logout link is clicked and the secure page is requested'
+		casServerLogout.click()
+		via SecurePage
+		then: 'the login page is displayed'
+		at LoginPage
+	}
+
+	def 'access extremely secure page with ROLE_SUPERVISOR succeeds'() {
+		setup: 'login with ROLE_SUPERVISOR'
+		login 'rod'
+		when: 'access extremely secure page'
+		to ExtremelySecurePage
+		then: 'extremely secure page is displayed'
+		at ExtremelySecurePage
+	}
+
+	def 'after logout extremely secure page requires login'() {
+		when: 'logout and request extremely secure page'
+		navModule.logout.click()
+		casServerLogout.click()
+		via ExtremelySecurePage
+		then: 'login page is displayed'
+		at LoginPage
+	}
+
+	def 'logging out of the cas server successfully logs out of the cas sample application'() {
+		setup: 'login with ROLE_USER'
+		via SecurePage
+		at LoginPage
+		login 'rod'
+		at SecurePage
+		when: 'logout of the CAS Server'
+		go casServerLogoutUrl
+		via SecurePage
+		then: 'user is logged out of the CAS Service'
+		at LoginPage
+	}
 }

+ 77 - 77
samples/cas/sample-xml/src/integration-test/groovy/org/springframework/security/samples/cas/JettyCasService.groovy

@@ -38,87 +38,87 @@ import org.jasig.cas.client.validation.Cas20ProxyTicketValidator;
  * @author Rob Winch
  */
 class JettyCasService extends Server {
-    private Cas20ProxyTicketValidator validator
-    private int port = availablePort()
+	private Cas20ProxyTicketValidator validator
+	private int port = availablePort()
 
-    /**
-     * The Proxy Granting Ticket. To initialize pgt, authenticate to the CAS Server with the service parameter
-     * equal to {@link #serviceUrl()}.
-     */
-    String pgt
+	/**
+	 * The Proxy Granting Ticket. To initialize pgt, authenticate to the CAS Server with the service parameter
+	 * equal to {@link #serviceUrl()}.
+	 */
+	String pgt
 
-    /**
-     * Start the CAS Service which will be available at {@link #serviceUrl()}.
-     *
-     * @param casServerUrl
-     * @return
-     */
-    def init(String casServerUrl) {
-        ProxyGrantingTicketStorage storage = new ProxyGrantingTicketStorageImpl()
-        validator = new Cas20ProxyTicketValidator(casServerUrl)
-        validator.setAcceptAnyProxy(true)
-        validator.setProxyGrantingTicketStorage(storage)
-        validator.setProxyCallbackUrl(absoluteUrl('callback'))
+	/**
+	 * Start the CAS Service which will be available at {@link #serviceUrl()}.
+	 *
+	 * @param casServerUrl
+	 * @return
+	 */
+	def init(String casServerUrl) {
+		ProxyGrantingTicketStorage storage = new ProxyGrantingTicketStorageImpl()
+		validator = new Cas20ProxyTicketValidator(casServerUrl)
+		validator.setAcceptAnyProxy(true)
+		validator.setProxyGrantingTicketStorage(storage)
+		validator.setProxyCallbackUrl(absoluteUrl('callback'))
 
-        String password = System.getProperty('javax.net.ssl.trustStorePassword','password')
-        SslSelectChannelConnector ssl_connector = new SslSelectChannelConnector()
-        ssl_connector.setPort(port)
-        ssl_connector.setKeystore(getTrustStore())
-        ssl_connector.setPassword(password)
-        ssl_connector.setKeyPassword(password)
-        addConnector(ssl_connector)
-        setHandler(new AbstractHandler() {
-            public void handle(String target, Request baseRequest,
-                    HttpServletRequest request, HttpServletResponse response)
-            throws IOException, ServletException {
-                def st = request.getParameter('ticket')
-                if(st) {
-                    JettyCasService.this.validator.validate(st, JettyCasService.this.serviceUrl())
-                }
-                def pgt = request.getParameter('pgtId')
-                if(pgt) {
-                  JettyCasService.this.pgt = pgt
-                }
-                response.setStatus(HttpServletResponse.SC_OK);
-                baseRequest.setHandled(true);
-            }
-        })
-        start()
-        this
-    }
+		String password = System.getProperty('javax.net.ssl.trustStorePassword','password')
+		SslSelectChannelConnector ssl_connector = new SslSelectChannelConnector()
+		ssl_connector.setPort(port)
+		ssl_connector.setKeystore(getTrustStore())
+		ssl_connector.setPassword(password)
+		ssl_connector.setKeyPassword(password)
+		addConnector(ssl_connector)
+		setHandler(new AbstractHandler() {
+			public void handle(String target, Request baseRequest,
+					HttpServletRequest request, HttpServletResponse response)
+			throws IOException, ServletException {
+				def st = request.getParameter('ticket')
+				if(st) {
+					JettyCasService.this.validator.validate(st, JettyCasService.this.serviceUrl())
+				}
+				def pgt = request.getParameter('pgtId')
+				if(pgt) {
+				  JettyCasService.this.pgt = pgt
+				}
+				response.setStatus(HttpServletResponse.SC_OK);
+				baseRequest.setHandled(true);
+			}
+		})
+		start()
+		this
+	}
 
-    /**
-     * Returns the absolute URL that this CAS service is available at.
-     * @return
-     */
-    String serviceUrl() {
-        absoluteUrl('service')
-    }
+	/**
+	 * Returns the absolute URL that this CAS service is available at.
+	 * @return
+	 */
+	String serviceUrl() {
+		absoluteUrl('service')
+	}
 
-    /**
-     * Given a relative url, will provide an absolute url for this CAS Service.
-     * @param relativeUrl the relative url (i.e. service, callback, etc)
-     * @return
-     */
-    private String absoluteUrl(String relativeUrl) {
-        "https://localhost:${port}/${relativeUrl}"
-    }
+	/**
+	 * Given a relative url, will provide an absolute url for this CAS Service.
+	 * @param relativeUrl the relative url (i.e. service, callback, etc)
+	 * @return
+	 */
+	private String absoluteUrl(String relativeUrl) {
+		"https://localhost:${port}/${relativeUrl}"
+	}
 
-    private static String getTrustStore() {
-        String trustStoreLocation = System.getProperty('javax.net.ssl.trustStore')
-        if(trustStoreLocation == null || !new File(trustStoreLocation).isFile()) {
-            throw new  IllegalStateException('Could not find the trust store at path "'+trustStoreLocation+'". Specify the location using the javax.net.ssl.trustStore system property.')
-        }
-        trustStoreLocation
-    }
-    /**
-     * Obtains a random available port (i.e. one that is not in use)
-     * @return
-     */
-    private static int availablePort() {
-        ServerSocket server = new ServerSocket(0)
-        int port = server.localPort
-        server.close()
-        port
-    }
+	private static String getTrustStore() {
+		String trustStoreLocation = System.getProperty('javax.net.ssl.trustStore')
+		if(trustStoreLocation == null || !new File(trustStoreLocation).isFile()) {
+			throw new  IllegalStateException('Could not find the trust store at path "'+trustStoreLocation+'". Specify the location using the javax.net.ssl.trustStore system property.')
+		}
+		trustStoreLocation
+	}
+	/**
+	 * Obtains a random available port (i.e. one that is not in use)
+	 * @return
+	 */
+	private static int availablePort() {
+		ServerSocket server = new ServerSocket(0)
+		int port = server.localPort
+		server.close()
+		port
+	}
 }

+ 4 - 4
samples/cas/sample-xml/src/integration-test/groovy/org/springframework/security/samples/cas/modules/NavModule.groovy

@@ -24,8 +24,8 @@ import org.springframework.security.samples.cas.pages.*
  * @author Rob Winch
  */
 class NavModule extends Module {
-    static content = {
-        home(to: HomePage) { $("a", text: "Home") }
-        logout(to: LocalLogoutPage) { $("a", text: "Logout") }
-    }
+	static content = {
+		home(to: HomePage) { $("a", text: "Home") }
+		logout(to: LocalLogoutPage) { $("a", text: "Logout") }
+	}
 }

+ 1 - 1
samples/cas/sample-xml/src/integration-test/groovy/org/springframework/security/samples/cas/pages/AccessDeniedPage.groovy

@@ -23,5 +23,5 @@ import geb.*
  * @author Rob Winch
  */
 class AccessDeniedPage extends Page {
-    static at = { $("*",text: iContains(~/.*?403.*/)) }
+	static at = { $("*",text: iContains(~/.*?403.*/)) }
 }

+ 5 - 5
samples/cas/sample-xml/src/integration-test/groovy/org/springframework/security/samples/cas/pages/ExtremelySecurePage.groovy

@@ -24,9 +24,9 @@ import org.springframework.security.samples.cas.modules.*
  * @author Rob Winch
  */
 class ExtremelySecurePage extends Page {
-    static url = "secure/extreme/"
-    static at = { assert $('h1').text() == 'VERY Secure Page'; true; }
-    static content = {
-        navModule { module NavModule }
-    }
+	static url = "secure/extreme/"
+	static at = { assert $('h1').text() == 'VERY Secure Page'; true; }
+	static content = {
+		navModule { module NavModule }
+	}
 }

+ 6 - 6
samples/cas/sample-xml/src/integration-test/groovy/org/springframework/security/samples/cas/pages/HomePage.groovy

@@ -23,10 +23,10 @@ import geb.*
  * @author Rob Winch
  */
 class HomePage extends Page {
-    static at = { assert $('h1').text() == 'Home Page'; true}
-    static url = ''
-    static content = {
-        securePage { $('a',text: 'Secure page') }
-        extremelySecurePage { $('a',text: 'Extremely secure page') }
-    }
+	static at = { assert $('h1').text() == 'Home Page'; true}
+	static url = ''
+	static content = {
+		securePage { $('a',text: 'Secure page') }
+		extremelySecurePage { $('a',text: 'Extremely secure page') }
+	}
 }

+ 5 - 5
samples/cas/sample-xml/src/integration-test/groovy/org/springframework/security/samples/cas/pages/LocalLogoutPage.groovy

@@ -27,9 +27,9 @@ import geb.*
  * @author Rob Winch
  */
 class LocalLogoutPage extends Page {
-    static url = 'cas-logout.jsp'
-    static at = { assert driver.currentUrl.endsWith(url); true }
-    static content = {
-        casServerLogout { $('a',text: 'Logout of CAS') }
-    }
+	static url = 'cas-logout.jsp'
+	static at = { assert driver.currentUrl.endsWith(url); true }
+	static content = {
+		casServerLogout { $('a',text: 'Logout of CAS') }
+	}
 }

+ 19 - 19
samples/cas/sample-xml/src/integration-test/groovy/org/springframework/security/samples/cas/pages/LoginPage.groovy

@@ -23,24 +23,24 @@ import geb.*
  * @author Rob Winch
  */
 class LoginPage extends Page {
-    static url = loginUrl()
-    static at = { assert driver.currentUrl.startsWith(loginUrl()); true}
-    static content = {
-        login(required:false) { user, password=user ->
-            loginForm.username = user
-            loginForm.password = password
-            submit.click()
-        }
-        loginForm { $('#login') }
-        submit { $('input', type: 'submit') }
-    }
+	static url = loginUrl()
+	static at = { assert driver.currentUrl.startsWith(loginUrl()); true}
+	static content = {
+		login(required:false) { user, password=user ->
+			loginForm.username = user
+			loginForm.password = password
+			submit.click()
+		}
+		loginForm { $('#login') }
+		submit { $('input', type: 'submit') }
+	}
 
-    /**
-     * Gets the login page url which might change based upon the system properties. This is to support using a randomly available port for CI.
-     * @return
-     */
-    private static String loginUrl() {
-        def host = System.getProperty('cas.server.host', 'localhost:9443')
-        "https://${host}/cas/login"
-    }
+	/**
+	 * Gets the login page url which might change based upon the system properties. This is to support using a randomly available port for CI.
+	 * @return
+	 */
+	private static String loginUrl() {
+		def host = System.getProperty('cas.server.host', 'localhost:9443')
+		"https://${host}/cas/login"
+	}
 }

+ 5 - 5
samples/cas/sample-xml/src/integration-test/groovy/org/springframework/security/samples/cas/pages/ProxyTicketSamplePage.groovy

@@ -25,9 +25,9 @@ import org.springframework.security.samples.cas.modules.*
  * @author Rob Winch
  */
 class ProxyTicketSamplePage extends Page {
-    static url = "secure/ptSample"
-    static at = { assert $('h1').text() == 'Secure Page using a Proxy Ticket'; true}
-    static content = {
-        navModule { module NavModule }
-    }
+	static url = "secure/ptSample"
+	static at = { assert $('h1').text() == 'Secure Page using a Proxy Ticket'; true}
+	static content = {
+		navModule { module NavModule }
+	}
 }

+ 5 - 5
samples/cas/sample-xml/src/integration-test/groovy/org/springframework/security/samples/cas/pages/SecurePage.groovy

@@ -25,9 +25,9 @@ import org.springframework.security.samples.cas.modules.*
  * @author Rob Winch
  */
 class SecurePage extends Page {
-    static url = "secure/"
-    static at = { assert $('h1').text() == 'Secure Page'; true}
-    static content = {
-        navModule { module NavModule }
-    }
+	static url = "secure/"
+	static at = { assert $('h1').text() == 'Secure Page'; true}
+	static content = {
+		navModule { module NavModule }
+	}
 }

+ 4 - 4
samples/cas/sample-xml/src/integration-test/resources/logback-test.xml

@@ -1,11 +1,11 @@
 <configuration>
   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
+	<encoder>
+	  <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+	</encoder>
   </appender>
 
   <root level="error">
-    <appender-ref ref="STDOUT" />
+	<appender-ref ref="STDOUT" />
   </root>
 </configuration>

+ 12 - 12
samples/cas/server/src/main/webapp/WEB-INF/classes/log4j.xml

@@ -2,16 +2,16 @@
 <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
 
 <log4j:configuration debug="false" xmlns:log4j="http://jakarta.apache.org/log4j/">
-    <appender name="console" class="org.apache.log4j.ConsoleAppender">
-        <layout class="org.apache.log4j.PatternLayout">
-            <param name="ConversionPattern" value="%d %p [%c] - &lt;%m&gt;%n"/>
-        </layout>
-    </appender>
-    <logger name="org.jasig" additivity="true">
-        <level value="@logLevel@" />
-    </logger>
-    <root>
-        <level value="ERROR"/>
-        <appender-ref ref="console"/>
-    </root>
+	<appender name="console" class="org.apache.log4j.ConsoleAppender">
+		<layout class="org.apache.log4j.PatternLayout">
+			<param name="ConversionPattern" value="%d %p [%c] - &lt;%m&gt;%n"/>
+		</layout>
+	</appender>
+	<logger name="org.jasig" additivity="true">
+		<level value="@logLevel@" />
+	</logger>
+	<root>
+		<level value="ERROR"/>
+		<appender-ref ref="console"/>
+	</root>
 </log4j:configuration>

Неке датотеке нису приказане због велике количине промена