Bläddra i källkod

NamespaceHttpTests groovy->java

Issue: gh-4939
Joe Grandja 7 år sedan
förälder
incheckning
dc9248e73c

+ 0 - 34
config/src/test/groovy/org/springframework/security/config/annotation/web/builders/DisableUseExpressionsConfig.java

@@ -1,34 +0,0 @@
-/*
- * Copyright 2002-2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.config.annotation.web.builders;
-
-import org.springframework.security.config.annotation.web.configuration.BaseWebConfig;
-import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
-import org.springframework.security.config.annotation.web.configurers.UrlAuthorizationConfigurer;
-
-@EnableWebSecurity
-public class DisableUseExpressionsConfig extends BaseWebConfig {
-	// @formatter:off
-	protected void configure(HttpSecurity http) throws Exception {
-		// This config is also on UrlAuthorizationConfigurer javadoc
-		http
-			.apply(new UrlAuthorizationConfigurer<>(getApplicationContext())).getRegistry()
-				.antMatchers("/users**", "/sessions/**").hasRole("USER")
-				.antMatchers("/signup").hasRole("ANONYMOUS")
-				.anyRequest().hasRole("USER");
-	}
-	// @formatter:on
-}

+ 0 - 499
config/src/test/groovy/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.groovy

@@ -1,499 +0,0 @@
-/*
- * Copyright 2002-2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *		http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.config.annotation.web.builders
-
-import javax.servlet.http.HttpServletRequest
-
-import org.springframework.context.annotation.Configuration
-import org.springframework.security.access.AccessDecisionManager
-import org.springframework.security.access.ConfigAttribute
-import org.springframework.security.access.vote.AuthenticatedVoter
-import org.springframework.security.access.vote.RoleVoter
-import org.springframework.security.authentication.AuthenticationManager
-import org.springframework.security.authentication.BadCredentialsException
-import org.springframework.security.config.annotation.BaseSpringSpec
-import org.springframework.security.config.annotation.web.builders.NamespaceHttpTests.AuthenticationManagerRefConfig.CustomAuthenticationManager
-import org.springframework.security.config.annotation.web.builders.NamespaceHttpTests.RequestMatcherRefConfig.MyRequestMatcher
-import org.springframework.security.config.annotation.web.configuration.BaseWebConfig
-import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
-import org.springframework.security.config.annotation.web.configurers.UrlAuthorizationConfigurer
-import org.springframework.security.config.http.SessionCreationPolicy;
-import org.springframework.security.core.Authentication
-import org.springframework.security.core.AuthenticationException
-import org.springframework.security.web.FilterInvocation
-import org.springframework.security.web.access.ExceptionTranslationFilter
-import org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource
-import org.springframework.security.web.access.expression.WebExpressionVoter
-import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource
-import org.springframework.security.web.access.intercept.FilterSecurityInterceptor
-import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint
-import org.springframework.security.web.authentication.www.BasicAuthenticationFilter
-import org.springframework.security.web.context.HttpSessionSecurityContextRepository
-import org.springframework.security.web.context.NullSecurityContextRepository
-import org.springframework.security.web.context.SecurityContextPersistenceFilter
-import org.springframework.security.web.jaasapi.JaasApiIntegrationFilter
-import org.springframework.security.web.savedrequest.HttpSessionRequestCache
-import org.springframework.security.web.savedrequest.NullRequestCache
-import org.springframework.security.web.savedrequest.RequestCacheAwareFilter
-import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter
-import org.springframework.security.web.session.SessionManagementFilter
-import org.springframework.security.web.util.matcher.RegexRequestMatcher
-import org.springframework.security.web.util.matcher.RequestMatcher
-
-/**
- * Tests to verify that all the functionality of <http> attributes is present
- *
- * @author Rob Winch
- *
- */
-public class NamespaceHttpTests extends BaseSpringSpec {
-	def "http@access-decision-manager-ref"() {
-		setup:
-			AccessDecisionManagerRefConfig.ACCESS_DECISION_MGR = Mock(AccessDecisionManager)
-			AccessDecisionManagerRefConfig.ACCESS_DECISION_MGR.supports(FilterInvocation) >> true
-			AccessDecisionManagerRefConfig.ACCESS_DECISION_MGR.supports(_ as ConfigAttribute) >> true
-		when:
-			loadConfig(AccessDecisionManagerRefConfig)
-		then:
-			findFilter(FilterSecurityInterceptor).accessDecisionManager == AccessDecisionManagerRefConfig.ACCESS_DECISION_MGR
-	}
-
-	@Configuration
-	static class AccessDecisionManagerRefConfig extends BaseWebConfig {
-		static AccessDecisionManager ACCESS_DECISION_MGR
-
-		protected void configure(HttpSecurity http) throws Exception {
-			http
-				.authorizeRequests()
-					.anyRequest().permitAll()
-					.accessDecisionManager(ACCESS_DECISION_MGR)
-		}
-	}
-
-	def "http@access-denied-page"() {
-		when:
-			loadConfig(AccessDeniedPageConfig)
-		then:
-			findFilter(ExceptionTranslationFilter).accessDeniedHandler.errorPage == "/AccessDeniedPageConfig"
-	}
-
-	@Configuration
-	static class AccessDeniedPageConfig extends BaseWebConfig {
-		protected void configure(HttpSecurity http) throws Exception {
-			http
-				.exceptionHandling()
-					.accessDeniedPage("/AccessDeniedPageConfig")
-		}
-	}
-
-	def "http@authentication-manager-ref"() {
-		when: "Specify AuthenticationManager"
-			loadConfig(AuthenticationManagerRefConfig)
-		then: "Populates the AuthenticationManager"
-			findFilter(FilterSecurityInterceptor).authenticationManager.parent.class == CustomAuthenticationManager
-	}
-
-	@Configuration
-	static class AuthenticationManagerRefConfig extends BaseWebConfig {
-		// demo authentication-manager-ref (could be any value)
-
-		@Override
-		protected AuthenticationManager authenticationManager() throws Exception {
-			return new CustomAuthenticationManager();
-		}
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			http
-				.authorizeRequests()
-					.anyRequest().hasRole("USER");
-		}
-
-		static class CustomAuthenticationManager implements AuthenticationManager {
-			public Authentication authenticate(Authentication authentication)
-					throws AuthenticationException {
-				throw new BadCredentialsException("This always fails");
-			}
-		}
-	}
-
-	// Note: There is no http@auto-config equivalent in Java Config
-
-	def "http@create-session=always"() {
-		when:
-			loadConfig(IfRequiredConfig)
-		then:
-			findFilter(SecurityContextPersistenceFilter).forceEagerSessionCreation == false
-			findFilter(SecurityContextPersistenceFilter).repo.allowSessionCreation == true
-			findFilter(SessionManagementFilter).securityContextRepository.allowSessionCreation == true
-			findFilter(ExceptionTranslationFilter).requestCache.class == HttpSessionRequestCache
-	}
-
-	@Configuration
-	static class CreateSessionAlwaysConfig extends BaseWebConfig {
-		protected void configure(HttpSecurity http) throws Exception {
-			http
-				.sessionManagement()
-					.sessionCreationPolicy(SessionCreationPolicy.ALWAYS);
-		}
-	}
-
-	def "http@create-session=stateless"() {
-		when:
-			loadConfig(CreateSessionStatelessConfig)
-		then:
-			findFilter(SecurityContextPersistenceFilter).forceEagerSessionCreation == false
-			findFilter(SecurityContextPersistenceFilter).repo.class == NullSecurityContextRepository
-			findFilter(SessionManagementFilter).securityContextRepository.class == NullSecurityContextRepository
-			findFilter(ExceptionTranslationFilter).requestCache.class == NullRequestCache
-			findFilter(RequestCacheAwareFilter).requestCache.class == NullRequestCache
-	}
-
-	@Configuration
-	static class CreateSessionStatelessConfig extends BaseWebConfig {
-		protected void configure(HttpSecurity http) throws Exception {
-			http
-				.sessionManagement()
-					.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
-		}
-	}
-
-	def "http@create-session=ifRequired"() {
-		when:
-			loadConfig(IfRequiredConfig)
-		then:
-			findFilter(SecurityContextPersistenceFilter).forceEagerSessionCreation == false
-			findFilter(SecurityContextPersistenceFilter).repo.allowSessionCreation == true
-			findFilter(SessionManagementFilter).securityContextRepository.allowSessionCreation == true
-	}
-
-	@Configuration
-	static class IfRequiredConfig extends BaseWebConfig {
-		protected void configure(HttpSecurity http) throws Exception {
-			http
-				.sessionManagement()
-					.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
-		}
-	}
-
-	def "http@create-session defaults to ifRequired"() {
-		when:
-			loadConfig(IfRequiredConfig)
-		then:
-			findFilter(SecurityContextPersistenceFilter).forceEagerSessionCreation == false
-			findFilter(SecurityContextPersistenceFilter).repo.allowSessionCreation == true
-			findFilter(SessionManagementFilter).securityContextRepository.allowSessionCreation == true
-	}
-
-	def "http@create-session=never"() {
-		when:
-			loadConfig(CreateSessionNeverConfig)
-		then:
-			findFilter(SecurityContextPersistenceFilter).forceEagerSessionCreation == false
-			findFilter(SecurityContextPersistenceFilter).repo.allowSessionCreation == false
-			findFilter(SessionManagementFilter).securityContextRepository.allowSessionCreation == false
-	}
-
-	@Configuration
-	static class CreateSessionNeverConfig extends BaseWebConfig {
-		protected void configure(HttpSecurity http) throws Exception {
-			http
-				.sessionManagement()
-					.sessionCreationPolicy(SessionCreationPolicy.NEVER);
-		}
-	}
-
-	@Configuration
-	static class DefaultCreateSessionConfig extends BaseWebConfig {
-		protected void configure(HttpSecurity http) throws Exception {
-		}
-	}
-
-	def "http@disable-url-rewriting = true (default for Java Config)"() {
-		when:
-			loadConfig(DefaultUrlRewritingConfig)
-		then:
-			findFilter(SecurityContextPersistenceFilter).repo.disableUrlRewriting
-	}
-
-	@Configuration
-	static class DefaultUrlRewritingConfig extends BaseWebConfig {
-		protected void configure(HttpSecurity http) throws Exception {
-		}
-	}
-
-	// http@disable-url-rewriting is on by default to disable it create a custom HttpSecurityContextRepository and use security-context-repository-ref
-
-	def "http@disable-url-rewriting = false"() {
-		when:
-			loadConfig(EnableUrlRewritingConfig)
-		then:
-			findFilter(SecurityContextPersistenceFilter).repo.disableUrlRewriting == false
-	}
-
-	@Configuration
-	static class EnableUrlRewritingConfig extends BaseWebConfig {
-		protected void configure(HttpSecurity http) throws Exception {
-			HttpSessionSecurityContextRepository repository = new HttpSessionSecurityContextRepository()
-			repository.disableUrlRewriting = false // explicitly configured
-
-			http.
-				securityContext()
-					.securityContextRepository(repository)
-		}
-	}
-
-	def "http@entry-point-ref"() {
-		when:
-			loadConfig(EntryPointRefConfig)
-		then:
-			findFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl == "/EntryPointRefConfig"
-	}
-
-	@Configuration
-	static class EntryPointRefConfig extends BaseWebConfig {
-		protected void configure(HttpSecurity http) throws Exception {
-			http
-				.exceptionHandling()
-					.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/EntryPointRefConfig"))
-		}
-	}
-
-	def "http@jaas-api-provision"() {
-		when:
-			loadConfig(JaasApiProvisionConfig)
-		then:
-			findFilter(JaasApiIntegrationFilter)
-	}
-
-	@Configuration
-	static class JaasApiProvisionConfig extends BaseWebConfig {
-		protected void configure(HttpSecurity http) throws Exception {
-			http
-				.addFilter(new JaasApiIntegrationFilter())
-		}
-	}
-
-	// http@name is not available since it can be done w/ standard bean configuration easily
-
-	def "http@once-per-request=true"() {
-		when:
-			loadConfig(OncePerRequestConfig)
-		then:
-			findFilter(FilterSecurityInterceptor).observeOncePerRequest
-	}
-
-	@Configuration
-	static class OncePerRequestConfig extends BaseWebConfig {
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			http
-				.authorizeRequests()
-					.anyRequest().hasRole("USER");
-		}
-	}
-
-	def "http@once-per-request=false"() {
-		when:
-			loadConfig(OncePerRequestFalseConfig)
-		then:
-			!findFilter(FilterSecurityInterceptor).observeOncePerRequest
-	}
-
-	@Configuration
-	static class OncePerRequestFalseConfig extends BaseWebConfig {
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {
-			http.
-				authorizeRequests()
-					.filterSecurityInterceptorOncePerRequest(false)
-					.antMatchers("/users**","/sessions/**").hasRole("ADMIN")
-					.antMatchers("/signup").permitAll()
-					.anyRequest().hasRole("USER");
-		}
-	}
-
-	def "http@realm"() {
-		setup:
-			loadConfig(RealmConfig)
-		when:
-			springSecurityFilterChain.doFilter(request,response,chain)
-		then:
-			response.getHeader("WWW-Authenticate") == 'Basic realm="RealmConfig"'
-	}
-
-	@Configuration
-	static class RealmConfig extends BaseWebConfig {
-		protected void configure(HttpSecurity http) throws Exception {
-			http
-				.authorizeRequests()
-					.anyRequest().authenticated()
-					.and()
-				.httpBasic().realmName("RealmConfig")
-		}
-	}
-
-	// http@request-matcher is not available (instead request securityMatcher instances are used)
-
-	def "http@request-matcher-ref ant"() {
-		when:
-			loadConfig(RequestMatcherAntConfig)
-		then:
-			filterChain(0).requestMatcher.pattern == "/api/**"
-	}
-
-	@Configuration
-	static class RequestMatcherAntConfig extends BaseWebConfig {
-		protected void configure(HttpSecurity http) throws Exception {
-			http
-				.antMatcher("/api/**")
-		}
-	}
-
-	def "http@request-matcher-ref regex"() {
-		when:
-			loadConfig(RequestMatcherRegexConfig)
-		then:
-			filterChain(0).requestMatcher.class == RegexRequestMatcher
-			filterChain(0).requestMatcher.pattern.matcher("/regex/a")
-			filterChain(0).requestMatcher.pattern.matcher("/regex/b")
-			!filterChain(0).requestMatcher.pattern.matcher("/regex1/b")
-	}
-
-	@Configuration
-	static class RequestMatcherRegexConfig extends BaseWebConfig {
-		protected void configure(HttpSecurity http) throws Exception {
-			http
-				.regexMatcher("/regex/.*")
-		}
-	}
-
-	def "http@request-matcher-ref"() {
-		when:
-			loadConfig(RequestMatcherRefConfig)
-		then:
-			filterChain(0).requestMatcher.class == MyRequestMatcher
-	}
-
-	@Configuration
-	static class RequestMatcherRefConfig extends BaseWebConfig {
-		protected void configure(HttpSecurity http) throws Exception {
-			http
-				.requestMatcher(new MyRequestMatcher());
-		}
-		static class MyRequestMatcher implements RequestMatcher {
-			public boolean matches(HttpServletRequest request) {
-				return true;
-			}
-		}
-	}
-
-	def "http@security=none"() {
-		when:
-			loadConfig(SecurityNoneConfig)
-		then:
-			filterChain(0).requestMatcher.pattern == "/resources/**"
-			filterChain(0).filters.empty
-			filterChain(1).requestMatcher.pattern == "/public/**"
-			filterChain(1).filters.empty
-	}
-
-	@Configuration
-	static class SecurityNoneConfig extends BaseWebConfig {
-
-		@Override
-		public void configure(WebSecurity web)
-				throws Exception {
-			web
-				.ignoring()
-					.antMatchers("/resources/**","/public/**")
-		}
-
-		@Override
-		protected void configure(HttpSecurity http) throws Exception {}
-
-	}
-
-	def "http@security-context-repository-ref"() {
-		when:
-			loadConfig(SecurityContextRepoConfig)
-		then:
-			findFilter(SecurityContextPersistenceFilter).repo.class == NullSecurityContextRepository
-	}
-
-	@Configuration
-	static class SecurityContextRepoConfig extends BaseWebConfig {
-		protected void configure(HttpSecurity http) throws Exception {
-			http
-				.securityContext()
-					.securityContextRepository(new NullSecurityContextRepository()) // security-context-repository-ref
-		}
-	}
-
-	def "http@servlet-api-provision=false"() {
-		when:
-			loadConfig(ServletApiProvisionConfig)
-		then:
-			findFilter(SecurityContextHolderAwareRequestFilter) == null
-	}
-
-	@Configuration
-	static class ServletApiProvisionConfig extends BaseWebConfig {
-		protected void configure(HttpSecurity http) throws Exception {
-			http.servletApi().disable()
-		}
-	}
-
-	def "http@servlet-api-provision defaults to true"() {
-		when:
-			loadConfig(ServletApiProvisionDefaultsConfig)
-		then:
-			findFilter(SecurityContextHolderAwareRequestFilter) != null
-	}
-
-	@Configuration
-	static class ServletApiProvisionDefaultsConfig extends BaseWebConfig {
-		protected void configure(HttpSecurity http) throws Exception {
-		}
-	}
-
-	def "http@use-expressions=true"() {
-		when:
-			loadConfig(UseExpressionsConfig)
-		then:
-			findFilter(FilterSecurityInterceptor).securityMetadataSource.class == ExpressionBasedFilterInvocationSecurityMetadataSource
-			findFilter(FilterSecurityInterceptor).accessDecisionManager.decisionVoters.collect { it.class } == [WebExpressionVoter]
-	}
-
-	@EnableWebSecurity
-	static class UseExpressionsConfig extends BaseWebConfig {
-		protected void configure(HttpSecurity http) throws Exception {
-			http
-				.authorizeRequests()
-					.antMatchers("/users**","/sessions/**").hasRole("USER")
-					.antMatchers("/signup").permitAll()
-					.anyRequest().hasRole("USER")
-		}
-	}
-
-	def "http@use-expressions=false"() {
-		when:
-			loadConfig(DisableUseExpressionsConfig)
-		then:
-			findFilter(FilterSecurityInterceptor).securityMetadataSource.class == DefaultFilterInvocationSecurityMetadataSource
-			findFilter(FilterSecurityInterceptor).accessDecisionManager.decisionVoters.collect { it.class } == [RoleVoter, AuthenticatedVoter]
-	}
-}

+ 582 - 0
config/src/test/java/org/springframework/security/config/annotation/web/builders/NamespaceHttpTests.java

@@ -0,0 +1,582 @@
+/*
+ * Copyright 2002-2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.security.config.annotation.web.builders;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.AccessDecisionManager;
+import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.jaas.JaasAuthenticationToken;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.annotation.web.configurers.UrlAuthorizationConfigurer;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.config.test.SpringTestRule;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.userdetails.PasswordEncodedUser;
+import org.springframework.security.web.DefaultSecurityFilterChain;
+import org.springframework.security.web.FilterChainProxy;
+import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource;
+import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource;
+import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
+import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
+import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
+import org.springframework.security.web.context.NullSecurityContextRepository;
+import org.springframework.security.web.jaasapi.JaasApiIntegrationFilter;
+import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestWrapper;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+import org.springframework.security.web.util.matcher.RegexRequestMatcher;
+import org.springframework.security.web.util.matcher.RequestMatcher;
+import org.springframework.stereotype.Controller;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.web.bind.annotation.GetMapping;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
+
+/**
+ * Tests to verify that all the functionality of <http> attributes are present in Java Config.
+ *
+ * @author Rob Winch
+ * @author Joe Grandja
+ */
+public class NamespaceHttpTests {
+	@Rule
+	public final SpringTestRule spring = new SpringTestRule();
+
+	@Autowired
+	private MockMvc mockMvc;
+
+	@Test	// http@access-decision-manager-ref
+	public void configureWhenAccessDecisionManagerSetThenVerifyUse() throws Exception {
+		AccessDecisionManagerRefConfig.ACCESS_DECISION_MANAGER = mock(AccessDecisionManager.class);
+		when(AccessDecisionManagerRefConfig.ACCESS_DECISION_MANAGER.supports(FilterInvocation.class)).thenReturn(true);
+		when(AccessDecisionManagerRefConfig.ACCESS_DECISION_MANAGER.supports(any(ConfigAttribute.class))).thenReturn(true);
+
+		this.spring.register(AccessDecisionManagerRefConfig.class).autowire();
+
+		this.mockMvc.perform(get("/"));
+
+		verify(AccessDecisionManagerRefConfig.ACCESS_DECISION_MANAGER, times(1)).decide(any(Authentication.class), any(), anyCollection());
+	}
+
+	@EnableWebSecurity
+	static class AccessDecisionManagerRefConfig extends WebSecurityConfigurerAdapter {
+		static AccessDecisionManager ACCESS_DECISION_MANAGER;
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().permitAll()
+				.accessDecisionManager(ACCESS_DECISION_MANAGER);
+		}
+	}
+
+	@Test	// http@access-denied-page
+	public void configureWhenAccessDeniedPageSetAndRequestForbiddenThenForwardedToAccessDeniedPage() throws Exception {
+		this.spring.register(AccessDeniedPageConfig.class).autowire();
+
+		this.mockMvc.perform(get("/admin").with(user(PasswordEncodedUser.user())))
+			.andExpect(status().isForbidden())
+			.andExpect(forwardedUrl("/AccessDeniedPage"));
+	}
+
+	@EnableWebSecurity
+	static class AccessDeniedPageConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.antMatchers("/admin").hasRole("ADMIN")
+					.anyRequest().authenticated()
+					.and()
+				.exceptionHandling()
+					.accessDeniedPage("/AccessDeniedPage");
+		}
+	}
+
+	@Test	// http@authentication-manager-ref
+	public void configureWhenAuthenticationManagerProvidedThenVerifyUse() throws Exception {
+		AuthenticationManagerRefConfig.AUTHENTICATION_MANAGER = mock(AuthenticationManager.class);
+		this.spring.register(AuthenticationManagerRefConfig.class).autowire();
+
+		this.mockMvc.perform(formLogin());
+
+		verify(AuthenticationManagerRefConfig.AUTHENTICATION_MANAGER, times(1)).authenticate(any(Authentication.class));
+	}
+
+	@EnableWebSecurity
+	static class AuthenticationManagerRefConfig extends WebSecurityConfigurerAdapter {
+		static AuthenticationManager AUTHENTICATION_MANAGER;
+
+		@Override
+		protected AuthenticationManager authenticationManager() throws Exception {
+			return AUTHENTICATION_MANAGER;
+		}
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().authenticated()
+					.and()
+				.formLogin();
+		}
+	}
+
+	@Test	// http@create-session=always
+	public void configureWhenSessionCreationPolicyAlwaysThenSessionCreatedOnRequest() throws Exception {
+		this.spring.register(CreateSessionAlwaysConfig.class).autowire();
+
+		MvcResult mvcResult = this.mockMvc.perform(get("/")).andReturn();
+		HttpSession session = mvcResult.getRequest().getSession(false);
+
+		assertThat(session).isNotNull();
+		assertThat(session.isNew()).isTrue();
+	}
+
+	@EnableWebSecurity
+	static class CreateSessionAlwaysConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().permitAll()
+					.and()
+				.sessionManagement()
+					.sessionCreationPolicy(SessionCreationPolicy.ALWAYS);
+		}
+	}
+
+	@Test	// http@create-session=stateless
+	public void configureWhenSessionCreationPolicyStatelessThenSessionNotCreatedOnRequest() throws Exception {
+		this.spring.register(CreateSessionStatelessConfig.class).autowire();
+
+		MvcResult mvcResult = this.mockMvc.perform(get("/")).andReturn();
+		HttpSession session = mvcResult.getRequest().getSession(false);
+
+		assertThat(session).isNull();
+	}
+
+	@EnableWebSecurity
+	static class CreateSessionStatelessConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().permitAll()
+					.and()
+				.sessionManagement()
+					.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
+		}
+	}
+
+	@Test	// http@create-session=ifRequired
+	public void configureWhenSessionCreationPolicyIfRequiredThenSessionCreatedWhenRequiredOnRequest() throws Exception {
+		this.spring.register(IfRequiredConfig.class).autowire();
+
+		MvcResult mvcResult = this.mockMvc.perform(get("/unsecure")).andReturn();
+		HttpSession session = mvcResult.getRequest().getSession(false);
+
+		assertThat(session).isNull();
+
+		mvcResult = this.mockMvc.perform(formLogin()).andReturn();
+		session = mvcResult.getRequest().getSession(false);
+
+		assertThat(session).isNotNull();
+		assertThat(session.isNew()).isTrue();
+	}
+
+	@EnableWebSecurity
+	static class IfRequiredConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.antMatchers("/unsecure").permitAll()
+					.anyRequest().authenticated()
+					.and()
+				.sessionManagement()
+					.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
+					.and()
+				.formLogin();
+		}
+	}
+
+	@Test	// http@create-session=never
+	public void configureWhenSessionCreationPolicyNeverThenSessionNotCreatedOnRequest() throws Exception {
+		this.spring.register(CreateSessionNeverConfig.class).autowire();
+
+		MvcResult mvcResult = this.mockMvc.perform(get("/")).andReturn();
+		HttpSession session = mvcResult.getRequest().getSession(false);
+
+		assertThat(session).isNull();
+	}
+
+	@EnableWebSecurity
+	static class CreateSessionNeverConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().anonymous()
+					.and()
+				.sessionManagement()
+					.sessionCreationPolicy(SessionCreationPolicy.NEVER);
+		}
+	}
+
+	@Test	// http@entry-point-ref
+	public void configureWhenAuthenticationEntryPointSetAndRequestUnauthorizedThenRedirectedToAuthenticationEntryPoint() throws Exception {
+		this.spring.register(EntryPointRefConfig.class).autowire();
+
+		this.mockMvc.perform(get("/"))
+			.andExpect(status().is3xxRedirection())
+			.andExpect(redirectedUrlPattern("**/entry-point"));
+	}
+
+	@EnableWebSecurity
+	static class EntryPointRefConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().authenticated()
+					.and()
+				.exceptionHandling()
+					.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/entry-point"))
+					.and()
+				.formLogin();
+		}
+	}
+
+	@Test	// http@jaas-api-provision
+	public void configureWhenJaasApiIntegrationFilterAddedThenJaasSubjectObtained() throws Exception {
+		LoginContext loginContext = mock(LoginContext.class);
+		when(loginContext.getSubject()).thenReturn(new Subject());
+
+		JaasAuthenticationToken authenticationToken = mock(JaasAuthenticationToken.class);
+		when(authenticationToken.isAuthenticated()).thenReturn(true);
+		when(authenticationToken.getLoginContext()).thenReturn(loginContext);
+
+		this.spring.register(JaasApiProvisionConfig.class).autowire();
+
+		this.mockMvc.perform(get("/").with(authentication(authenticationToken)));
+
+		verify(loginContext, times(1)).getSubject();
+	}
+
+	@EnableWebSecurity
+	static class JaasApiProvisionConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.addFilter(new JaasApiIntegrationFilter());
+		}
+	}
+
+	@Test	// http@realm
+	public void configureWhenHttpBasicAndRequestUnauthorizedThenReturnWWWAuthenticateWithRealm() throws Exception {
+		this.spring.register(RealmConfig.class).autowire();
+
+		this.mockMvc.perform(get("/"))
+			.andExpect(status().isUnauthorized())
+			.andExpect(header().string("WWW-Authenticate", "Basic realm=\"RealmConfig\""));
+	}
+
+	@EnableWebSecurity
+	static class RealmConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().authenticated()
+					.and()
+				.httpBasic()
+					.realmName("RealmConfig");
+		}
+	}
+
+	@Test	// http@request-matcher-ref ant
+	public void configureWhenAntPatternMatchingThenAntPathRequestMatcherUsed() throws Exception {
+		this.spring.register(RequestMatcherAntConfig.class).autowire();
+
+		FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
+
+		assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class);
+		DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains().get(0);
+		assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class);
+	}
+
+	@EnableWebSecurity
+	static class RequestMatcherAntConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.antMatcher("/api/**");
+		}
+	}
+
+	@Test	// http@request-matcher-ref regex
+	public void configureWhenRegexPatternMatchingThenRegexRequestMatcherUsed() throws Exception {
+		this.spring.register(RequestMatcherRegexConfig.class).autowire();
+
+		FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
+
+		assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class);
+		DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains().get(0);
+		assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(RegexRequestMatcher.class);
+	}
+
+	@EnableWebSecurity
+	static class RequestMatcherRegexConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.regexMatcher("/regex/.*");
+		}
+	}
+
+	@Test	// http@request-matcher-ref
+	public void configureWhenRequestMatcherProvidedThenRequestMatcherUsed() throws Exception {
+		this.spring.register(RequestMatcherRefConfig.class).autowire();
+
+		FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
+
+		assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class);
+		DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains().get(0);
+		assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(RequestMatcherRefConfig.MyRequestMatcher.class);
+	}
+
+	@EnableWebSecurity
+	static class RequestMatcherRefConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.requestMatcher(new MyRequestMatcher());
+		}
+
+		static class MyRequestMatcher implements RequestMatcher {
+			public boolean matches(HttpServletRequest request) {
+				return true;
+			}
+		}
+	}
+
+	@Test	// http@security=none
+	public void configureWhenIgnoredAntPatternsThenAntPathRequestMatcherUsedWithNoFilters() throws Exception {
+		this.spring.register(SecurityNoneConfig.class).autowire();
+
+		FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
+
+		assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class);
+		DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains().get(0);
+		assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class);
+		assertThat(((AntPathRequestMatcher) securityFilterChain.getRequestMatcher()).getPattern()).isEqualTo("/resources/**");
+		assertThat(securityFilterChain.getFilters()).isEmpty();
+
+		assertThat(filterChainProxy.getFilterChains().get(1)).isInstanceOf(DefaultSecurityFilterChain.class);
+		securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains().get(1);
+		assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class);
+		assertThat(((AntPathRequestMatcher) securityFilterChain.getRequestMatcher()).getPattern()).isEqualTo("/public/**");
+		assertThat(securityFilterChain.getFilters()).isEmpty();
+	}
+
+	@EnableWebSecurity
+	static class SecurityNoneConfig extends WebSecurityConfigurerAdapter {
+
+		@Override
+		public void configure(WebSecurity web) throws Exception {
+			web
+				.ignoring()
+					.antMatchers("/resources/**", "/public/**");
+		}
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+		}
+	}
+
+	@Test	// http@security-context-repository-ref
+	public void configureWhenNullSecurityContextRepositoryThenSecurityContextNotSavedInSession() throws Exception {
+		this.spring.register(SecurityContextRepoConfig.class).autowire();
+
+		MvcResult mvcResult = this.mockMvc.perform(formLogin()).andReturn();
+		HttpSession session = mvcResult.getRequest().getSession(false);
+		assertThat(session).isNull();
+	}
+
+	@EnableWebSecurity
+	static class SecurityContextRepoConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().authenticated()
+					.and()
+				.securityContext()
+					.securityContextRepository(new NullSecurityContextRepository())
+					.and()
+				.formLogin();
+		}
+
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+			auth
+				.inMemoryAuthentication()
+					.withUser(PasswordEncodedUser.user());
+		}
+	}
+
+	@Test	// http@servlet-api-provision=false
+	public void configureWhenServletApiDisabledThenRequestNotServletApiWrapper() throws Exception {
+		this.spring.register(ServletApiProvisionConfig.class, MainController.class).autowire();
+
+		this.mockMvc.perform(get("/"));
+
+		assertThat(MainController.HTTP_SERVLET_REQUEST_TYPE).isNotInstanceOf(SecurityContextHolderAwareRequestWrapper.class);
+	}
+
+	@EnableWebSecurity
+	static class ServletApiProvisionConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().permitAll()
+					.and()
+				.servletApi()
+					.disable();
+		}
+	}
+
+	@Test	// http@servlet-api-provision defaults to true
+	public void configureWhenServletApiDefaultThenRequestIsServletApiWrapper() throws Exception {
+		this.spring.register(ServletApiProvisionDefaultsConfig.class, MainController.class).autowire();
+
+		this.mockMvc.perform(get("/"));
+
+		assertThat(SecurityContextHolderAwareRequestWrapper.class).isAssignableFrom(MainController.HTTP_SERVLET_REQUEST_TYPE);
+	}
+
+	@EnableWebSecurity
+	static class ServletApiProvisionDefaultsConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.anyRequest().permitAll();
+		}
+	}
+
+	@Controller
+	static class MainController {
+		static Class<? extends HttpServletRequest> HTTP_SERVLET_REQUEST_TYPE;
+
+		@GetMapping("/")
+		public String index(HttpServletRequest request) {
+			HTTP_SERVLET_REQUEST_TYPE = request.getClass();
+			return "index";
+		}
+	}
+
+	@Test	// http@use-expressions=true
+	public void configureWhenUseExpressionsEnabledThenExpressionBasedSecurityMetadataSource() throws Exception {
+		this.spring.register(UseExpressionsConfig.class).autowire();
+
+		UseExpressionsConfig config = this.spring.getContext().getBean(UseExpressionsConfig.class);
+
+		assertThat(ExpressionBasedFilterInvocationSecurityMetadataSource.class)
+			.isAssignableFrom(config.filterInvocationSecurityMetadataSourceType);
+	}
+
+	@EnableWebSecurity
+	static class UseExpressionsConfig extends WebSecurityConfigurerAdapter {
+		private Class<? extends FilterInvocationSecurityMetadataSource> filterInvocationSecurityMetadataSourceType;
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.authorizeRequests()
+					.antMatchers("/users**", "/sessions/**").hasRole("USER")
+					.antMatchers("/signup").permitAll()
+					.anyRequest().hasRole("USER");
+		}
+
+		@Override
+		public void init(final WebSecurity web) throws Exception {
+			super.init(web);
+			final HttpSecurity http = this.getHttp();
+			web.postBuildAction(() -> {
+				FilterSecurityInterceptor securityInterceptor = http.getSharedObject(FilterSecurityInterceptor.class);
+				UseExpressionsConfig.this.filterInvocationSecurityMetadataSourceType =
+					securityInterceptor.getSecurityMetadataSource().getClass();
+			});
+		}
+	}
+
+	@Test	// http@use-expressions=false
+	public void configureWhenUseExpressionsDisabledThenDefaultSecurityMetadataSource() throws Exception {
+		this.spring.register(DisableUseExpressionsConfig.class).autowire();
+
+		DisableUseExpressionsConfig config = this.spring.getContext().getBean(DisableUseExpressionsConfig.class);
+
+		assertThat(DefaultFilterInvocationSecurityMetadataSource.class)
+			.isAssignableFrom(config.filterInvocationSecurityMetadataSourceType);
+	}
+
+	@EnableWebSecurity
+	static class DisableUseExpressionsConfig extends WebSecurityConfigurerAdapter {
+		private Class<? extends FilterInvocationSecurityMetadataSource> filterInvocationSecurityMetadataSourceType;
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.apply(new UrlAuthorizationConfigurer<>(getApplicationContext())).getRegistry()
+					.antMatchers("/users**", "/sessions/**").hasRole("USER")
+					.antMatchers("/signup").hasRole("ANONYMOUS")
+					.anyRequest().hasRole("USER");
+		}
+
+		@Override
+		public void init(final WebSecurity web) throws Exception {
+			super.init(web);
+			final HttpSecurity http = this.getHttp();
+			web.postBuildAction(() -> {
+				FilterSecurityInterceptor securityInterceptor = http.getSharedObject(FilterSecurityInterceptor.class);
+				DisableUseExpressionsConfig.this.filterInvocationSecurityMetadataSourceType =
+					securityInterceptor.getSecurityMetadataSource().getClass();
+			});
+		}
+	}
+}