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:
parent
788ba9a1fa
commit
f294480e6b
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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_")) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue