SEC-879: Added required BeanPostProcessor to set SessionRegistry is set on namespace registered AbstractProcessingFilter and SessionFixationProtectionFilter when using custom ConcurrentSessionController
http://jira.springframework.org/browse/SEC-879.
This commit is contained in:
parent
d5ee89bb7c
commit
3ee8733261
|
@ -158,4 +158,8 @@ public class ConcurrentSessionControllerImpl implements ConcurrentSessionControl
|
|||
public void setSessionRegistry(SessionRegistry sessionRegistry) {
|
||||
this.sessionRegistry = sessionRegistry;
|
||||
}
|
||||
|
||||
public SessionRegistry getSessionRegistry() {
|
||||
return sessionRegistry;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.springframework.security.config;
|
||||
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
|
@ -36,6 +37,11 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition
|
|||
BeanIds.CONCURRENT_SESSION_CONTROLLER, element);
|
||||
authManager.getPropertyValues().addPropertyValue("sessionController",
|
||||
new RuntimeBeanReference(sessionControllerRef));
|
||||
RootBeanDefinition sessionRegistryInjector = new RootBeanDefinition(SessionRegistryInjectionBeanPostProcessor.class);
|
||||
sessionRegistryInjector.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
sessionRegistryInjector.getConstructorArgumentValues().addGenericArgumentValue(sessionControllerRef);
|
||||
|
||||
parserContext.getRegistry().registerBeanDefinition(BeanIds.SESSION_REGISTRY_INJECTION_POST_PROCESSOR, sessionRegistryInjector);
|
||||
}
|
||||
|
||||
parserContext.getRegistry().registerAlias(BeanIds.AUTHENTICATION_MANAGER, alias);
|
||||
|
|
|
@ -18,6 +18,7 @@ public abstract class BeanIds {
|
|||
static final String CONTEXT_SOURCE_SETTING_POST_PROCESSOR = "_contextSettingPostProcessor";
|
||||
static final String ENTRY_POINT_INJECTION_POST_PROCESSOR = "_entryPointInjectionBeanPostProcessor";
|
||||
static final String USER_DETAILS_SERVICE_INJECTION_POST_PROCESSOR = "_userServiceInjectionPostProcessor";
|
||||
static final String SESSION_REGISTRY_INJECTION_POST_PROCESSOR = "_sessionRegistryInjectionPostProcessor";
|
||||
static final String FILTER_CHAIN_POST_PROCESSOR = "_filterChainProxyPostProcessor";
|
||||
static final String FILTER_LIST = "_filterChainList";
|
||||
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
package org.springframework.security.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.security.concurrent.ConcurrentSessionController;
|
||||
import org.springframework.security.concurrent.ConcurrentSessionControllerImpl;
|
||||
import org.springframework.security.concurrent.SessionRegistry;
|
||||
import org.springframework.security.ui.AbstractProcessingFilter;
|
||||
import org.springframework.security.ui.SessionFixationProtectionFilter;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Registered by the <tt>AuthenticationManagerBeanDefinitionParser</tt> if an external
|
||||
* ConcurrentSessionController is set (and hence an external SessionRegistry).
|
||||
* Its responsibility is to set the SessionRegistry on namespace-registered beans which require access
|
||||
* to it.
|
||||
* <p>
|
||||
* It will attempt to read the registry directly from the registered controller. If that fails, it will look in
|
||||
* the application context for a registered SessionRegistry bean.
|
||||
*
|
||||
* See SEC-879.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 2.0.3
|
||||
*/
|
||||
class SessionRegistryInjectionBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private ListableBeanFactory beanFactory;
|
||||
private SessionRegistry sessionRegistry;
|
||||
private final String controllerBeanName;
|
||||
|
||||
SessionRegistryInjectionBeanPostProcessor(String controllerBeanName) {
|
||||
this.controllerBeanName = controllerBeanName;
|
||||
}
|
||||
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (BeanIds.FORM_LOGIN_FILTER.equals(beanName) ||
|
||||
BeanIds.OPEN_ID_FILTER.equals(beanName)) {
|
||||
((AbstractProcessingFilter) bean).setSessionRegistry(getSessionRegistry());
|
||||
} else if (BeanIds.SESSION_FIXATION_PROTECTION_FILTER.equals(beanName)) {
|
||||
((SessionFixationProtectionFilter)bean).setSessionRegistry(getSessionRegistry());
|
||||
}
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
private SessionRegistry getSessionRegistry() {
|
||||
if (sessionRegistry != null) {
|
||||
return sessionRegistry;
|
||||
}
|
||||
|
||||
logger.info("Attempting to read SessionRegistry from registered ConcurrentSessionController bean");
|
||||
|
||||
ConcurrentSessionController controller = (ConcurrentSessionController) beanFactory.getBean(controllerBeanName);
|
||||
|
||||
if (controller instanceof ConcurrentSessionControllerImpl) {
|
||||
sessionRegistry = ((ConcurrentSessionControllerImpl)controller).getSessionRegistry();
|
||||
|
||||
return sessionRegistry;
|
||||
}
|
||||
|
||||
logger.info("ConcurrentSessionController is not a standard implementation. SessionRegistry could not be read from it. Looking for it in the context.");
|
||||
|
||||
List sessionRegs = new ArrayList(beanFactory.getBeansOfType(SessionRegistry.class).values());
|
||||
|
||||
if (sessionRegs.size() == 0) {
|
||||
throw new SecurityConfigurationException("concurrent-session-controller-ref was set but no SessionRegistry could be obtained from the application context.");
|
||||
}
|
||||
|
||||
if (sessionRegs.size() > 1) {
|
||||
logger.warn("More than one SessionRegistry instance in application context. Possible configuration errors may result.");
|
||||
}
|
||||
|
||||
sessionRegistry = (SessionRegistry) sessionRegs.get(0);
|
||||
|
||||
return sessionRegistry;
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = (ListableBeanFactory) beanFactory;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package org.springframework.security.config;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.support.AbstractXmlApplicationContext;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.AuthenticationException;
|
||||
import org.springframework.security.concurrent.ConcurrentSessionController;
|
||||
import org.springframework.security.util.FieldUtils;
|
||||
import org.springframework.security.util.InMemoryXmlApplicationContext;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
public class SessionRegistryInjectionBeanPostProcessorTests {
|
||||
private AbstractXmlApplicationContext appContext;
|
||||
|
||||
@After
|
||||
public void closeAppContext() {
|
||||
if (appContext != null) {
|
||||
appContext.close();
|
||||
appContext = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void setContext(String context) {
|
||||
appContext = new InMemoryXmlApplicationContext(context);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sessionRegistryIsSetOnFiltersWhenUsingCustomControllerWithInternalRegistryBean() throws Exception {
|
||||
setContext(
|
||||
"<http auto-config='true'/>" +
|
||||
"<b:bean id='sc' class='org.springframework.security.concurrent.ConcurrentSessionControllerImpl'>" +
|
||||
" <b:property name='sessionRegistry'>" +
|
||||
" <b:bean class='org.springframework.security.concurrent.SessionRegistryImpl'/>" +
|
||||
" </b:property>" +
|
||||
"</b:bean>" +
|
||||
"<authentication-manager alias='authManager' session-controller-ref='sc'/>" +
|
||||
HttpSecurityBeanDefinitionParserTests.AUTH_PROVIDER_XML);
|
||||
assertNotNull(FieldUtils.getFieldValue(appContext.getBean(BeanIds.SESSION_FIXATION_PROTECTION_FILTER), "sessionRegistry"));
|
||||
assertNotNull(FieldUtils.getFieldValue(appContext.getBean(BeanIds.FORM_LOGIN_FILTER), "sessionRegistry"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sessionRegistryIsSetOnFiltersWhenUsingCustomControllerWithNonStandardController() throws Exception {
|
||||
setContext(
|
||||
"<http auto-config='true'/>" +
|
||||
"<b:bean id='sc' class='org.springframework.security.config.SessionRegistryInjectionBeanPostProcessorTests$MockConcurrentSessionController'/>" +
|
||||
"<b:bean id='sessionRegistry' class='org.springframework.security.concurrent.SessionRegistryImpl'/>" +
|
||||
"<authentication-manager alias='authManager' session-controller-ref='sc'/>" +
|
||||
HttpSecurityBeanDefinitionParserTests.AUTH_PROVIDER_XML);
|
||||
assertNotNull(FieldUtils.getFieldValue(appContext.getBean(BeanIds.SESSION_FIXATION_PROTECTION_FILTER), "sessionRegistry"));
|
||||
assertNotNull(FieldUtils.getFieldValue(appContext.getBean(BeanIds.FORM_LOGIN_FILTER), "sessionRegistry"));
|
||||
}
|
||||
|
||||
public static class MockConcurrentSessionController implements ConcurrentSessionController {
|
||||
public void checkAuthenticationAllowed(Authentication request) throws AuthenticationException {
|
||||
}
|
||||
public void registerSuccessfulAuthentication(Authentication authentication) {
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue