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.
This commit is contained in:
Rob Winch 2013-09-20 15:28:50 -05:00
parent 788ba9a1fa
commit f294480e6b
11 changed files with 200 additions and 44 deletions

View File

@ -62,6 +62,7 @@ import org.springframework.security.access.vote.AffirmativeBased;
import org.springframework.security.access.vote.AuthenticatedVoter; import org.springframework.security.access.vote.AuthenticatedVoter;
import org.springframework.security.access.vote.RoleVoter; import org.springframework.security.access.vote.RoleVoter;
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher; import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
import org.springframework.security.config.annotation.ObjectPostProcessor; import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 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()); 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 AuthenticationManager authenticationManager;
private AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR); private AuthenticationManagerBuilder auth = new AuthenticationManagerBuilder(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR);
private boolean disableAuthenticationRegistry; private boolean disableAuthenticationRegistry;
@ -192,16 +194,20 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
} }
/** /**
* Provide a {@link MethodSecurityExpressionHandler} that is * Provide a {@link MethodSecurityExpressionHandler} that is registered with
* registered with the {@link ExpressionBasedPreInvocationAdvice}. The default is * the {@link ExpressionBasedPreInvocationAdvice}. The default is
* {@link DefaultMethodSecurityExpressionHandler} * {@link DefaultMethodSecurityExpressionHandler} which optionally will
* Autowire an {@link AuthenticationTrustResolver}.
* *
* <p>Subclasses may override this method to provide a custom {@link MethodSecurityExpressionHandler}</p> * <p>
* Subclasses may override this method to provide a custom
* {@link MethodSecurityExpressionHandler}
* </p>
* *
* @return * @return
*/ */
protected MethodSecurityExpressionHandler expressionHandler() { protected MethodSecurityExpressionHandler expressionHandler() {
return new DefaultMethodSecurityExpressionHandler(); return defaultMethodExpressionHandler;
} }
/** /**
@ -339,6 +345,11 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
.fromMap(annotationAttributes); .fromMap(annotationAttributes);
} }
@Autowired(required = false)
public void setAuthenticationTrustResolver(AuthenticationTrustResolver trustResolver) {
this.defaultMethodExpressionHandler.setTrustResolver(trustResolver);
}
@Autowired @Autowired
public void setApplicationContext(ApplicationContext context) { public void setApplicationContext(ApplicationContext context) {
this.context = context; this.context = context;

View File

@ -24,6 +24,8 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.security.authentication.AuthenticationManager; 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.authentication.DefaultAuthenticationEventPublisher;
import org.springframework.security.config.annotation.ObjectPostProcessor; import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.SecurityConfigurer; import org.springframework.security.config.annotation.SecurityConfigurer;
@ -76,6 +78,7 @@ public abstract class WebSecurityConfigurerAdapter implements SecurityConfigurer
private boolean disableAuthenticationRegistration; private boolean disableAuthenticationRegistration;
private boolean authenticationManagerInitialized; private boolean authenticationManagerInitialized;
private AuthenticationManager authenticationManager; private AuthenticationManager authenticationManager;
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
private HttpSecurity http; private HttpSecurity http;
private boolean disableDefaults; private boolean disableDefaults;
@ -153,6 +156,7 @@ public abstract class WebSecurityConfigurerAdapter implements SecurityConfigurer
http.setSharedObject(UserDetailsService.class, userDetailsService()); http.setSharedObject(UserDetailsService.class, userDetailsService());
http.setSharedObject(ApplicationContext.class, context); http.setSharedObject(ApplicationContext.class, context);
http.setSharedObject(ContentNegotiationStrategy.class, contentNegotiationStrategy); http.setSharedObject(ContentNegotiationStrategy.class, contentNegotiationStrategy);
http.setSharedObject(AuthenticationTrustResolver.class, trustResolver);
if(!disableDefaults) { if(!disableDefaults) {
http http
.csrf().and() .csrf().and()
@ -312,6 +316,11 @@ public abstract class WebSecurityConfigurerAdapter implements SecurityConfigurer
this.context = context; this.context = context;
} }
@Autowired(required=false)
public void setTrustResolver(AuthenticationTrustResolver trustResolver) {
this.trustResolver = trustResolver;
}
@Autowired(required=false) @Autowired(required=false)
public void setContentNegotationStrategy(ContentNegotiationStrategy contentNegotiationStrategy) { public void setContentNegotationStrategy(ContentNegotiationStrategy contentNegotiationStrategy) {
this.contentNegotiationStrategy = contentNegotiationStrategy; this.contentNegotiationStrategy = contentNegotiationStrategy;

View File

@ -98,11 +98,11 @@ abstract class AbstractInterceptUrlConfigurer<H extends HttpSecurityBuilder<H>,C
@Override @Override
public void configure(H http) throws Exception { public void configure(H http) throws Exception {
FilterInvocationSecurityMetadataSource metadataSource = createMetadataSource(); FilterInvocationSecurityMetadataSource metadataSource = createMetadataSource(http);
if(metadataSource == null) { if(metadataSource == null) {
return; return;
} }
FilterSecurityInterceptor securityInterceptor = createFilterSecurityInterceptor(metadataSource, http.getSharedObject(AuthenticationManager.class)); FilterSecurityInterceptor securityInterceptor = createFilterSecurityInterceptor(http, metadataSource, http.getSharedObject(AuthenticationManager.class));
if(filterSecurityInterceptorOncePerRequest != null) { if(filterSecurityInterceptorOncePerRequest != null) {
securityInterceptor.setObserveOncePerRequest(filterSecurityInterceptorOncePerRequest); securityInterceptor.setObserveOncePerRequest(filterSecurityInterceptorOncePerRequest);
} }
@ -115,38 +115,44 @@ abstract class AbstractInterceptUrlConfigurer<H extends HttpSecurityBuilder<H>,C
* Subclasses should implement this method to provide a {@link FilterInvocationSecurityMetadataSource} for the * Subclasses should implement this method to provide a {@link FilterInvocationSecurityMetadataSource} for the
* {@link FilterSecurityInterceptor}. * {@link FilterSecurityInterceptor}.
* *
* @param http the builder to use
*
* @return the {@link FilterInvocationSecurityMetadataSource} to set on the {@link FilterSecurityInterceptor}. * @return the {@link FilterInvocationSecurityMetadataSource} to set on the {@link FilterSecurityInterceptor}.
* Cannot be null. * 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 * Subclasses should implement this method to provide the {@link AccessDecisionVoter} instances used to create the
* default {@link AccessDecisionManager} * default {@link AccessDecisionManager}
* *
* @param http the builder to use
*
* @return the {@link AccessDecisionVoter} instances used to create the * @return the {@link AccessDecisionVoter} instances used to create the
* default {@link AccessDecisionManager} * default {@link AccessDecisionManager}
*/ */
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
abstract List<AccessDecisionVoter> getDecisionVoters(); abstract List<AccessDecisionVoter> getDecisionVoters(H http);
/** /**
* Creates the default {@code AccessDecisionManager} * Creates the default {@code AccessDecisionManager}
* @return the default {@code AccessDecisionManager} * @return the default {@code AccessDecisionManager}
*/ */
private AccessDecisionManager createDefaultAccessDecisionManager() { private AccessDecisionManager createDefaultAccessDecisionManager(H http) {
return new AffirmativeBased(getDecisionVoters()); return new AffirmativeBased(getDecisionVoters(http));
} }
/** /**
* If currently null, creates a default {@link AccessDecisionManager} using * If currently null, creates a default {@link AccessDecisionManager} using
* {@link #createDefaultAccessDecisionManager()}. Otherwise returns the {@link AccessDecisionManager}. * {@link #createDefaultAccessDecisionManager()}. Otherwise returns the {@link AccessDecisionManager}.
* *
* @param http the builder to use
*
* @return the {@link AccessDecisionManager} to use * @return the {@link AccessDecisionManager} to use
*/ */
private AccessDecisionManager getAccessDecisionManager() { private AccessDecisionManager getAccessDecisionManager(H http) {
if (accessDecisionManager == null) { if (accessDecisionManager == null) {
accessDecisionManager = createDefaultAccessDecisionManager(); accessDecisionManager = createDefaultAccessDecisionManager(http);
} }
return accessDecisionManager; return accessDecisionManager;
} }
@ -154,16 +160,17 @@ abstract class AbstractInterceptUrlConfigurer<H extends HttpSecurityBuilder<H>,C
/** /**
* Creates the {@link FilterSecurityInterceptor} * Creates the {@link FilterSecurityInterceptor}
* *
* @param http the builder to use
* @param metadataSource the {@link FilterInvocationSecurityMetadataSource} to use * @param metadataSource the {@link FilterInvocationSecurityMetadataSource} to use
* @param authenticationManager the {@link AuthenticationManager} to use * @param authenticationManager the {@link AuthenticationManager} to use
* @return the {@link FilterSecurityInterceptor} * @return the {@link FilterSecurityInterceptor}
* @throws Exception * @throws Exception
*/ */
private FilterSecurityInterceptor createFilterSecurityInterceptor(FilterInvocationSecurityMetadataSource metadataSource, private FilterSecurityInterceptor createFilterSecurityInterceptor(H http, FilterInvocationSecurityMetadataSource metadataSource,
AuthenticationManager authenticationManager) throws Exception { AuthenticationManager authenticationManager) throws Exception {
FilterSecurityInterceptor securityInterceptor = new FilterSecurityInterceptor(); FilterSecurityInterceptor securityInterceptor = new FilterSecurityInterceptor();
securityInterceptor.setSecurityMetadataSource(metadataSource); securityInterceptor.setSecurityMetadataSource(metadataSource);
securityInterceptor.setAccessDecisionManager(getAccessDecisionManager()); securityInterceptor.setAccessDecisionManager(getAccessDecisionManager(http));
securityInterceptor.setAuthenticationManager(authenticationManager); securityInterceptor.setAuthenticationManager(authenticationManager);
securityInterceptor.afterPropertiesSet(); securityInterceptor.afterPropertiesSet();
return securityInterceptor; return securityInterceptor;

View File

@ -24,6 +24,7 @@ import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig; import org.springframework.security.access.SecurityConfig;
import org.springframework.security.access.expression.SecurityExpressionHandler; 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.ObjectPostProcessor;
import org.springframework.security.config.annotation.web.HttpSecurityBuilder; import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@ -56,7 +57,9 @@ import org.springframework.util.StringUtils;
* *
* <h2>Shared Objects Used</h2> * <h2>Shared Objects Used</h2>
* *
* No shared objects are used. * <ul>
* <li>{@link AuthenticationTrustResolver} is optionally used to populate the {@link DefaultWebSecurityExpressionHandler}</li>
* </ul>
* *
* @param <H> the type of {@link HttpSecurityBuilder} that is being configured * @param <H> the type of {@link HttpSecurityBuilder} that is being configured
* *
@ -72,7 +75,7 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
private static final String fullyAuthenticated = "fullyAuthenticated"; private static final String fullyAuthenticated = "fullyAuthenticated";
private static final String rememberMe = "rememberMe"; private static final String rememberMe = "rememberMe";
private SecurityExpressionHandler<FilterInvocation> expressionHandler = new DefaultWebSecurityExpressionHandler(); private SecurityExpressionHandler<FilterInvocation> expressionHandler;
/** /**
* Creates a new instance * Creates a new instance
@ -110,21 +113,21 @@ public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBu
@Override @Override
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
final List<AccessDecisionVoter> getDecisionVoters() { final List<AccessDecisionVoter> getDecisionVoters(H http) {
List<AccessDecisionVoter> decisionVoters = new ArrayList<AccessDecisionVoter>(); List<AccessDecisionVoter> decisionVoters = new ArrayList<AccessDecisionVoter>();
WebExpressionVoter expressionVoter = new WebExpressionVoter(); WebExpressionVoter expressionVoter = new WebExpressionVoter();
expressionVoter.setExpressionHandler(expressionHandler); expressionVoter.setExpressionHandler(getExpressionHandler(http));
decisionVoters.add(expressionVoter); decisionVoters.add(expressionVoter);
return decisionVoters; return decisionVoters;
} }
@Override @Override
final ExpressionBasedFilterInvocationSecurityMetadataSource createMetadataSource() { final ExpressionBasedFilterInvocationSecurityMetadataSource createMetadataSource(H http) {
LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = createRequestMap(); LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = createRequestMap();
if(requestMap.isEmpty()) { if(requestMap.isEmpty()) {
throw new IllegalStateException("At least one mapping is required (i.e. authorizeRequests().anyRequest.authenticated())"); 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<H extends HttpSecurityBu
return this; return this;
} }
private SecurityExpressionHandler<FilterInvocation> 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) { private static String hasRole(String role) {
Assert.notNull(role, "role cannot be null"); Assert.notNull(role, "role cannot be null");
if (role.startsWith("ROLE_")) { if (role.startsWith("ROLE_")) {

View File

@ -20,6 +20,7 @@ import java.util.List;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.springframework.security.authentication.AuthenticationManager; 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.HttpSecurityBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContext;
@ -45,7 +46,9 @@ import org.springframework.security.web.servletapi.SecurityContextHolderAwareReq
* *
* <h2>Shared Objects Used</h2> * <h2>Shared Objects Used</h2>
* *
* No shared Objects are used. * <ul>
* <li>{@link AuthenticationTrustResolver} is optionally used to populate the {@link SecurityContextHolderAwareRequestFilter}</li>
* </ul>
* *
* @author Rob Winch * @author Rob Winch
* @since 3.2 * @since 3.2
@ -75,6 +78,10 @@ public final class ServletApiConfigurer<H extends HttpSecurityBuilder<H>> extend
LogoutConfigurer<H> logoutConf = http.getConfigurer(LogoutConfigurer.class); LogoutConfigurer<H> logoutConf = http.getConfigurer(LogoutConfigurer.class);
List<LogoutHandler> logoutHandlers = logoutConf == null ? null : logoutConf.getLogoutHandlers(); List<LogoutHandler> logoutHandlers = logoutConf == null ? null : logoutConf.getLogoutHandlers();
securityContextRequestFilter.setLogoutHandlers(logoutHandlers); securityContextRequestFilter.setLogoutHandlers(logoutHandlers);
AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class);
if(trustResolver != null) {
securityContextRequestFilter.setTrustResolver(trustResolver);
}
securityContextRequestFilter = postProcess(securityContextRequestFilter); securityContextRequestFilter = postProcess(securityContextRequestFilter);
http.addFilter(securityContextRequestFilter); http.addFilter(securityContextRequestFilter);
} }

View File

@ -22,6 +22,7 @@ import java.util.List;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; 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.HttpSecurityBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.config.http.SessionCreationPolicy;
@ -71,6 +72,7 @@ import org.springframework.util.Assert;
* *
* <ul> * <ul>
* <li>{@link SecurityContextRepository}</li> * <li>{@link SecurityContextRepository}</li>
* <li>{@link AuthenticationTrustResolver} is optionally used to populate the {@link HttpSessionSecurityContextRepository} and {@link SessionManagementFilter}</li>
* </ul> * </ul>
* *
* @author Rob Winch * @author Rob Winch
@ -337,28 +339,32 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
} }
@Override @Override
public void init(H builder) throws Exception { public void init(H http) throws Exception {
SecurityContextRepository securityContextRepository = builder.getSharedObject(SecurityContextRepository.class); SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class);
boolean stateless = isStateless(); boolean stateless = isStateless();
if(securityContextRepository == null) { if(securityContextRepository == null) {
if(stateless) { if(stateless) {
builder.setSharedObject(SecurityContextRepository.class, new NullSecurityContextRepository()); http.setSharedObject(SecurityContextRepository.class, new NullSecurityContextRepository());
} else { } else {
HttpSessionSecurityContextRepository httpSecurityRepository = new HttpSessionSecurityContextRepository(); HttpSessionSecurityContextRepository httpSecurityRepository = new HttpSessionSecurityContextRepository();
httpSecurityRepository.setDisableUrlRewriting(!enableSessionUrlRewriting); httpSecurityRepository.setDisableUrlRewriting(!enableSessionUrlRewriting);
httpSecurityRepository.setAllowSessionCreation(isAllowSessionCreation()); 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(requestCache == null) {
if(stateless) { 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 @Override
@ -371,6 +377,10 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
if(invalidSessionUrl != null) { if(invalidSessionUrl != null) {
sessionManagementFilter.setInvalidSessionStrategy(new SimpleRedirectInvalidSessionStrategy(invalidSessionUrl)); sessionManagementFilter.setInvalidSessionStrategy(new SimpleRedirectInvalidSessionStrategy(invalidSessionUrl));
} }
AuthenticationTrustResolver trustResolver = http.getSharedObject(AuthenticationTrustResolver.class);
if(trustResolver != null) {
sessionManagementFilter.setTrustResolver(trustResolver);
}
sessionManagementFilter = postProcess(sessionManagementFilter); sessionManagementFilter = postProcess(sessionManagementFilter);
http.addFilter(sessionManagementFilter); http.addFilter(sessionManagementFilter);

View File

@ -84,10 +84,12 @@ public final class UrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>,
* Creates the default {@link AccessDecisionVoter} instances used if an * Creates the default {@link AccessDecisionVoter} instances used if an
* {@link AccessDecisionManager} was not specified using * {@link AccessDecisionManager} was not specified using
* {@link #accessDecisionManager(AccessDecisionManager)}. * {@link #accessDecisionManager(AccessDecisionManager)}.
*
* @param http the builder to use
*/ */
@Override @Override
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
final List<AccessDecisionVoter> getDecisionVoters() { final List<AccessDecisionVoter> getDecisionVoters(H http) {
List<AccessDecisionVoter> decisionVoters = new ArrayList<AccessDecisionVoter>(); List<AccessDecisionVoter> decisionVoters = new ArrayList<AccessDecisionVoter>();
decisionVoters.add(new RoleVoter()); decisionVoters.add(new RoleVoter());
decisionVoters.add(new AuthenticatedVoter()); decisionVoters.add(new AuthenticatedVoter());
@ -96,11 +98,12 @@ public final class UrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>,
/** /**
* Creates the {@link FilterInvocationSecurityMetadataSource} to use. The * Creates the {@link FilterInvocationSecurityMetadataSource} to use. The
* implementation is a {@link DefaultFilterInvocationSecurityMetadataSource} * implementation is a {@link DefaultFilterInvocationSecurityMetadataSource}.
* . *
* @param http the builder to use
*/ */
@Override @Override
FilterInvocationSecurityMetadataSource createMetadataSource() { FilterInvocationSecurityMetadataSource createMetadataSource(H http) {
return new DefaultFilterInvocationSecurityMetadataSource(createRequestMap()); return new DefaultFilterInvocationSecurityMetadataSource(createRequestMap());
} }

View File

@ -18,22 +18,21 @@ package org.springframework.security.config.annotation.method.configuration
import static org.fest.assertions.Assertions.assertThat import static org.fest.assertions.Assertions.assertThat
import static org.junit.Assert.fail 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.ApplicationContext
import org.springframework.context.ApplicationListener; import org.springframework.context.ApplicationListener
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.access.AccessDecisionManager import org.springframework.security.access.AccessDecisionManager
import org.springframework.security.access.AccessDeniedException import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler
import org.springframework.security.access.ConfigAttribute import org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter
import org.springframework.security.authentication.AuthenticationManager import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.authentication.AuthenticationTrustResolver
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher import org.springframework.security.authentication.DefaultAuthenticationEventPublisher
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken 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.BaseSpringSpec
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 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.core.Authentication import org.springframework.security.core.Authentication
import org.springframework.security.core.authority.AuthorityUtils import org.springframework.security.core.authority.AuthorityUtils
@ -82,4 +81,32 @@ public class GlobalMethodSecurityConfigurationTests extends BaseSpringSpec {
AuthenticationManager getAuthenticationManager() { AuthenticationManager getAuthenticationManager() {
context.getBean(MethodInterceptor).authenticationManager 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
}
}
} }

View File

@ -29,6 +29,7 @@ import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration import org.springframework.context.annotation.Configuration
import org.springframework.security.authentication.AuthenticationManager import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.authentication.AuthenticationProvider import org.springframework.security.authentication.AuthenticationProvider
import org.springframework.security.authentication.AuthenticationTrustResolver
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher import org.springframework.security.authentication.DefaultAuthenticationEventPublisher
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.authentication.event.AuthenticationSuccessEvent 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.UserDetailsService
import org.springframework.security.core.userdetails.UsernameNotFoundException import org.springframework.security.core.userdetails.UsernameNotFoundException
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter 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.ContentNegotiationStrategy
import org.springframework.web.accept.HeaderContentNegotiationStrategy import org.springframework.web.accept.HeaderContentNegotiationStrategy
import org.springframework.web.filter.OncePerRequestFilter import org.springframework.web.filter.OncePerRequestFilter
@ -266,4 +267,24 @@ class WebSecurityConfigurerAdapterTests extends BaseSpringSpec {
chain.doFilter(request,response) 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
}
}
} }

View File

@ -18,6 +18,7 @@ package org.springframework.security.config.annotation.web.configurers
import groovy.transform.CompileStatic import groovy.transform.CompileStatic
import org.springframework.context.annotation.Configuration 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.AnyObjectPostProcessor
import org.springframework.security.config.annotation.BaseSpringSpec import org.springframework.security.config.annotation.BaseSpringSpec
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
@ -132,4 +133,25 @@ class ServletApiConfigurerTests extends BaseSpringSpec {
.exceptionHandling() .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)
}
}
} }

View File

@ -21,6 +21,7 @@ import org.springframework.context.annotation.Configuration
import org.springframework.mock.web.MockFilterChain import org.springframework.mock.web.MockFilterChain
import org.springframework.mock.web.MockHttpServletRequest import org.springframework.mock.web.MockHttpServletRequest
import org.springframework.mock.web.MockHttpServletResponse 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.AnyObjectPostProcessor
import org.springframework.security.config.annotation.BaseSpringSpec import org.springframework.security.config.annotation.BaseSpringSpec
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
@ -217,4 +218,26 @@ class SessionManagementConfigurerTests extends BaseSpringSpec {
and: "RegisterSessionAuthenticationStrategy is registered with ObjectPostProcessor" and: "RegisterSessionAuthenticationStrategy is registered with ObjectPostProcessor"
1 * opp.postProcess(_ as RegisterSessionAuthenticationStrategy) >> {RegisterSessionAuthenticationStrategy o -> o} 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)
}
}
} }