SEC-1893: Namespace now register PortMapper with custom mappings for all components that use a PortMapper

This commit is contained in:
Rob Winch 2012-03-11 20:52:17 -05:00
parent 84141c4c76
commit f78c11650f
5 changed files with 69 additions and 16 deletions

View File

@ -47,6 +47,7 @@ import java.util.*;
* Handles creation of authentication mechanism filters and related beans for <http> parsing.
*
* @author Luke Taylor
* @author Rob Winch
* @since 3.0
*/
final class AuthenticationConfigBuilder {
@ -102,15 +103,19 @@ final class AuthenticationConfigBuilder {
private BeanDefinition loginPageGenerationFilter;
private BeanDefinition etf;
private final BeanReference requestCache;
private final BeanReference portMapper;
private final BeanReference portResolver;
public AuthenticationConfigBuilder(Element element, ParserContext pc, SessionCreationPolicy sessionPolicy,
BeanReference requestCache, BeanReference authenticationManager, BeanReference sessionStrategy) {
BeanReference requestCache, BeanReference authenticationManager, BeanReference sessionStrategy, BeanReference portMapper, BeanReference portResolver) {
this.httpElt = element;
this.pc = pc;
this.requestCache = requestCache;
autoConfig = "true".equals(element.getAttribute(ATT_AUTO_CONFIG));
this.allowSessionCreation = sessionPolicy != SessionCreationPolicy.never
&& sessionPolicy != SessionCreationPolicy.stateless;
this.portMapper = portMapper;
this.portResolver = portResolver;
createAnonymousFilter();
createRememberMeFilter(authenticationManager);
@ -164,7 +169,7 @@ final class AuthenticationConfigBuilder {
if (formLoginElt != null || autoConfig) {
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_security_check",
AUTHENTICATION_PROCESSING_FILTER_CLASS, requestCache, sessionStrategy, allowSessionCreation);
AUTHENTICATION_PROCESSING_FILTER_CLASS, requestCache, sessionStrategy, allowSessionCreation, portMapper, portResolver);
parser.parse(formLoginElt, pc);
formFilter = parser.getFilterBean();
@ -188,7 +193,7 @@ final class AuthenticationConfigBuilder {
if (openIDLoginElt != null) {
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_openid_security_check",
OPEN_ID_AUTHENTICATION_PROCESSING_FILTER_CLASS, requestCache, sessionStrategy, allowSessionCreation);
OPEN_ID_AUTHENTICATION_PROCESSING_FILTER_CLASS, requestCache, sessionStrategy, allowSessionCreation, portMapper, portResolver);
parser.parse(openIDLoginElt, pc);
openIDFilter = parser.getFilterBean();

View File

@ -17,6 +17,7 @@ import org.w3c.dom.Element;
/**
* @author Luke Taylor
* @author Ben Alex
* @author Rob Winch
*/
public class FormLoginBeanDefinitionParser {
protected final Log logger = LogFactory.getLog(getClass());
@ -44,18 +45,22 @@ public class FormLoginBeanDefinitionParser {
private final BeanReference requestCache;
private final BeanReference sessionStrategy;
private final boolean allowSessionCreation;
private final BeanReference portMapper;
private final BeanReference portResolver;
private RootBeanDefinition filterBean;
private RootBeanDefinition entryPointBean;
private String loginPage;
FormLoginBeanDefinitionParser(String defaultLoginProcessingUrl, String filterClassName,
BeanReference requestCache, BeanReference sessionStrategy, boolean allowSessionCreation) {
BeanReference requestCache, BeanReference sessionStrategy, boolean allowSessionCreation, BeanReference portMapper, BeanReference portResolver) {
this.defaultLoginProcessingUrl = defaultLoginProcessingUrl;
this.filterClassName = filterClassName;
this.requestCache = requestCache;
this.sessionStrategy = sessionStrategy;
this.allowSessionCreation = allowSessionCreation;
this.portMapper = portMapper;
this.portResolver = portResolver;
}
public BeanDefinition parse(Element elt, ParserContext pc) {
@ -111,6 +116,8 @@ public class FormLoginBeanDefinitionParser {
BeanDefinitionBuilder.rootBeanDefinition(LoginUrlAuthenticationEntryPoint.class);
entryPointBuilder.getRawBeanDefinition().setSource(source);
entryPointBuilder.addPropertyValue("loginFormUrl", loginPage != null ? loginPage : DEF_LOGIN_PAGE);
entryPointBuilder.addPropertyValue("portMapper", portMapper);
entryPointBuilder.addPropertyValue("portResolver", portResolver);
entryPointBean = (RootBeanDefinition) entryPointBuilder.getBeanDefinition();
return null;

View File

@ -55,6 +55,7 @@ import org.w3c.dom.Element;
* Stateful class which helps HttpSecurityBDP to create the configuration for the <http> element.
*
* @author Luke Taylor
* @author Rob Winch
* @since 3.0
*/
class HttpConfigurationBuilder {
@ -92,16 +93,18 @@ class HttpConfigurationBuilder {
private RootBeanDefinition sfpf;
private BeanDefinition servApiFilter;
private BeanDefinition jaasApiFilter;
private final String portMapperName;
private final BeanReference portMapper;
private final BeanReference portResolver;
private BeanReference fsi;
private BeanReference requestCache;
public HttpConfigurationBuilder(Element element, ParserContext pc,
String portMapperName, BeanReference authenticationManager) {
BeanReference portMapper, BeanReference portResolver, BeanReference authenticationManager) {
this.httpElt = element;
this.pc = pc;
this.portMapperName = portMapperName;
this.portMapper = portMapper;
this.portResolver = portResolver;
this.matcherType = MatcherType.fromElement(element);
interceptUrls = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_URL);
@ -374,9 +377,11 @@ class HttpConfigurationBuilder {
RootBeanDefinition secureChannelProcessor = new RootBeanDefinition(SecureChannelProcessor.class);
RootBeanDefinition retryWithHttp = new RootBeanDefinition(RetryWithHttpEntryPoint.class);
RootBeanDefinition retryWithHttps = new RootBeanDefinition(RetryWithHttpsEntryPoint.class);
RuntimeBeanReference portMapper = new RuntimeBeanReference(portMapperName);
retryWithHttp.getPropertyValues().addPropertyValue("portMapper", portMapper);
retryWithHttp.getPropertyValues().addPropertyValue("portResolver", portResolver);
retryWithHttps.getPropertyValues().addPropertyValue("portMapper", portMapper);
retryWithHttps.getPropertyValues().addPropertyValue("portResolver", portResolver);
secureChannelProcessor.getPropertyValues().addPropertyValue("entryPoint", retryWithHttps);
RootBeanDefinition inSecureChannelProcessor = new RootBeanDefinition(InsecureChannelProcessor.class);
inSecureChannelProcessor.getPropertyValues().addPropertyValue("entryPoint", retryWithHttp);
@ -433,10 +438,8 @@ class HttpConfigurationBuilder {
requestCacheBldr = BeanDefinitionBuilder.rootBeanDefinition(NullRequestCache.class);
} else {
requestCacheBldr = BeanDefinitionBuilder.rootBeanDefinition(HttpSessionRequestCache.class);
BeanDefinitionBuilder portResolver = BeanDefinitionBuilder.rootBeanDefinition(PortResolverImpl.class);
portResolver.addPropertyReference("portMapper", portMapperName);
requestCacheBldr.addPropertyValue("createSessionAllowed", sessionPolicy == SessionCreationPolicy.ifRequired);
requestCacheBldr.addPropertyValue("portResolver", portResolver.getBeanDefinition());
requestCacheBldr.addPropertyValue("portResolver", portResolver);
}
BeanDefinition bean = requestCacheBldr.getBeanDefinition();

View File

@ -23,6 +23,7 @@ import org.springframework.security.config.Elements;
import org.springframework.security.config.authentication.AuthenticationManagerFactoryBean;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.PortResolverImpl;
import org.springframework.security.web.util.AnyRequestMatcher;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
@ -35,6 +36,7 @@ import java.util.*;
*
* @author Luke Taylor
* @author Ben Alex
* @author Rob Winch
* @since 2.0
*/
public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
@ -108,17 +110,18 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
return createSecurityFilterChainBean(element, pc, Collections.emptyList());
}
final String portMapperName = createPortMapper(element, pc);
final BeanReference portMapper = createPortMapper(element, pc);
final BeanReference portResolver = createPortResolver(portMapper, pc);
ManagedList<BeanReference> authenticationProviders = new ManagedList<BeanReference>();
BeanReference authenticationManager = createAuthenticationManager(element, pc, authenticationProviders);
HttpConfigurationBuilder httpBldr = new HttpConfigurationBuilder(element, pc,
portMapperName, authenticationManager);
portMapper, portResolver, authenticationManager);
AuthenticationConfigBuilder authBldr = new AuthenticationConfigBuilder(element, pc,
httpBldr.getSessionCreationPolicy(), httpBldr.getRequestCache(), authenticationManager,
httpBldr.getSessionStrategy());
httpBldr.getSessionStrategy(), portMapper, portResolver);
authenticationProviders.addAll(authBldr.getProviders());
@ -179,14 +182,22 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
return new RuntimeBeanReference(id);
}
private String createPortMapper(Element elt, ParserContext pc) {
private BeanReference createPortMapper(Element elt, ParserContext pc) {
// Register the portMapper. A default will always be created, even if no element exists.
BeanDefinition portMapper = new PortMappingsBeanDefinitionParser().parse(
DomUtils.getChildElementByTagName(elt, Elements.PORT_MAPPINGS), pc);
String portMapperName = pc.getReaderContext().generateBeanName(portMapper);
pc.registerBeanComponent(new BeanComponentDefinition(portMapper, portMapperName));
return portMapperName;
return new RuntimeBeanReference(portMapperName);
}
private RuntimeBeanReference createPortResolver(BeanReference portMapper, ParserContext pc) {
RootBeanDefinition portResolver = new RootBeanDefinition(PortResolverImpl.class);
portResolver.getPropertyValues().addPropertyValue("portMapper", portMapper);
String portResolverName = pc.getReaderContext().generateBeanName(portResolver);
pc.registerBeanComponent(new BeanComponentDefinition(portResolver, portResolverName));
return new RuntimeBeanReference(portResolverName);
}
/**

View File

@ -688,6 +688,33 @@ class MiscHttpConfigTests extends AbstractHttpConfigTests {
expect:
getFilter(UsernamePasswordAuthenticationFilter.class).authenticationManager.parent instanceof MockAuthenticationManager
}
// SEC-1893
def customPortMappings() {
when: 'A custom port-mappings is registered'
def expectedHttpsPortMappings = [8443:8080]
xml.http('auto-config': 'true') {
'intercept-url'('pattern':'/**','requires-channel':'https')
'port-mappings' {
'port-mapping'(http:'8443',https:'8080')
}
}
createAppContext()
then: 'All the components created by the namespace use that port mapping'
getFilter(RequestCacheAwareFilter.class).requestCache.portResolver.portMapper.httpsPortMappings == expectedHttpsPortMappings
def channelProcessors = getFilter(ChannelProcessingFilter.class).channelDecisionManager.channelProcessors
channelProcessors.size() == 2
channelProcessors.each { cp->
cp.entryPoint.portMapper.httpsPortMappings == expectedHttpsPortMappings
cp.entryPoint.portResolver.portMapper.httpsPortMappings == expectedHttpsPortMappings
}
def authEntryPoint = getFilter(ExceptionTranslationFilter.class).authenticationEntryPoint
authEntryPoint.portMapper.httpsPortMappings == expectedHttpsPortMappings
authEntryPoint.portResolver.portMapper.httpsPortMappings == expectedHttpsPortMappings
}
}
class MockAuthenticationManager implements AuthenticationManager {