mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-23 20:42:14 +00:00
OPEN - issue SEC-953: Query string isn't ignored while url - filterchain pattern matching
http://jira.springframework.org/browse/SEC-953. Added stripQueryStringFromUrls parameter to FilterChainProxy which works the same as the one on DefaultFilterInvocationDefinitionSource. This defaults to true when used with ant path matching.
This commit is contained in:
parent
b6dec19e90
commit
39a656eb78
@ -50,16 +50,16 @@ import org.w3c.dom.Element;
|
|||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||||
static final Log logger = LogFactory.getLog(HttpSecurityBeanDefinitionParser.class);
|
static final Log logger = LogFactory.getLog(HttpSecurityBeanDefinitionParser.class);
|
||||||
|
|
||||||
static final String ATT_REALM = "realm";
|
static final String ATT_REALM = "realm";
|
||||||
static final String DEF_REALM = "Spring Security Application";
|
static final String DEF_REALM = "Spring Security Application";
|
||||||
|
|
||||||
static final String ATT_PATH_PATTERN = "pattern";
|
static final String ATT_PATH_PATTERN = "pattern";
|
||||||
|
|
||||||
static final String ATT_SESSION_FIXATION_PROTECTION = "session-fixation-protection";
|
static final String ATT_SESSION_FIXATION_PROTECTION = "session-fixation-protection";
|
||||||
static final String OPT_SESSION_FIXATION_NO_PROTECTION = "none";
|
static final String OPT_SESSION_FIXATION_NO_PROTECTION = "none";
|
||||||
static final String OPT_SESSION_FIXATION_CLEAN_SESSION = "newSession";
|
static final String OPT_SESSION_FIXATION_CLEAN_SESSION = "newSession";
|
||||||
static final String OPT_SESSION_FIXATION_MIGRATE_SESSION = "migrateSession";
|
static final String OPT_SESSION_FIXATION_MIGRATE_SESSION = "migrateSession";
|
||||||
|
|
||||||
static final String ATT_PATH_TYPE = "path-type";
|
static final String ATT_PATH_TYPE = "path-type";
|
||||||
@ -91,9 +91,9 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
static final String ATT_SERVLET_API_PROVISION = "servlet-api-provision";
|
static final String ATT_SERVLET_API_PROVISION = "servlet-api-provision";
|
||||||
static final String DEF_SERVLET_API_PROVISION = "true";
|
static final String DEF_SERVLET_API_PROVISION = "true";
|
||||||
|
|
||||||
static final String ATT_ACCESS_MGR = "access-decision-manager-ref";
|
static final String ATT_ACCESS_MGR = "access-decision-manager-ref";
|
||||||
static final String ATT_USER_SERVICE_REF = "user-service-ref";
|
static final String ATT_USER_SERVICE_REF = "user-service-ref";
|
||||||
|
|
||||||
static final String ATT_ENTRY_POINT_REF = "entry-point-ref";
|
static final String ATT_ENTRY_POINT_REF = "entry-point-ref";
|
||||||
static final String ATT_ONCE_PER_REQUEST = "once-per-request";
|
static final String ATT_ONCE_PER_REQUEST = "once-per-request";
|
||||||
static final String ATT_ACCESS_DENIED_PAGE = "access-denied-page";
|
static final String ATT_ACCESS_DENIED_PAGE = "access-denied-page";
|
||||||
@ -106,20 +106,20 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
// SEC-501 - should paths stored in request maps be converted to lower case
|
// SEC-501 - should paths stored in request maps be converted to lower case
|
||||||
// true if Ant path and using lower case
|
// true if Ant path and using lower case
|
||||||
final boolean convertPathsToLowerCase = (matcher instanceof AntUrlPathMatcher) && matcher.requiresLowerCaseUrl();
|
final boolean convertPathsToLowerCase = (matcher instanceof AntUrlPathMatcher) && matcher.requiresLowerCaseUrl();
|
||||||
|
|
||||||
final List interceptUrlElts = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_URL);
|
final List interceptUrlElts = DomUtils.getChildElementsByTagName(element, Elements.INTERCEPT_URL);
|
||||||
final Map filterChainMap = new LinkedHashMap();
|
final Map filterChainMap = new LinkedHashMap();
|
||||||
final LinkedHashMap channelRequestMap = new LinkedHashMap();
|
final LinkedHashMap channelRequestMap = new LinkedHashMap();
|
||||||
|
|
||||||
registerFilterChainProxy(parserContext, filterChainMap, matcher, source);
|
registerFilterChainProxy(parserContext, filterChainMap, matcher, source);
|
||||||
|
|
||||||
parseInterceptUrlsForChannelSecurityAndFilterChain(interceptUrlElts, filterChainMap, channelRequestMap,
|
parseInterceptUrlsForChannelSecurityAndFilterChain(interceptUrlElts, filterChainMap, channelRequestMap,
|
||||||
convertPathsToLowerCase, parserContext);
|
convertPathsToLowerCase, parserContext);
|
||||||
|
|
||||||
boolean allowSessionCreation = registerHttpSessionIntegrationFilter(element, parserContext);
|
boolean allowSessionCreation = registerHttpSessionIntegrationFilter(element, parserContext);
|
||||||
|
|
||||||
registerServletApiFilter(element, parserContext);
|
registerServletApiFilter(element, parserContext);
|
||||||
|
|
||||||
// Set up the access manager reference for http
|
// Set up the access manager reference for http
|
||||||
String accessManagerId = element.getAttribute(ATT_ACCESS_MGR);
|
String accessManagerId = element.getAttribute(ATT_ACCESS_MGR);
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
ConfigUtils.registerDefaultAccessManagerIfNecessary(parserContext);
|
ConfigUtils.registerDefaultAccessManagerIfNecessary(parserContext);
|
||||||
accessManagerId = BeanIds.ACCESS_MANAGER;
|
accessManagerId = BeanIds.ACCESS_MANAGER;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register the portMapper. A default will always be created, even if no element exists.
|
// Register the portMapper. A default will always be created, even if no element exists.
|
||||||
BeanDefinition portMapper = new PortMappingsBeanDefinitionParser().parse(
|
BeanDefinition portMapper = new PortMappingsBeanDefinitionParser().parse(
|
||||||
DomUtils.getChildElementByTagName(element, Elements.PORT_MAPPINGS), parserContext);
|
DomUtils.getChildElementByTagName(element, Elements.PORT_MAPPINGS), parserContext);
|
||||||
@ -139,19 +139,19 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
if (channelRequestMap.size() > 0) {
|
if (channelRequestMap.size() > 0) {
|
||||||
// At least one channel requirement has been specified
|
// At least one channel requirement has been specified
|
||||||
registerChannelProcessingBeans(parserContext, matcher, channelRequestMap);
|
registerChannelProcessingBeans(parserContext, matcher, channelRequestMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
registerFilterSecurityInterceptor(element, parserContext, matcher, accessManagerId,
|
registerFilterSecurityInterceptor(element, parserContext, matcher, accessManagerId,
|
||||||
parseInterceptUrlsForFilterInvocationRequestMap(interceptUrlElts, convertPathsToLowerCase, parserContext));
|
parseInterceptUrlsForFilterInvocationRequestMap(interceptUrlElts, convertPathsToLowerCase, parserContext));
|
||||||
|
|
||||||
boolean sessionControlEnabled = registerConcurrentSessionControlBeansIfRequired(element, parserContext);
|
boolean sessionControlEnabled = registerConcurrentSessionControlBeansIfRequired(element, parserContext);
|
||||||
|
|
||||||
registerSessionFixationProtectionFilter(parserContext, element.getAttribute(ATT_SESSION_FIXATION_PROTECTION),
|
registerSessionFixationProtectionFilter(parserContext, element.getAttribute(ATT_SESSION_FIXATION_PROTECTION),
|
||||||
sessionControlEnabled);
|
sessionControlEnabled);
|
||||||
|
|
||||||
boolean autoConfig = false;
|
boolean autoConfig = false;
|
||||||
if ("true".equals(element.getAttribute(ATT_AUTO_CONFIG))) {
|
if ("true".equals(element.getAttribute(ATT_AUTO_CONFIG))) {
|
||||||
autoConfig = true;
|
autoConfig = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Element anonymousElt = DomUtils.getChildElementByTagName(element, Elements.ANONYMOUS);
|
Element anonymousElt = DomUtils.getChildElementByTagName(element, Elements.ANONYMOUS);
|
||||||
@ -160,7 +160,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
parseRememberMeAndLogout(element, autoConfig, parserContext);
|
parseRememberMeAndLogout(element, autoConfig, parserContext);
|
||||||
|
|
||||||
parseBasicFormLoginAndOpenID(element, parserContext, autoConfig, allowSessionCreation);
|
parseBasicFormLoginAndOpenID(element, parserContext, autoConfig, allowSessionCreation);
|
||||||
|
|
||||||
Element x509Elt = DomUtils.getChildElementByTagName(element, Elements.X509);
|
Element x509Elt = DomUtils.getChildElementByTagName(element, Elements.X509);
|
||||||
@ -175,48 +175,49 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
RootBeanDefinition postProcessor2 = new RootBeanDefinition(UserDetailsServiceInjectionBeanPostProcessor.class);
|
RootBeanDefinition postProcessor2 = new RootBeanDefinition(UserDetailsServiceInjectionBeanPostProcessor.class);
|
||||||
postProcessor2.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
postProcessor2.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||||
registry.registerBeanDefinition(BeanIds.USER_DETAILS_SERVICE_INJECTION_POST_PROCESSOR, postProcessor2);
|
registry.registerBeanDefinition(BeanIds.USER_DETAILS_SERVICE_INJECTION_POST_PROCESSOR, postProcessor2);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseRememberMeAndLogout(Element elt, boolean autoConfig, ParserContext pc) {
|
private void parseRememberMeAndLogout(Element elt, boolean autoConfig, ParserContext pc) {
|
||||||
// Parse remember me before logout as RememberMeServices is also a LogoutHandler implementation.
|
// Parse remember me before logout as RememberMeServices is also a LogoutHandler implementation.
|
||||||
Element rememberMeElt = DomUtils.getChildElementByTagName(elt, Elements.REMEMBER_ME);
|
Element rememberMeElt = DomUtils.getChildElementByTagName(elt, Elements.REMEMBER_ME);
|
||||||
String rememberMeServices = null;
|
String rememberMeServices = null;
|
||||||
|
|
||||||
if (rememberMeElt != null || autoConfig) {
|
if (rememberMeElt != null || autoConfig) {
|
||||||
RememberMeBeanDefinitionParser rmbdp = new RememberMeBeanDefinitionParser();
|
RememberMeBeanDefinitionParser rmbdp = new RememberMeBeanDefinitionParser();
|
||||||
rmbdp.parse(rememberMeElt, pc);
|
rmbdp.parse(rememberMeElt, pc);
|
||||||
rememberMeServices = rmbdp.getServicesName();
|
rememberMeServices = rmbdp.getServicesName();
|
||||||
// Post processor to inject RememberMeServices into filters which need it
|
// Post processor to inject RememberMeServices into filters which need it
|
||||||
RootBeanDefinition rememberMeInjectionPostProcessor = new RootBeanDefinition(RememberMeServicesInjectionBeanPostProcessor.class);
|
RootBeanDefinition rememberMeInjectionPostProcessor = new RootBeanDefinition(RememberMeServicesInjectionBeanPostProcessor.class);
|
||||||
rememberMeInjectionPostProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
rememberMeInjectionPostProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||||
pc.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES_INJECTION_POST_PROCESSOR, rememberMeInjectionPostProcessor);
|
pc.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES_INJECTION_POST_PROCESSOR, rememberMeInjectionPostProcessor);
|
||||||
}
|
}
|
||||||
|
|
||||||
Element logoutElt = DomUtils.getChildElementByTagName(elt, Elements.LOGOUT);
|
Element logoutElt = DomUtils.getChildElementByTagName(elt, Elements.LOGOUT);
|
||||||
if (logoutElt != null || autoConfig) {
|
if (logoutElt != null || autoConfig) {
|
||||||
new LogoutBeanDefinitionParser(rememberMeServices).parse(logoutElt, pc);
|
new LogoutBeanDefinitionParser(rememberMeServices).parse(logoutElt, pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerFilterChainProxy(ParserContext pc, Map filterChainMap, UrlMatcher matcher, Object source) {
|
private void registerFilterChainProxy(ParserContext pc, Map filterChainMap, UrlMatcher matcher, Object source) {
|
||||||
if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_PROXY)) {
|
if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_PROXY)) {
|
||||||
pc.getReaderContext().error("Duplicate <http> element detected", source);
|
pc.getReaderContext().error("Duplicate <http> element detected", source);
|
||||||
}
|
}
|
||||||
|
|
||||||
RootBeanDefinition filterChainProxy = new RootBeanDefinition(FilterChainProxy.class);
|
RootBeanDefinition filterChainProxy = new RootBeanDefinition(FilterChainProxy.class);
|
||||||
filterChainProxy.setSource(source);
|
filterChainProxy.setSource(source);
|
||||||
filterChainProxy.getPropertyValues().addPropertyValue("matcher", matcher);
|
filterChainProxy.getPropertyValues().addPropertyValue("matcher", matcher);
|
||||||
|
filterChainProxy.getPropertyValues().addPropertyValue("stripQueryStringFromUrls", matcher instanceof AntUrlPathMatcher);
|
||||||
filterChainProxy.getPropertyValues().addPropertyValue("filterChainMap", filterChainMap);
|
filterChainProxy.getPropertyValues().addPropertyValue("filterChainMap", filterChainMap);
|
||||||
pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_CHAIN_PROXY, filterChainProxy);
|
pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_CHAIN_PROXY, filterChainProxy);
|
||||||
pc.getRegistry().registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN);
|
pc.getRegistry().registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean registerHttpSessionIntegrationFilter(Element element, ParserContext pc) {
|
private boolean registerHttpSessionIntegrationFilter(Element element, ParserContext pc) {
|
||||||
RootBeanDefinition httpScif = new RootBeanDefinition(HttpSessionContextIntegrationFilter.class);
|
RootBeanDefinition httpScif = new RootBeanDefinition(HttpSessionContextIntegrationFilter.class);
|
||||||
boolean sessionCreationAllowed = true;
|
boolean sessionCreationAllowed = true;
|
||||||
|
|
||||||
String createSession = element.getAttribute(ATT_CREATE_SESSION);
|
String createSession = element.getAttribute(ATT_CREATE_SESSION);
|
||||||
if (OPT_CREATE_SESSION_ALWAYS.equals(createSession)) {
|
if (OPT_CREATE_SESSION_ALWAYS.equals(createSession)) {
|
||||||
httpScif.getPropertyValues().addPropertyValue("allowSessionCreation", Boolean.TRUE);
|
httpScif.getPropertyValues().addPropertyValue("allowSessionCreation", Boolean.TRUE);
|
||||||
@ -233,11 +234,11 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
|
|
||||||
pc.getRegistry().registerBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER, httpScif);
|
pc.getRegistry().registerBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER, httpScif);
|
||||||
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER));
|
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER));
|
||||||
|
|
||||||
return sessionCreationAllowed;
|
return sessionCreationAllowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds the servlet-api integration filter if required
|
// Adds the servlet-api integration filter if required
|
||||||
private void registerServletApiFilter(Element element, ParserContext pc) {
|
private void registerServletApiFilter(Element element, ParserContext pc) {
|
||||||
String provideServletApi = element.getAttribute(ATT_SERVLET_API_PROVISION);
|
String provideServletApi = element.getAttribute(ATT_SERVLET_API_PROVISION);
|
||||||
if (!StringUtils.hasText(provideServletApi)) {
|
if (!StringUtils.hasText(provideServletApi)) {
|
||||||
@ -250,27 +251,27 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER));
|
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SECURITY_CONTEXT_HOLDER_AWARE_REQUEST_FILTER));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean registerConcurrentSessionControlBeansIfRequired(Element element, ParserContext parserContext) {
|
private boolean registerConcurrentSessionControlBeansIfRequired(Element element, ParserContext parserContext) {
|
||||||
Element sessionControlElt = DomUtils.getChildElementByTagName(element, Elements.CONCURRENT_SESSIONS);
|
Element sessionControlElt = DomUtils.getChildElementByTagName(element, Elements.CONCURRENT_SESSIONS);
|
||||||
if (sessionControlElt == null) {
|
if (sessionControlElt == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
new ConcurrentSessionsBeanDefinitionParser().parse(sessionControlElt, parserContext);
|
new ConcurrentSessionsBeanDefinitionParser().parse(sessionControlElt, parserContext);
|
||||||
logger.info("Concurrent session filter in use, setting 'forceEagerSessionCreation' to true");
|
logger.info("Concurrent session filter in use, setting 'forceEagerSessionCreation' to true");
|
||||||
BeanDefinition sessionIntegrationFilter = parserContext.getRegistry().getBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER);
|
BeanDefinition sessionIntegrationFilter = parserContext.getRegistry().getBeanDefinition(BeanIds.HTTP_SESSION_CONTEXT_INTEGRATION_FILTER);
|
||||||
sessionIntegrationFilter.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.TRUE);
|
sessionIntegrationFilter.getPropertyValues().addPropertyValue("forceEagerSessionCreation", Boolean.TRUE);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerExceptionTranslationFilter(Element element, ParserContext pc, boolean allowSessionCreation) {
|
private void registerExceptionTranslationFilter(Element element, ParserContext pc, boolean allowSessionCreation) {
|
||||||
String accessDeniedPage = element.getAttribute(ATT_ACCESS_DENIED_PAGE);
|
String accessDeniedPage = element.getAttribute(ATT_ACCESS_DENIED_PAGE);
|
||||||
ConfigUtils.validateHttpRedirect(accessDeniedPage, pc, pc.extractSource(element));
|
ConfigUtils.validateHttpRedirect(accessDeniedPage, pc, pc.extractSource(element));
|
||||||
BeanDefinitionBuilder exceptionTranslationFilterBuilder
|
BeanDefinitionBuilder exceptionTranslationFilterBuilder
|
||||||
= BeanDefinitionBuilder.rootBeanDefinition(ExceptionTranslationFilter.class);
|
= BeanDefinitionBuilder.rootBeanDefinition(ExceptionTranslationFilter.class);
|
||||||
exceptionTranslationFilterBuilder.addPropertyValue("createSessionAllowed", new Boolean(allowSessionCreation));
|
exceptionTranslationFilterBuilder.addPropertyValue("createSessionAllowed", new Boolean(allowSessionCreation));
|
||||||
|
|
||||||
if (StringUtils.hasText(accessDeniedPage)) {
|
if (StringUtils.hasText(accessDeniedPage)) {
|
||||||
AccessDeniedHandlerImpl accessDeniedHandler = new AccessDeniedHandlerImpl();
|
AccessDeniedHandlerImpl accessDeniedHandler = new AccessDeniedHandlerImpl();
|
||||||
accessDeniedHandler.setErrorPage(accessDeniedPage);
|
accessDeniedHandler.setErrorPage(accessDeniedPage);
|
||||||
@ -280,27 +281,27 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
pc.getRegistry().registerBeanDefinition(BeanIds.EXCEPTION_TRANSLATION_FILTER, exceptionTranslationFilterBuilder.getBeanDefinition());
|
pc.getRegistry().registerBeanDefinition(BeanIds.EXCEPTION_TRANSLATION_FILTER, exceptionTranslationFilterBuilder.getBeanDefinition());
|
||||||
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.EXCEPTION_TRANSLATION_FILTER));
|
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.EXCEPTION_TRANSLATION_FILTER));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerFilterSecurityInterceptor(Element element, ParserContext pc, UrlMatcher matcher,
|
private void registerFilterSecurityInterceptor(Element element, ParserContext pc, UrlMatcher matcher,
|
||||||
String accessManagerId, LinkedHashMap filterInvocationDefinitionMap) {
|
String accessManagerId, LinkedHashMap filterInvocationDefinitionMap) {
|
||||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(FilterSecurityInterceptor.class);
|
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(FilterSecurityInterceptor.class);
|
||||||
|
|
||||||
builder.addPropertyReference("accessDecisionManager", accessManagerId);
|
builder.addPropertyReference("accessDecisionManager", accessManagerId);
|
||||||
builder.addPropertyReference("authenticationManager", BeanIds.AUTHENTICATION_MANAGER);
|
builder.addPropertyReference("authenticationManager", BeanIds.AUTHENTICATION_MANAGER);
|
||||||
|
|
||||||
if ("false".equals(element.getAttribute(ATT_ONCE_PER_REQUEST))) {
|
if ("false".equals(element.getAttribute(ATT_ONCE_PER_REQUEST))) {
|
||||||
builder.addPropertyValue("observeOncePerRequest", Boolean.FALSE);
|
builder.addPropertyValue("observeOncePerRequest", Boolean.FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultFilterInvocationDefinitionSource fids =
|
DefaultFilterInvocationDefinitionSource fids =
|
||||||
new DefaultFilterInvocationDefinitionSource(matcher, filterInvocationDefinitionMap);
|
new DefaultFilterInvocationDefinitionSource(matcher, filterInvocationDefinitionMap);
|
||||||
fids.setStripQueryStringFromUrls(matcher instanceof AntUrlPathMatcher);
|
fids.setStripQueryStringFromUrls(matcher instanceof AntUrlPathMatcher);
|
||||||
|
|
||||||
builder.addPropertyValue("objectDefinitionSource", fids);
|
builder.addPropertyValue("objectDefinitionSource", fids);
|
||||||
pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_SECURITY_INTERCEPTOR, builder.getBeanDefinition());
|
pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_SECURITY_INTERCEPTOR, builder.getBeanDefinition());
|
||||||
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FILTER_SECURITY_INTERCEPTOR));
|
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FILTER_SECURITY_INTERCEPTOR));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerChannelProcessingBeans(ParserContext pc, UrlMatcher matcher, LinkedHashMap channelRequestMap) {
|
private void registerChannelProcessingBeans(ParserContext pc, UrlMatcher matcher, LinkedHashMap channelRequestMap) {
|
||||||
RootBeanDefinition channelFilter = new RootBeanDefinition(ChannelProcessingFilter.class);
|
RootBeanDefinition channelFilter = new RootBeanDefinition(ChannelProcessingFilter.class);
|
||||||
channelFilter.getPropertyValues().addPropertyValue("channelDecisionManager",
|
channelFilter.getPropertyValues().addPropertyValue("channelDecisionManager",
|
||||||
@ -308,7 +309,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
DefaultFilterInvocationDefinitionSource channelFilterInvDefSource =
|
DefaultFilterInvocationDefinitionSource channelFilterInvDefSource =
|
||||||
new DefaultFilterInvocationDefinitionSource(matcher, channelRequestMap);
|
new DefaultFilterInvocationDefinitionSource(matcher, channelRequestMap);
|
||||||
channelFilterInvDefSource.setStripQueryStringFromUrls(matcher instanceof AntUrlPathMatcher);
|
channelFilterInvDefSource.setStripQueryStringFromUrls(matcher instanceof AntUrlPathMatcher);
|
||||||
|
|
||||||
channelFilter.getPropertyValues().addPropertyValue("filterInvocationDefinitionSource",
|
channelFilter.getPropertyValues().addPropertyValue("filterInvocationDefinitionSource",
|
||||||
channelFilterInvDefSource);
|
channelFilterInvDefSource);
|
||||||
RootBeanDefinition channelDecisionManager = new RootBeanDefinition(ChannelDecisionManagerImpl.class);
|
RootBeanDefinition channelDecisionManager = new RootBeanDefinition(ChannelDecisionManagerImpl.class);
|
||||||
@ -329,161 +330,161 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
pc.getRegistry().registerBeanDefinition(BeanIds.CHANNEL_PROCESSING_FILTER, channelFilter);
|
pc.getRegistry().registerBeanDefinition(BeanIds.CHANNEL_PROCESSING_FILTER, channelFilter);
|
||||||
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.CHANNEL_PROCESSING_FILTER));
|
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.CHANNEL_PROCESSING_FILTER));
|
||||||
pc.getRegistry().registerBeanDefinition(BeanIds.CHANNEL_DECISION_MANAGER, channelDecisionManager);
|
pc.getRegistry().registerBeanDefinition(BeanIds.CHANNEL_DECISION_MANAGER, channelDecisionManager);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerSessionFixationProtectionFilter(ParserContext pc, String sessionFixationAttribute, boolean sessionControlEnabled) {
|
private void registerSessionFixationProtectionFilter(ParserContext pc, String sessionFixationAttribute, boolean sessionControlEnabled) {
|
||||||
if(!StringUtils.hasText(sessionFixationAttribute)) {
|
if(!StringUtils.hasText(sessionFixationAttribute)) {
|
||||||
sessionFixationAttribute = OPT_SESSION_FIXATION_MIGRATE_SESSION;
|
sessionFixationAttribute = OPT_SESSION_FIXATION_MIGRATE_SESSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sessionFixationAttribute.equals(OPT_SESSION_FIXATION_NO_PROTECTION)) {
|
if (!sessionFixationAttribute.equals(OPT_SESSION_FIXATION_NO_PROTECTION)) {
|
||||||
BeanDefinitionBuilder sessionFixationFilter =
|
BeanDefinitionBuilder sessionFixationFilter =
|
||||||
BeanDefinitionBuilder.rootBeanDefinition(SessionFixationProtectionFilter.class);
|
BeanDefinitionBuilder.rootBeanDefinition(SessionFixationProtectionFilter.class);
|
||||||
sessionFixationFilter.addPropertyValue("migrateSessionAttributes",
|
sessionFixationFilter.addPropertyValue("migrateSessionAttributes",
|
||||||
Boolean.valueOf(sessionFixationAttribute.equals(OPT_SESSION_FIXATION_MIGRATE_SESSION)));
|
Boolean.valueOf(sessionFixationAttribute.equals(OPT_SESSION_FIXATION_MIGRATE_SESSION)));
|
||||||
if (sessionControlEnabled) {
|
if (sessionControlEnabled) {
|
||||||
sessionFixationFilter.addPropertyReference("sessionRegistry", BeanIds.SESSION_REGISTRY);
|
sessionFixationFilter.addPropertyReference("sessionRegistry", BeanIds.SESSION_REGISTRY);
|
||||||
}
|
}
|
||||||
pc.getRegistry().registerBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER,
|
pc.getRegistry().registerBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER,
|
||||||
sessionFixationFilter.getBeanDefinition());
|
sessionFixationFilter.getBeanDefinition());
|
||||||
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SESSION_FIXATION_PROTECTION_FILTER));
|
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SESSION_FIXATION_PROTECTION_FILTER));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseBasicFormLoginAndOpenID(Element element, ParserContext pc, boolean autoConfig, boolean allowSessionCreation) {
|
private void parseBasicFormLoginAndOpenID(Element element, ParserContext pc, boolean autoConfig, boolean allowSessionCreation) {
|
||||||
RootBeanDefinition formLoginFilter = null;
|
RootBeanDefinition formLoginFilter = null;
|
||||||
RootBeanDefinition formLoginEntryPoint = null;
|
RootBeanDefinition formLoginEntryPoint = null;
|
||||||
String formLoginPage = null;
|
String formLoginPage = null;
|
||||||
RootBeanDefinition openIDFilter = null;
|
RootBeanDefinition openIDFilter = null;
|
||||||
RootBeanDefinition openIDEntryPoint = null;
|
RootBeanDefinition openIDEntryPoint = null;
|
||||||
String openIDLoginPage = null;
|
String openIDLoginPage = null;
|
||||||
|
|
||||||
String realm = element.getAttribute(ATT_REALM);
|
String realm = element.getAttribute(ATT_REALM);
|
||||||
if (!StringUtils.hasText(realm)) {
|
if (!StringUtils.hasText(realm)) {
|
||||||
realm = DEF_REALM;
|
realm = DEF_REALM;
|
||||||
}
|
}
|
||||||
|
|
||||||
Element basicAuthElt = DomUtils.getChildElementByTagName(element, Elements.BASIC_AUTH);
|
Element basicAuthElt = DomUtils.getChildElementByTagName(element, Elements.BASIC_AUTH);
|
||||||
if (basicAuthElt != null || autoConfig) {
|
if (basicAuthElt != null || autoConfig) {
|
||||||
new BasicAuthenticationBeanDefinitionParser(realm).parse(basicAuthElt, pc);
|
new BasicAuthenticationBeanDefinitionParser(realm).parse(basicAuthElt, pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
Element formLoginElt = DomUtils.getChildElementByTagName(element, Elements.FORM_LOGIN);
|
Element formLoginElt = DomUtils.getChildElementByTagName(element, Elements.FORM_LOGIN);
|
||||||
|
|
||||||
if (formLoginElt != null || autoConfig) {
|
if (formLoginElt != null || autoConfig) {
|
||||||
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_security_check",
|
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_security_check",
|
||||||
"org.springframework.security.ui.webapp.AuthenticationProcessingFilter");
|
"org.springframework.security.ui.webapp.AuthenticationProcessingFilter");
|
||||||
|
|
||||||
parser.parse(formLoginElt, pc);
|
parser.parse(formLoginElt, pc);
|
||||||
formLoginFilter = parser.getFilterBean();
|
formLoginFilter = parser.getFilterBean();
|
||||||
formLoginEntryPoint = parser.getEntryPointBean();
|
formLoginEntryPoint = parser.getEntryPointBean();
|
||||||
formLoginPage = parser.getLoginPage();
|
formLoginPage = parser.getLoginPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
Element openIDLoginElt = DomUtils.getChildElementByTagName(element, Elements.OPENID_LOGIN);
|
Element openIDLoginElt = DomUtils.getChildElementByTagName(element, Elements.OPENID_LOGIN);
|
||||||
|
|
||||||
if (openIDLoginElt != null) {
|
if (openIDLoginElt != null) {
|
||||||
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_openid_security_check",
|
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/j_spring_openid_security_check",
|
||||||
"org.springframework.security.ui.openid.OpenIDAuthenticationProcessingFilter");
|
"org.springframework.security.ui.openid.OpenIDAuthenticationProcessingFilter");
|
||||||
|
|
||||||
parser.parse(openIDLoginElt, pc);
|
parser.parse(openIDLoginElt, pc);
|
||||||
openIDFilter = parser.getFilterBean();
|
openIDFilter = parser.getFilterBean();
|
||||||
openIDEntryPoint = parser.getEntryPointBean();
|
openIDEntryPoint = parser.getEntryPointBean();
|
||||||
openIDLoginPage = parser.getLoginPage();
|
openIDLoginPage = parser.getLoginPage();
|
||||||
|
|
||||||
BeanDefinitionBuilder openIDProviderBuilder =
|
BeanDefinitionBuilder openIDProviderBuilder =
|
||||||
BeanDefinitionBuilder.rootBeanDefinition("org.springframework.security.providers.openid.OpenIDAuthenticationProvider");
|
BeanDefinitionBuilder.rootBeanDefinition("org.springframework.security.providers.openid.OpenIDAuthenticationProvider");
|
||||||
|
|
||||||
String userService = openIDLoginElt.getAttribute(ATT_USER_SERVICE_REF);
|
String userService = openIDLoginElt.getAttribute(ATT_USER_SERVICE_REF);
|
||||||
|
|
||||||
if (StringUtils.hasText(userService)) {
|
if (StringUtils.hasText(userService)) {
|
||||||
openIDProviderBuilder.addPropertyReference("userDetailsService", userService);
|
openIDProviderBuilder.addPropertyReference("userDetailsService", userService);
|
||||||
}
|
}
|
||||||
|
|
||||||
BeanDefinition openIDProvider = openIDProviderBuilder.getBeanDefinition();
|
BeanDefinition openIDProvider = openIDProviderBuilder.getBeanDefinition();
|
||||||
pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_PROVIDER, openIDProvider);
|
pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_PROVIDER, openIDProvider);
|
||||||
ConfigUtils.addAuthenticationProvider(pc, BeanIds.OPEN_ID_PROVIDER);
|
ConfigUtils.addAuthenticationProvider(pc, BeanIds.OPEN_ID_PROVIDER);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean needLoginPage = false;
|
boolean needLoginPage = false;
|
||||||
|
|
||||||
if (formLoginFilter != null) {
|
if (formLoginFilter != null) {
|
||||||
needLoginPage = true;
|
needLoginPage = true;
|
||||||
formLoginFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation));
|
formLoginFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation));
|
||||||
pc.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_FILTER, formLoginFilter);
|
pc.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_FILTER, formLoginFilter);
|
||||||
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FORM_LOGIN_FILTER));
|
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FORM_LOGIN_FILTER));
|
||||||
pc.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_ENTRY_POINT, formLoginEntryPoint);
|
pc.getRegistry().registerBeanDefinition(BeanIds.FORM_LOGIN_ENTRY_POINT, formLoginEntryPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (openIDFilter != null) {
|
if (openIDFilter != null) {
|
||||||
needLoginPage = true;
|
needLoginPage = true;
|
||||||
openIDFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation));
|
openIDFilter.getPropertyValues().addPropertyValue("allowSessionCreation", new Boolean(allowSessionCreation));
|
||||||
pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_FILTER, openIDFilter);
|
pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_FILTER, openIDFilter);
|
||||||
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER));
|
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER));
|
||||||
pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_ENTRY_POINT, openIDEntryPoint);
|
pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_ENTRY_POINT, openIDEntryPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no login page has been defined, add in the default page generator.
|
// If no login page has been defined, add in the default page generator.
|
||||||
if (needLoginPage && formLoginPage == null && openIDLoginPage == null) {
|
if (needLoginPage && formLoginPage == null && openIDLoginPage == null) {
|
||||||
logger.info("No login page configured. The default internal one will be used. Use the '"
|
logger.info("No login page configured. The default internal one will be used. Use the '"
|
||||||
+ FormLoginBeanDefinitionParser.ATT_LOGIN_PAGE + "' attribute to set the URL of the login page.");
|
+ FormLoginBeanDefinitionParser.ATT_LOGIN_PAGE + "' attribute to set the URL of the login page.");
|
||||||
BeanDefinitionBuilder loginPageFilter =
|
BeanDefinitionBuilder loginPageFilter =
|
||||||
BeanDefinitionBuilder.rootBeanDefinition(DefaultLoginPageGeneratingFilter.class);
|
BeanDefinitionBuilder.rootBeanDefinition(DefaultLoginPageGeneratingFilter.class);
|
||||||
|
|
||||||
if (formLoginFilter != null) {
|
if (formLoginFilter != null) {
|
||||||
loginPageFilter.addConstructorArg(new RuntimeBeanReference(BeanIds.FORM_LOGIN_FILTER));
|
loginPageFilter.addConstructorArg(new RuntimeBeanReference(BeanIds.FORM_LOGIN_FILTER));
|
||||||
}
|
|
||||||
|
|
||||||
if (openIDFilter != null) {
|
|
||||||
loginPageFilter.addConstructorArg(new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pc.getRegistry().registerBeanDefinition(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER,
|
if (openIDFilter != null) {
|
||||||
loginPageFilter.getBeanDefinition());
|
loginPageFilter.addConstructorArg(new RuntimeBeanReference(BeanIds.OPEN_ID_FILTER));
|
||||||
|
}
|
||||||
|
|
||||||
|
pc.getRegistry().registerBeanDefinition(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER,
|
||||||
|
loginPageFilter.getBeanDefinition());
|
||||||
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER));
|
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.DEFAULT_LOGIN_PAGE_GENERATING_FILTER));
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to establish the main entry point.
|
// We need to establish the main entry point.
|
||||||
// First check if a custom entry point bean is set
|
// First check if a custom entry point bean is set
|
||||||
String customEntryPoint = element.getAttribute(ATT_ENTRY_POINT_REF);
|
String customEntryPoint = element.getAttribute(ATT_ENTRY_POINT_REF);
|
||||||
|
|
||||||
if (StringUtils.hasText(customEntryPoint)) {
|
if (StringUtils.hasText(customEntryPoint)) {
|
||||||
pc.getRegistry().registerAlias(customEntryPoint, BeanIds.MAIN_ENTRY_POINT);
|
pc.getRegistry().registerAlias(customEntryPoint, BeanIds.MAIN_ENTRY_POINT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Basic takes precedence if explicit element is used and no others are configured
|
// Basic takes precedence if explicit element is used and no others are configured
|
||||||
if (basicAuthElt != null && formLoginElt == null && openIDLoginElt == null) {
|
if (basicAuthElt != null && formLoginElt == null && openIDLoginElt == null) {
|
||||||
pc.getRegistry().registerAlias(BeanIds.BASIC_AUTHENTICATION_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
|
pc.getRegistry().registerAlias(BeanIds.BASIC_AUTHENTICATION_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If formLogin has been enabled either through an element or auto-config, then it is used if no openID login page
|
// If formLogin has been enabled either through an element or auto-config, then it is used if no openID login page
|
||||||
// has been set
|
// has been set
|
||||||
if (formLoginFilter != null && openIDLoginPage == null) {
|
if (formLoginFilter != null && openIDLoginPage == null) {
|
||||||
pc.getRegistry().registerAlias(BeanIds.FORM_LOGIN_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
|
pc.getRegistry().registerAlias(BeanIds.FORM_LOGIN_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise use OpenID if enabled
|
// Otherwise use OpenID if enabled
|
||||||
if (openIDFilter != null && formLoginFilter == null) {
|
if (openIDFilter != null && formLoginFilter == null) {
|
||||||
pc.getRegistry().registerAlias(BeanIds.OPEN_ID_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
|
pc.getRegistry().registerAlias(BeanIds.OPEN_ID_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If X.509 has been enabled, use the preauth entry point.
|
// If X.509 has been enabled, use the preauth entry point.
|
||||||
if (DomUtils.getChildElementByTagName(element, Elements.X509) != null) {
|
if (DomUtils.getChildElementByTagName(element, Elements.X509) != null) {
|
||||||
pc.getRegistry().registerAlias(BeanIds.PRE_AUTH_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
|
pc.getRegistry().registerAlias(BeanIds.PRE_AUTH_ENTRY_POINT, BeanIds.MAIN_ENTRY_POINT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pc.getReaderContext().error("No AuthenticationEntryPoint could be established. Please " +
|
pc.getReaderContext().error("No AuthenticationEntryPoint could be established. Please " +
|
||||||
"make sure you have a login mechanism configured through the namespace (such as form-login) or " +
|
"make sure you have a login mechanism configured through the namespace (such as form-login) or " +
|
||||||
"specify a custom AuthenticationEntryPoint with the custom-entry-point-ref attribute ",
|
"specify a custom AuthenticationEntryPoint with the custom-entry-point-ref attribute ",
|
||||||
pc.extractSource(element));
|
pc.extractSource(element));
|
||||||
}
|
}
|
||||||
|
|
||||||
static UrlMatcher createUrlMatcher(Element element) {
|
static UrlMatcher createUrlMatcher(Element element) {
|
||||||
String patternType = element.getAttribute(ATT_PATH_TYPE);
|
String patternType = element.getAttribute(ATT_PATH_TYPE);
|
||||||
if (!StringUtils.hasText(patternType)) {
|
if (!StringUtils.hasText(patternType)) {
|
||||||
@ -517,8 +518,8 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
}
|
}
|
||||||
// Default for regex is no change
|
// Default for regex is no change
|
||||||
}
|
}
|
||||||
|
|
||||||
return matcher;
|
return matcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -562,7 +563,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
editor.setAsText(channelConfigAttribute);
|
editor.setAsText(channelConfigAttribute);
|
||||||
channelRequestMap.put(new RequestKey(path), (ConfigAttributeDefinition) editor.getValue());
|
channelRequestMap.put(new RequestKey(path), (ConfigAttributeDefinition) editor.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
String filters = urlElt.getAttribute(ATT_FILTERS);
|
String filters = urlElt.getAttribute(ATT_FILTERS);
|
||||||
|
|
||||||
if (StringUtils.hasText(filters)) {
|
if (StringUtils.hasText(filters)) {
|
||||||
@ -575,10 +576,10 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static LinkedHashMap parseInterceptUrlsForFilterInvocationRequestMap(List urlElts, boolean useLowerCasePaths, ParserContext parserContext) {
|
static LinkedHashMap parseInterceptUrlsForFilterInvocationRequestMap(List urlElts, boolean useLowerCasePaths, ParserContext parserContext) {
|
||||||
LinkedHashMap filterInvocationDefinitionMap = new LinkedHashMap();
|
LinkedHashMap filterInvocationDefinitionMap = new LinkedHashMap();
|
||||||
|
|
||||||
Iterator urlEltsIterator = urlElts.iterator();
|
Iterator urlEltsIterator = urlElts.iterator();
|
||||||
ConfigAttributeEditor editor = new ConfigAttributeEditor();
|
ConfigAttributeEditor editor = new ConfigAttributeEditor();
|
||||||
|
|
||||||
@ -606,16 +607,16 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
if (StringUtils.hasText(access)) {
|
if (StringUtils.hasText(access)) {
|
||||||
editor.setAsText(access);
|
editor.setAsText(access);
|
||||||
Object key = new RequestKey(path, method);
|
Object key = new RequestKey(path, method);
|
||||||
|
|
||||||
if (filterInvocationDefinitionMap.containsKey(key)) {
|
if (filterInvocationDefinitionMap.containsKey(key)) {
|
||||||
logger.warn("Duplicate URL defined: " + key + ". The original attribute values will be overwritten");
|
logger.warn("Duplicate URL defined: " + key + ". The original attribute values will be overwritten");
|
||||||
}
|
}
|
||||||
|
|
||||||
filterInvocationDefinitionMap.put(key, editor.getValue());
|
filterInvocationDefinitionMap.put(key, editor.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return filterInvocationDefinitionMap;
|
return filterInvocationDefinitionMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -107,6 +107,7 @@ public class FilterChainProxy implements Filter, InitializingBean, ApplicationCo
|
|||||||
/** Compiled pattern version of the filter chain map */
|
/** Compiled pattern version of the filter chain map */
|
||||||
private Map filterChainMap;
|
private Map filterChainMap;
|
||||||
private UrlMatcher matcher = new AntUrlPathMatcher();
|
private UrlMatcher matcher = new AntUrlPathMatcher();
|
||||||
|
private boolean stripQueryStringFromUrls = true;
|
||||||
private DefaultFilterInvocationDefinitionSource fids;
|
private DefaultFilterInvocationDefinitionSource fids;
|
||||||
|
|
||||||
//~ Methods ========================================================================================================
|
//~ Methods ========================================================================================================
|
||||||
@ -116,8 +117,8 @@ public class FilterChainProxy implements Filter, InitializingBean, ApplicationCo
|
|||||||
if (fids != null) {
|
if (fids != null) {
|
||||||
Assert.isNull(uncompiledFilterChainMap, "Set the filterChainMap or FilterInvocationDefinitionSource but not both");
|
Assert.isNull(uncompiledFilterChainMap, "Set the filterChainMap or FilterInvocationDefinitionSource but not both");
|
||||||
FIDSToFilterChainMapConverter converter = new FIDSToFilterChainMapConverter(fids, applicationContext);
|
FIDSToFilterChainMapConverter converter = new FIDSToFilterChainMapConverter(fids, applicationContext);
|
||||||
setMatcher(converter.getMatcher());
|
setMatcher(converter.getMatcher());
|
||||||
setFilterChainMap(converter.getFilterChainMap());
|
setFilterChainMap(converter.getFilterChainMap());
|
||||||
fids = null;
|
fids = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,6 +182,16 @@ public class FilterChainProxy implements Filter, InitializingBean, ApplicationCo
|
|||||||
* @return an ordered array of Filters defining the filter chain
|
* @return an ordered array of Filters defining the filter chain
|
||||||
*/
|
*/
|
||||||
public List getFilters(String url) {
|
public List getFilters(String url) {
|
||||||
|
if (stripQueryStringFromUrls) {
|
||||||
|
// String query string - see SEC-953
|
||||||
|
int firstQuestionMarkIndex = url.indexOf("?");
|
||||||
|
|
||||||
|
if (firstQuestionMarkIndex != -1) {
|
||||||
|
url = url.substring(0, firstQuestionMarkIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Iterator filterChains = filterChainMap.entrySet().iterator();
|
Iterator filterChains = filterChainMap.entrySet().iterator();
|
||||||
|
|
||||||
while (filterChains.hasNext()) {
|
while (filterChains.hasNext()) {
|
||||||
@ -319,6 +330,14 @@ public class FilterChainProxy implements Filter, InitializingBean, ApplicationCo
|
|||||||
return matcher;
|
return matcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set to 'true', the query string will be stripped from the request URL before
|
||||||
|
* attempting to find a matching filter chain. This is the default value.
|
||||||
|
*/
|
||||||
|
public void setStripQueryStringFromUrls(boolean stripQueryStringFromUrls) {
|
||||||
|
this.stripQueryStringFromUrls = stripQueryStringFromUrls;
|
||||||
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
sb.append("FilterChainProxy[");
|
sb.append("FilterChainProxy[");
|
||||||
|
@ -79,6 +79,8 @@ public class HttpSecurityBeanDefinitionParserTests {
|
|||||||
List filterList = getFilters("/anyurl");
|
List filterList = getFilters("/anyurl");
|
||||||
|
|
||||||
checkAutoConfigFilters(filterList);
|
checkAutoConfigFilters(filterList);
|
||||||
|
|
||||||
|
assertEquals(true, FieldUtils.getFieldValue(appContext.getBean("_filterChainProxy"), "stripQueryStringFromUrls"));
|
||||||
assertEquals(true, FieldUtils.getFieldValue(filterList.get(10), "objectDefinitionSource.stripQueryStringFromUrls"));
|
assertEquals(true, FieldUtils.getFieldValue(filterList.get(10), "objectDefinitionSource.stripQueryStringFromUrls"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,6 +138,7 @@ public class HttpSecurityBeanDefinitionParserTests {
|
|||||||
// This will be matched by the default pattern ".*"
|
// This will be matched by the default pattern ".*"
|
||||||
List allFilters = getFilters("/ImCaughtByTheUniversalMatchPattern");
|
List allFilters = getFilters("/ImCaughtByTheUniversalMatchPattern");
|
||||||
checkAutoConfigFilters(allFilters);
|
checkAutoConfigFilters(allFilters);
|
||||||
|
assertEquals(false, FieldUtils.getFieldValue(appContext.getBean("_filterChainProxy"), "stripQueryStringFromUrls"));
|
||||||
assertEquals(false, FieldUtils.getFieldValue(allFilters.get(10), "objectDefinitionSource.stripQueryStringFromUrls"));
|
assertEquals(false, FieldUtils.getFieldValue(allFilters.get(10), "objectDefinitionSource.stripQueryStringFromUrls"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +152,6 @@ public class HttpSecurityBeanDefinitionParserTests {
|
|||||||
// These will be matched by the default pattern "/**"
|
// These will be matched by the default pattern "/**"
|
||||||
checkAutoConfigFilters(getFilters("/secure"));
|
checkAutoConfigFilters(getFilters("/secure"));
|
||||||
checkAutoConfigFilters(getFilters("/ImCaughtByTheUniversalMatchPattern"));
|
checkAutoConfigFilters(getFilters("/ImCaughtByTheUniversalMatchPattern"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -62,20 +62,16 @@ public class FilterChainProxyTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected=IllegalArgumentException.class)
|
||||||
public void testDetectsFilterInvocationDefinitionSourceThatDoesNotReturnAllConfigAttributes() throws Exception {
|
public void testDetectsFilterInvocationDefinitionSourceThatDoesNotReturnAllConfigAttributes() throws Exception {
|
||||||
FilterChainProxy filterChainProxy = new FilterChainProxy();
|
FilterChainProxy filterChainProxy = new FilterChainProxy();
|
||||||
filterChainProxy.setApplicationContext(new StaticApplicationContext());
|
filterChainProxy.setApplicationContext(new StaticApplicationContext());
|
||||||
|
|
||||||
try {
|
filterChainProxy.setFilterInvocationDefinitionSource(new MockFilterInvocationDefinitionSource(false, false));
|
||||||
filterChainProxy.setFilterInvocationDefinitionSource(new MockFilterInvocationDefinitionSource(false, false));
|
filterChainProxy.afterPropertiesSet();
|
||||||
filterChainProxy.afterPropertiesSet();
|
|
||||||
fail("Should have thrown IllegalArgumentException");
|
|
||||||
} catch (IllegalArgumentException expected) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected=IllegalArgumentException.class)
|
||||||
public void testDetectsIfConfigAttributeDoesNotReturnValueForGetAttributeMethod() throws Exception {
|
public void testDetectsIfConfigAttributeDoesNotReturnValueForGetAttributeMethod() throws Exception {
|
||||||
FilterChainProxy filterChainProxy = new FilterChainProxy();
|
FilterChainProxy filterChainProxy = new FilterChainProxy();
|
||||||
filterChainProxy.setApplicationContext(new StaticApplicationContext());
|
filterChainProxy.setApplicationContext(new StaticApplicationContext());
|
||||||
@ -89,12 +85,8 @@ public class FilterChainProxyTests {
|
|||||||
|
|
||||||
filterChainProxy.setFilterInvocationDefinitionSource(fids);
|
filterChainProxy.setFilterInvocationDefinitionSource(fids);
|
||||||
|
|
||||||
try {
|
filterChainProxy.afterPropertiesSet();
|
||||||
filterChainProxy.afterPropertiesSet();
|
filterChainProxy.init(new MockFilterConfig());
|
||||||
filterChainProxy.init(new MockFilterConfig());
|
|
||||||
fail("Should have thrown IllegalArgumentException");
|
|
||||||
} catch (IllegalArgumentException expected) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
@ -131,18 +123,18 @@ public class FilterChainProxyTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void normalOperation() throws Exception {
|
public void normalOperation() throws Exception {
|
||||||
FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("filterChain", FilterChainProxy.class);
|
FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("filterChain", FilterChainProxy.class);
|
||||||
doNormalOperation(filterChainProxy);
|
doNormalOperation(filterChainProxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void proxyPathWithoutLowerCaseConversionShouldntMatchDifferentCasePath() throws Exception {
|
public void proxyPathWithoutLowerCaseConversionShouldntMatchDifferentCasePath() throws Exception {
|
||||||
FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("filterChainNonLowerCase", FilterChainProxy.class);
|
FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("filterChainNonLowerCase", FilterChainProxy.class);
|
||||||
assertNull(filterChainProxy.getFilters("/some/other/path/blah"));
|
assertNull(filterChainProxy.getFilters("/some/other/path/blah"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void normalOperationWithNewConfig() throws Exception {
|
public void normalOperationWithNewConfig() throws Exception {
|
||||||
FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("newFilterChainProxy", FilterChainProxy.class);
|
FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("newFilterChainProxy", FilterChainProxy.class);
|
||||||
@ -164,6 +156,24 @@ public class FilterChainProxyTests {
|
|||||||
doNormalOperation(filterChainProxy);
|
doNormalOperation(filterChainProxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void pathWithNoMatchHasNoFilters() throws Exception {
|
||||||
|
FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("newFilterChainProxyNoDefaultPath", FilterChainProxy.class);
|
||||||
|
assertEquals(null, filterChainProxy.getFilters("/nomatch"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void urlStrippingPropertyIsRespected() throws Exception {
|
||||||
|
FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("newFilterChainProxyNoDefaultPath", FilterChainProxy.class);
|
||||||
|
|
||||||
|
// Should only match if we are stripping the query string
|
||||||
|
String url = "/blah.bar?x=something";
|
||||||
|
assertNotNull(filterChainProxy.getFilters(url));
|
||||||
|
assertEquals(2, filterChainProxy.getFilters(url).size());
|
||||||
|
filterChainProxy.setStripQueryStringFromUrls(false);
|
||||||
|
assertNull(filterChainProxy.getFilters(url));
|
||||||
|
}
|
||||||
|
|
||||||
private void checkPathAndFilterOrder(FilterChainProxy filterChainProxy) throws Exception {
|
private void checkPathAndFilterOrder(FilterChainProxy filterChainProxy) throws Exception {
|
||||||
List filters = filterChainProxy.getFilters("/foo/blah");
|
List filters = filterChainProxy.getFilters("/foo/blah");
|
||||||
assertEquals(1, filters.size());
|
assertEquals(1, filters.size());
|
||||||
|
@ -24,9 +24,9 @@
|
|||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
|
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
|
||||||
|
|
||||||
<bean id="mockFilter" class="org.springframework.security.util.MockFilter"/>
|
<bean id="mockFilter" class="org.springframework.security.util.MockFilter"/>
|
||||||
|
|
||||||
<bean id="mockFilter2" class="org.springframework.security.util.MockFilter"/>
|
<bean id="mockFilter2" class="org.springframework.security.util.MockFilter"/>
|
||||||
|
|
||||||
<!-- These are just here so we have filters of a specfic type to check the ordering is as expected -->
|
<!-- These are just here so we have filters of a specfic type to check the ordering is as expected -->
|
||||||
<bean id="sif" class="org.springframework.security.context.HttpSessionContextIntegrationFilter"/>
|
<bean id="sif" class="org.springframework.security.context.HttpSessionContextIntegrationFilter"/>
|
||||||
@ -41,11 +41,11 @@ http://www.springframework.org/schema/security http://www.springframework.org/sc
|
|||||||
|
|
||||||
<bean id="mockNotAFilter" class="org.springframework.security.util.MockNotAFilter"/>
|
<bean id="mockNotAFilter" class="org.springframework.security.util.MockNotAFilter"/>
|
||||||
|
|
||||||
<bean id="filterChain" class="org.springframework.security.util.FilterChainProxy">
|
<bean id="filterChain" class="org.springframework.security.util.FilterChainProxy">
|
||||||
<property name="filterInvocationDefinitionSource">
|
<property name="filterInvocationDefinitionSource">
|
||||||
<value>
|
<value>
|
||||||
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
|
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
|
||||||
PATTERN_TYPE_APACHE_ANT
|
PATTERN_TYPE_APACHE_ANT
|
||||||
/foo/**=mockFilter
|
/foo/**=mockFilter
|
||||||
/some/other/path/**=mockFilter
|
/some/other/path/**=mockFilter
|
||||||
/do/not/filter=#NONE#
|
/do/not/filter=#NONE#
|
||||||
@ -53,10 +53,10 @@ http://www.springframework.org/schema/security http://www.springframework.org/sc
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="filterChainNonLowerCase" class="org.springframework.security.util.FilterChainProxy">
|
<bean id="filterChainNonLowerCase" class="org.springframework.security.util.FilterChainProxy">
|
||||||
<property name="filterInvocationDefinitionSource">
|
<property name="filterInvocationDefinitionSource">
|
||||||
<value>
|
<value>
|
||||||
PATTERN_TYPE_APACHE_ANT
|
PATTERN_TYPE_APACHE_ANT
|
||||||
/foo/**=mockFilter
|
/foo/**=mockFilter
|
||||||
/SOME/other/path/**=sif,mockFilter,mockFilter2
|
/SOME/other/path/**=sif,mockFilter,mockFilter2
|
||||||
/do/not/filter=#NONE#
|
/do/not/filter=#NONE#
|
||||||
@ -73,6 +73,13 @@ http://www.springframework.org/schema/security http://www.springframework.org/sc
|
|||||||
</sec:filter-chain-map>
|
</sec:filter-chain-map>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="newFilterChainProxyNoDefaultPath" class="org.springframework.security.util.FilterChainProxy">
|
||||||
|
<sec:filter-chain-map path-type="ant">
|
||||||
|
<sec:filter-chain pattern="/foo/**" filters="mockFilter"/>
|
||||||
|
<sec:filter-chain pattern="/*.bar" filters="mockFilter,mockFilter2"/>
|
||||||
|
</sec:filter-chain-map>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<bean id="newFilterChainProxyWrongPathOrder" class="org.springframework.security.util.FilterChainProxy">
|
<bean id="newFilterChainProxyWrongPathOrder" class="org.springframework.security.util.FilterChainProxy">
|
||||||
<sec:filter-chain-map path-type="ant">
|
<sec:filter-chain-map path-type="ant">
|
||||||
<sec:filter-chain pattern="/foo/**" filters="mockFilter"/>
|
<sec:filter-chain pattern="/foo/**" filters="mockFilter"/>
|
||||||
@ -117,7 +124,7 @@ http://www.springframework.org/schema/security http://www.springframework.org/sc
|
|||||||
<ref local="apf"/>
|
<ref local="apf"/>
|
||||||
<ref local="mockFilter"/>
|
<ref local="mockFilter"/>
|
||||||
</list>
|
</list>
|
||||||
</entry>
|
</entry>
|
||||||
</map>
|
</map>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user