mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-07-12 05:13:33 +00:00
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) {
|
public void setSessionRegistry(SessionRegistry sessionRegistry) {
|
||||||
this.sessionRegistry = sessionRegistry;
|
this.sessionRegistry = sessionRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SessionRegistry getSessionRegistry() {
|
||||||
|
return sessionRegistry;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.springframework.security.config;
|
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.BeanDefinitionParser;
|
||||||
import org.springframework.beans.factory.xml.ParserContext;
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
@ -36,6 +37,11 @@ public class AuthenticationManagerBeanDefinitionParser implements BeanDefinition
|
|||||||
BeanIds.CONCURRENT_SESSION_CONTROLLER, element);
|
BeanIds.CONCURRENT_SESSION_CONTROLLER, element);
|
||||||
authManager.getPropertyValues().addPropertyValue("sessionController",
|
authManager.getPropertyValues().addPropertyValue("sessionController",
|
||||||
new RuntimeBeanReference(sessionControllerRef));
|
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);
|
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 CONTEXT_SOURCE_SETTING_POST_PROCESSOR = "_contextSettingPostProcessor";
|
||||||
static final String ENTRY_POINT_INJECTION_POST_PROCESSOR = "_entryPointInjectionBeanPostProcessor";
|
static final String ENTRY_POINT_INJECTION_POST_PROCESSOR = "_entryPointInjectionBeanPostProcessor";
|
||||||
static final String USER_DETAILS_SERVICE_INJECTION_POST_PROCESSOR = "_userServiceInjectionPostProcessor";
|
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_CHAIN_POST_PROCESSOR = "_filterChainProxyPostProcessor";
|
||||||
static final String FILTER_LIST = "_filterChainList";
|
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…
x
Reference in New Issue
Block a user