SEC-1893: Namespace now register PortMapper with custom mappings for all components that use a PortMapper
This commit is contained in:
parent
84141c4c76
commit
f78c11650f
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue