From f294480e6ba453afb5d5a8cfdce1d53ca3a38d51 Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Fri, 20 Sep 2013 15:28:50 -0500 Subject: [PATCH] SEC-2329: JC @Autowire(required=false) AuthenticationTrustResolver Java Configuration now allows optional @Autowire of AuthenticationTrustResolver. In the WebSecurityConfigurerAdapter this is done by populating AuthenticationTrustResolver as a sharedObject. --- .../GlobalMethodSecurityConfiguration.java | 21 +++++++-- .../WebSecurityConfigurerAdapter.java | 9 ++++ .../AbstractInterceptUrlConfigurer.java | 27 +++++++---- .../ExpressionUrlAuthorizationConfigurer.java | 28 ++++++++--- .../web/configurers/ServletApiConfigurer.java | 9 +++- .../SessionManagementConfigurer.java | 24 +++++++--- .../UrlAuthorizationConfigurer.java | 11 +++-- ...balMethodSecurityConfigurationTests.groovy | 47 +++++++++++++++---- .../WebSecurityConfigurerAdapterTests.groovy | 23 ++++++++- .../ServletApiConfigurerTests.groovy | 22 +++++++++ .../SessionManagementConfigurerTests.groovy | 23 +++++++++ 11 files changed, 200 insertions(+), 44 deletions(-) diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java index c5815bd8fa..cbfbed4fb6 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java @@ -62,6 +62,7 @@ import org.springframework.security.access.vote.AffirmativeBased; 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.AuthenticationTrustResolver; import org.springframework.security.authentication.DefaultAuthenticationEventPublisher; import org.springframework.security.config.annotation.ObjectPostProcessor; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; @@ -85,6 +86,7 @@ public class GlobalMethodSecurityConfiguration implements ImportAware { throw new IllegalStateException(ObjectPostProcessor.class.getName()+ " is a required bean. Ensure you have used @"+EnableGlobalMethodSecurity.class.getName()); } }; + private DefaultMethodSecurityExpressionHandler defaultMethodExpressionHandler = new DefaultMethodSecurityExpressionHandler(); private AuthenticationManager authenticationManager; private AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR); private boolean disableAuthenticationRegistry; @@ -192,16 +194,20 @@ public class GlobalMethodSecurityConfiguration implements ImportAware { } /** - * Provide a {@link MethodSecurityExpressionHandler} that is - * registered with the {@link ExpressionBasedPreInvocationAdvice}. The default is - * {@link DefaultMethodSecurityExpressionHandler} + * Provide a {@link MethodSecurityExpressionHandler} that is registered with + * the {@link ExpressionBasedPreInvocationAdvice}. The default is + * {@link DefaultMethodSecurityExpressionHandler} which optionally will + * Autowire an {@link AuthenticationTrustResolver}. * - *

Subclasses may override this method to provide a custom {@link MethodSecurityExpressionHandler}

+ *

+ * Subclasses may override this method to provide a custom + * {@link MethodSecurityExpressionHandler} + *

* * @return */ protected MethodSecurityExpressionHandler expressionHandler() { - return new DefaultMethodSecurityExpressionHandler(); + return defaultMethodExpressionHandler; } /** @@ -339,6 +345,11 @@ public class GlobalMethodSecurityConfiguration implements ImportAware { .fromMap(annotationAttributes); } + @Autowired(required = false) + public void setAuthenticationTrustResolver(AuthenticationTrustResolver trustResolver) { + this.defaultMethodExpressionHandler.setTrustResolver(trustResolver); + } + @Autowired public void setApplicationContext(ApplicationContext context) { this.context = context; diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java index 4ad6b4d71d..a6cfc7e8a1 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java @@ -24,6 +24,8 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.AuthenticationTrustResolver; +import org.springframework.security.authentication.AuthenticationTrustResolverImpl; import org.springframework.security.authentication.DefaultAuthenticationEventPublisher; import org.springframework.security.config.annotation.ObjectPostProcessor; import org.springframework.security.config.annotation.SecurityConfigurer; @@ -76,6 +78,7 @@ public abstract class WebSecurityConfigurerAdapter implements SecurityConfigurer private boolean disableAuthenticationRegistration; private boolean authenticationManagerInitialized; private AuthenticationManager authenticationManager; + private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl(); private HttpSecurity http; private boolean disableDefaults; @@ -153,6 +156,7 @@ public abstract class WebSecurityConfigurerAdapter implements SecurityConfigurer http.setSharedObject(UserDetailsService.class, userDetailsService()); http.setSharedObject(ApplicationContext.class, context); http.setSharedObject(ContentNegotiationStrategy.class, contentNegotiationStrategy); + http.setSharedObject(AuthenticationTrustResolver.class, trustResolver); if(!disableDefaults) { http .csrf().and() @@ -312,6 +316,11 @@ public abstract class WebSecurityConfigurerAdapter implements SecurityConfigurer this.context = context; } + @Autowired(required=false) + public void setTrustResolver(AuthenticationTrustResolver trustResolver) { + this.trustResolver = trustResolver; + } + @Autowired(required=false) public void setContentNegotationStrategy(ContentNegotiationStrategy contentNegotiationStrategy) { this.contentNegotiationStrategy = contentNegotiationStrategy; diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractInterceptUrlConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractInterceptUrlConfigurer.java index 64d4487351..72de2bd786 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractInterceptUrlConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AbstractInterceptUrlConfigurer.java @@ -98,11 +98,11 @@ abstract class AbstractInterceptUrlConfigurer,C @Override public void configure(H http) throws Exception { - FilterInvocationSecurityMetadataSource metadataSource = createMetadataSource(); + FilterInvocationSecurityMetadataSource metadataSource = createMetadataSource(http); if(metadataSource == null) { return; } - FilterSecurityInterceptor securityInterceptor = createFilterSecurityInterceptor(metadataSource, http.getSharedObject(AuthenticationManager.class)); + FilterSecurityInterceptor securityInterceptor = createFilterSecurityInterceptor(http, metadataSource, http.getSharedObject(AuthenticationManager.class)); if(filterSecurityInterceptorOncePerRequest != null) { securityInterceptor.setObserveOncePerRequest(filterSecurityInterceptorOncePerRequest); } @@ -115,38 +115,44 @@ abstract class AbstractInterceptUrlConfigurer,C * Subclasses should implement this method to provide a {@link FilterInvocationSecurityMetadataSource} for the * {@link FilterSecurityInterceptor}. * + * @param http the builder to use + * * @return the {@link FilterInvocationSecurityMetadataSource} to set on the {@link FilterSecurityInterceptor}. * Cannot be null. */ - abstract FilterInvocationSecurityMetadataSource createMetadataSource(); + abstract FilterInvocationSecurityMetadataSource createMetadataSource(H http); /** * Subclasses should implement this method to provide the {@link AccessDecisionVoter} instances used to create the * default {@link AccessDecisionManager} * + * @param http the builder to use + * * @return the {@link AccessDecisionVoter} instances used to create the * default {@link AccessDecisionManager} */ @SuppressWarnings("rawtypes") - abstract List getDecisionVoters(); + abstract List getDecisionVoters(H http); /** * Creates the default {@code AccessDecisionManager} * @return the default {@code AccessDecisionManager} */ - private AccessDecisionManager createDefaultAccessDecisionManager() { - return new AffirmativeBased(getDecisionVoters()); + private AccessDecisionManager createDefaultAccessDecisionManager(H http) { + return new AffirmativeBased(getDecisionVoters(http)); } /** * If currently null, creates a default {@link AccessDecisionManager} using * {@link #createDefaultAccessDecisionManager()}. Otherwise returns the {@link AccessDecisionManager}. * + * @param http the builder to use + * * @return the {@link AccessDecisionManager} to use */ - private AccessDecisionManager getAccessDecisionManager() { + private AccessDecisionManager getAccessDecisionManager(H http) { if (accessDecisionManager == null) { - accessDecisionManager = createDefaultAccessDecisionManager(); + accessDecisionManager = createDefaultAccessDecisionManager(http); } return accessDecisionManager; } @@ -154,16 +160,17 @@ abstract class AbstractInterceptUrlConfigurer,C /** * Creates the {@link FilterSecurityInterceptor} * + * @param http the builder to use * @param metadataSource the {@link FilterInvocationSecurityMetadataSource} to use * @param authenticationManager the {@link AuthenticationManager} to use * @return the {@link FilterSecurityInterceptor} * @throws Exception */ - private FilterSecurityInterceptor createFilterSecurityInterceptor(FilterInvocationSecurityMetadataSource metadataSource, + private FilterSecurityInterceptor createFilterSecurityInterceptor(H http, FilterInvocationSecurityMetadataSource metadataSource, AuthenticationManager authenticationManager) throws Exception { FilterSecurityInterceptor securityInterceptor = new FilterSecurityInterceptor(); securityInterceptor.setSecurityMetadataSource(metadataSource); - securityInterceptor.setAccessDecisionManager(getAccessDecisionManager()); + securityInterceptor.setAccessDecisionManager(getAccessDecisionManager(http)); securityInterceptor.setAuthenticationManager(authenticationManager); securityInterceptor.afterPropertiesSet(); return securityInterceptor; diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java index e34018cfb6..c96b2814e2 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java @@ -24,6 +24,7 @@ import org.springframework.security.access.AccessDecisionVoter; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.SecurityConfig; import org.springframework.security.access.expression.SecurityExpressionHandler; +import org.springframework.security.authentication.AuthenticationTrustResolver; import org.springframework.security.config.annotation.ObjectPostProcessor; import org.springframework.security.config.annotation.web.HttpSecurityBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -56,7 +57,9 @@ import org.springframework.util.StringUtils; * *

Shared Objects Used

* - * No shared objects are used. + *
    + *
  • {@link AuthenticationTrustResolver} is optionally used to populate the {@link DefaultWebSecurityExpressionHandler}
  • + *
* * @param the type of {@link HttpSecurityBuilder} that is being configured * @@ -72,7 +75,7 @@ public final class ExpressionUrlAuthorizationConfigurer expressionHandler = new DefaultWebSecurityExpressionHandler(); + private SecurityExpressionHandler expressionHandler; /** * Creates a new instance @@ -110,21 +113,21 @@ public final class ExpressionUrlAuthorizationConfigurer getDecisionVoters() { + final List getDecisionVoters(H http) { List decisionVoters = new ArrayList(); WebExpressionVoter expressionVoter = new WebExpressionVoter(); - expressionVoter.setExpressionHandler(expressionHandler); + expressionVoter.setExpressionHandler(getExpressionHandler(http)); decisionVoters.add(expressionVoter); return decisionVoters; } @Override - final ExpressionBasedFilterInvocationSecurityMetadataSource createMetadataSource() { + final ExpressionBasedFilterInvocationSecurityMetadataSource createMetadataSource(H http) { LinkedHashMap> requestMap = createRequestMap(); if(requestMap.isEmpty()) { throw new IllegalStateException("At least one mapping is required (i.e. authorizeRequests().anyRequest.authenticated())"); } - return new ExpressionBasedFilterInvocationSecurityMetadataSource(requestMap, expressionHandler); + return new ExpressionBasedFilterInvocationSecurityMetadataSource(requestMap, getExpressionHandler(http)); } /** @@ -141,6 +144,19 @@ public final class ExpressionUrlAuthorizationConfigurer getExpressionHandler(H http) { + if(expressionHandler == null) { + DefaultWebSecurityExpressionHandler defaultHandler = new DefaultWebSecurityExpressionHandler(); + AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class); + if(trustResolver != null) { + defaultHandler.setTrustResolver(trustResolver); + } + expressionHandler = defaultHandler; + } + + return expressionHandler; + } + private static String hasRole(String role) { Assert.notNull(role, "role cannot be null"); if (role.startsWith("ROLE_")) { diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurer.java index c9812a0abd..9ffcd7b570 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurer.java @@ -20,6 +20,7 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.AuthenticationTrustResolver; import org.springframework.security.config.annotation.web.HttpSecurityBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.core.context.SecurityContext; @@ -45,7 +46,9 @@ import org.springframework.security.web.servletapi.SecurityContextHolderAwareReq * *

Shared Objects Used

* - * No shared Objects are used. + *
    + *
  • {@link AuthenticationTrustResolver} is optionally used to populate the {@link SecurityContextHolderAwareRequestFilter}
  • + *
* * @author Rob Winch * @since 3.2 @@ -75,6 +78,10 @@ public final class ServletApiConfigurer> extend LogoutConfigurer logoutConf = http.getConfigurer(LogoutConfigurer.class); List logoutHandlers = logoutConf == null ? null : logoutConf.getLogoutHandlers(); securityContextRequestFilter.setLogoutHandlers(logoutHandlers); + AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class); + if(trustResolver != null) { + securityContextRequestFilter.setTrustResolver(trustResolver); + } securityContextRequestFilter = postProcess(securityContextRequestFilter); http.addFilter(securityContextRequestFilter); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java index 7e0d918db8..6328fcf631 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java @@ -22,6 +22,7 @@ import java.util.List; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import org.springframework.security.authentication.AuthenticationTrustResolver; import org.springframework.security.config.annotation.web.HttpSecurityBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.http.SessionCreationPolicy; @@ -71,6 +72,7 @@ import org.springframework.util.Assert; * *
    *
  • {@link SecurityContextRepository}
  • + *
  • {@link AuthenticationTrustResolver} is optionally used to populate the {@link HttpSessionSecurityContextRepository} and {@link SessionManagementFilter}
  • *
* * @author Rob Winch @@ -337,28 +339,32 @@ public final class SessionManagementConfigurer> } @Override - public void init(H builder) throws Exception { - SecurityContextRepository securityContextRepository = builder.getSharedObject(SecurityContextRepository.class); + public void init(H http) throws Exception { + SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class); boolean stateless = isStateless(); if(securityContextRepository == null) { if(stateless) { - builder.setSharedObject(SecurityContextRepository.class, new NullSecurityContextRepository()); + http.setSharedObject(SecurityContextRepository.class, new NullSecurityContextRepository()); } else { HttpSessionSecurityContextRepository httpSecurityRepository = new HttpSessionSecurityContextRepository(); httpSecurityRepository.setDisableUrlRewriting(!enableSessionUrlRewriting); httpSecurityRepository.setAllowSessionCreation(isAllowSessionCreation()); - builder.setSharedObject(SecurityContextRepository.class, httpSecurityRepository); + AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class); + if(trustResolver != null) { + httpSecurityRepository.setTrustResolver(trustResolver); + } + http.setSharedObject(SecurityContextRepository.class, httpSecurityRepository); } } - RequestCache requestCache = builder.getSharedObject(RequestCache.class); + RequestCache requestCache = http.getSharedObject(RequestCache.class); if(requestCache == null) { if(stateless) { - builder.setSharedObject(RequestCache.class, new NullRequestCache()); + http.setSharedObject(RequestCache.class, new NullRequestCache()); } } - builder.setSharedObject(SessionAuthenticationStrategy.class, getSessionAuthenticationStrategy()); + http.setSharedObject(SessionAuthenticationStrategy.class, getSessionAuthenticationStrategy()); } @Override @@ -371,6 +377,10 @@ public final class SessionManagementConfigurer> if(invalidSessionUrl != null) { sessionManagementFilter.setInvalidSessionStrategy(new SimpleRedirectInvalidSessionStrategy(invalidSessionUrl)); } + AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class); + if(trustResolver != null) { + sessionManagementFilter.setTrustResolver(trustResolver); + } sessionManagementFilter = postProcess(sessionManagementFilter); http.addFilter(sessionManagementFilter); diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurer.java index d3c2d933ea..ed86671223 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurer.java @@ -84,10 +84,12 @@ public final class UrlAuthorizationConfigurer, * Creates the default {@link AccessDecisionVoter} instances used if an * {@link AccessDecisionManager} was not specified using * {@link #accessDecisionManager(AccessDecisionManager)}. + * + * @param http the builder to use */ @Override @SuppressWarnings("rawtypes") - final List getDecisionVoters() { + final List getDecisionVoters(H http) { List decisionVoters = new ArrayList(); decisionVoters.add(new RoleVoter()); decisionVoters.add(new AuthenticatedVoter()); @@ -96,11 +98,12 @@ public final class UrlAuthorizationConfigurer, /** * Creates the {@link FilterInvocationSecurityMetadataSource} to use. The - * implementation is a {@link DefaultFilterInvocationSecurityMetadataSource} - * . + * implementation is a {@link DefaultFilterInvocationSecurityMetadataSource}. + * + * @param http the builder to use */ @Override - FilterInvocationSecurityMetadataSource createMetadataSource() { + FilterInvocationSecurityMetadataSource createMetadataSource(H http) { return new DefaultFilterInvocationSecurityMetadataSource(createRequestMap()); } diff --git a/config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.groovy b/config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.groovy index 225027b935..d1a9d6f4bd 100644 --- a/config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.groovy +++ b/config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.groovy @@ -18,22 +18,21 @@ package org.springframework.security.config.annotation.method.configuration import static org.fest.assertions.Assertions.assertThat import static org.junit.Assert.fail -import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInterceptor import org.springframework.context.ApplicationContext -import org.springframework.context.ApplicationListener; -import org.springframework.context.annotation.Configuration; +import org.springframework.context.ApplicationListener +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration import org.springframework.security.access.AccessDecisionManager -import org.springframework.security.access.AccessDeniedException -import org.springframework.security.access.ConfigAttribute +import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler +import org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter import org.springframework.security.authentication.AuthenticationManager +import org.springframework.security.authentication.AuthenticationTrustResolver import org.springframework.security.authentication.DefaultAuthenticationEventPublisher import org.springframework.security.authentication.UsernamePasswordAuthenticationToken -import org.springframework.security.authentication.event.AuthenticationSuccessEvent; +import org.springframework.security.authentication.event.AuthenticationSuccessEvent import org.springframework.security.config.annotation.BaseSpringSpec -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; -import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration; -import org.springframework.security.config.annotation.web.WebSecurityConfigurerAdapterTests.InMemoryAuthWithWebSecurityConfigurerAdapter +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder import org.springframework.security.core.Authentication import org.springframework.security.core.authority.AuthorityUtils @@ -82,4 +81,32 @@ public class GlobalMethodSecurityConfigurationTests extends BaseSpringSpec { 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 + } + + @Configuration + @EnableGlobalMethodSecurity(prePostEnabled = true) + static class CustomTrustResolverConfig extends GlobalMethodSecurityConfiguration { + static AuthenticationTrustResolver TR + + @Override + protected void registerAuthentication(AuthenticationManagerBuilder auth) + throws Exception { + auth + .inMemoryAuthentication() + } + + @Bean + public AuthenticationTrustResolver tr() { + return TR + } + } } diff --git a/config/src/test/groovy/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterTests.groovy b/config/src/test/groovy/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterTests.groovy index 090a83f6e4..6df4cc91e2 100644 --- a/config/src/test/groovy/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterTests.groovy +++ b/config/src/test/groovy/org/springframework/security/config/annotation/web/WebSecurityConfigurerAdapterTests.groovy @@ -29,6 +29,7 @@ import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.security.authentication.AuthenticationManager import org.springframework.security.authentication.AuthenticationProvider +import org.springframework.security.authentication.AuthenticationTrustResolver import org.springframework.security.authentication.DefaultAuthenticationEventPublisher import org.springframework.security.authentication.UsernamePasswordAuthenticationToken import org.springframework.security.authentication.event.AuthenticationSuccessEvent @@ -41,7 +42,7 @@ import org.springframework.security.core.Authentication import org.springframework.security.core.userdetails.UserDetailsService import org.springframework.security.core.userdetails.UsernameNotFoundException import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter -import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter; +import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter import org.springframework.web.accept.ContentNegotiationStrategy import org.springframework.web.accept.HeaderContentNegotiationStrategy import org.springframework.web.filter.OncePerRequestFilter @@ -266,4 +267,24 @@ class WebSecurityConfigurerAdapterTests extends BaseSpringSpec { 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 + } + + @Configuration + @EnableWebSecurity + static class CustomTrustResolverConfig extends WebSecurityConfigurerAdapter { + static AuthenticationTrustResolver TR + + @Bean + public AuthenticationTrustResolver tr() { + return TR + } + } } diff --git a/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurerTests.groovy b/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurerTests.groovy index b3f4a5ecfa..5a2d852b15 100644 --- a/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurerTests.groovy +++ b/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/ServletApiConfigurerTests.groovy @@ -18,6 +18,7 @@ package org.springframework.security.config.annotation.web.configurers import groovy.transform.CompileStatic import org.springframework.context.annotation.Configuration +import org.springframework.security.authentication.AuthenticationTrustResolver; import org.springframework.security.config.annotation.AnyObjectPostProcessor import org.springframework.security.config.annotation.BaseSpringSpec import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder @@ -132,4 +133,25 @@ class ServletApiConfigurerTests extends BaseSpringSpec { .exceptionHandling() } } + + def "use sharedObject trustResolver"() { + setup: + SharedTrustResolverConfig.TR = Mock(AuthenticationTrustResolver) + when: + loadConfig(SharedTrustResolverConfig) + then: + findFilter(SecurityContextHolderAwareRequestFilter).trustResolver == SharedTrustResolverConfig.TR + } + + @Configuration + @EnableWebSecurity + static class SharedTrustResolverConfig extends WebSecurityConfigurerAdapter { + static AuthenticationTrustResolver TR + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .setSharedObject(AuthenticationTrustResolver, TR) + } + } } diff --git a/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTests.groovy b/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTests.groovy index 9cb529ef5e..545cb95cb7 100644 --- a/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTests.groovy +++ b/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTests.groovy @@ -21,6 +21,7 @@ import org.springframework.context.annotation.Configuration import org.springframework.mock.web.MockFilterChain import org.springframework.mock.web.MockHttpServletRequest import org.springframework.mock.web.MockHttpServletResponse +import org.springframework.security.authentication.AuthenticationTrustResolver; import org.springframework.security.config.annotation.AnyObjectPostProcessor import org.springframework.security.config.annotation.BaseSpringSpec import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder @@ -217,4 +218,26 @@ class SessionManagementConfigurerTests extends BaseSpringSpec { and: "RegisterSessionAuthenticationStrategy is registered with ObjectPostProcessor" 1 * opp.postProcess(_ as RegisterSessionAuthenticationStrategy) >> {RegisterSessionAuthenticationStrategy o -> o} } + + def "use sharedObject trustResolver"() { + setup: + SharedTrustResolverConfig.TR = Mock(AuthenticationTrustResolver) + when: + loadConfig(SharedTrustResolverConfig) + then: + findFilter(SecurityContextPersistenceFilter).repo.trustResolver == SharedTrustResolverConfig.TR + findFilter(SessionManagementFilter).trustResolver == SharedTrustResolverConfig.TR + } + + @Configuration + @EnableWebSecurity + static class SharedTrustResolverConfig extends WebSecurityConfigurerAdapter { + static AuthenticationTrustResolver TR + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .setSharedObject(AuthenticationTrustResolver, TR) + } + } }