Added building of filter chain in post-processing, support for basic authentication and automatic generation of login page, if no loginUrl supplied.
This commit is contained in:
parent
f0d8db5ce6
commit
cffd3131f0
|
@ -0,0 +1,43 @@
|
||||||
|
package org.springframework.security.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||||
|
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.springframework.security.ui.basicauth.BasicProcessingFilter;
|
||||||
|
import org.springframework.security.ui.basicauth.BasicProcessingFilterEntryPoint;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link BasicProcessingFilter} and {@link BasicProcessingFilterEntryPoint} and
|
||||||
|
* registers them in the application context.
|
||||||
|
*
|
||||||
|
* @author Luke Taylor
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class BasicAuthenticationBeanDefinitionParser implements BeanDefinitionParser {
|
||||||
|
public static final String DEFAULT_BASIC_AUTH_FILTER_ID = "_basicAuthenticationFilter";
|
||||||
|
public static final String DEFAULT_BASIC_AUTH_ENTRY_POINT_ID = "_basicAuthenticationEntryPoint";
|
||||||
|
|
||||||
|
|
||||||
|
public BeanDefinition parse(Element elt, ParserContext parserContext) {
|
||||||
|
BeanDefinitionBuilder filterBuilder =
|
||||||
|
BeanDefinitionBuilder.rootBeanDefinition(BasicProcessingFilter.class);
|
||||||
|
RootBeanDefinition entryPoint = new RootBeanDefinition(BasicProcessingFilterEntryPoint.class);
|
||||||
|
|
||||||
|
String realm = elt.getAttribute("realm");
|
||||||
|
|
||||||
|
entryPoint.getPropertyValues().addPropertyValue("realmName", realm);
|
||||||
|
|
||||||
|
filterBuilder.addPropertyValue("authenticationEntryPoint", entryPoint);
|
||||||
|
// Detect auth manager
|
||||||
|
filterBuilder.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE);
|
||||||
|
|
||||||
|
parserContext.getRegistry().registerBeanDefinition(DEFAULT_BASIC_AUTH_FILTER_ID,
|
||||||
|
filterBuilder.getBeanDefinition());
|
||||||
|
parserContext.getRegistry().registerBeanDefinition(DEFAULT_BASIC_AUTH_ENTRY_POINT_ID, entryPoint);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
package org.springframework.security.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||||
|
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.security.ui.webapp.AuthenticationProcessingFilter;
|
||||||
|
import org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint;
|
||||||
|
import org.springframework.security.ui.webapp.DefaultLoginPageGeneratingFilter;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luke Taylor
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class FormLoginBeanDefinitionParser implements BeanDefinitionParser {
|
||||||
|
protected final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
|
public static final String DEFAULT_FORM_LOGIN_FILTER_ID = "_formLoginFilter";
|
||||||
|
public static final String DEFAULT_FORM_LOGIN_ENTRY_POINT_ID = "_formLoginEntryPoint";
|
||||||
|
|
||||||
|
private static final String LOGIN_URL_ATTRIBUTE = "loginUrl";
|
||||||
|
private static final String LOGIN_PAGE_ATTRIBUTE = "loginPage";
|
||||||
|
|
||||||
|
private static final String FORM_LOGIN_TARGET_URL_ATTRIBUTE = "defaultTargetUrl";
|
||||||
|
private static final String DEFAULT_FORM_LOGIN_TARGET_URL = "/index";
|
||||||
|
|
||||||
|
private static final String FORM_LOGIN_AUTH_FAILURE_URL_ATTRIBUTE = "defaultTargetUrl";
|
||||||
|
// TODO: Change AbstractProcessingFilter to not need a failure URL and just write a failure message
|
||||||
|
// to the response if one isn't set.
|
||||||
|
private static final String DEFAULT_FORM_LOGIN_AUTH_FAILURE_URL = "/loginError";
|
||||||
|
|
||||||
|
|
||||||
|
public BeanDefinition parse(Element elt, ParserContext parserContext) {
|
||||||
|
BeanDefinition filterBean = createFilterBean(elt);
|
||||||
|
|
||||||
|
BeanDefinitionBuilder entryPointBuilder =
|
||||||
|
BeanDefinitionBuilder.rootBeanDefinition(AuthenticationProcessingFilterEntryPoint.class);
|
||||||
|
|
||||||
|
|
||||||
|
String loginPage = elt.getAttribute(LOGIN_PAGE_ATTRIBUTE);
|
||||||
|
|
||||||
|
// If no login page has been defined, add in the default page generator.
|
||||||
|
if (!StringUtils.hasText(loginPage)) {
|
||||||
|
logger.info("No login page configured in form-login element. The default internal one will be used. Use" +
|
||||||
|
"the 'loginPage' attribute to specify the URL of the login page.");
|
||||||
|
loginPage = DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL;
|
||||||
|
RootBeanDefinition loginPageFilter = new RootBeanDefinition(DefaultLoginPageGeneratingFilter.class);
|
||||||
|
loginPageFilter.getConstructorArgumentValues().addGenericArgumentValue(filterBean);
|
||||||
|
parserContext.getRegistry().registerBeanDefinition("_springSecurityLoginPageFilter", loginPageFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
entryPointBuilder.addPropertyValue("loginFormUrl", loginPage);
|
||||||
|
|
||||||
|
parserContext.getRegistry().registerBeanDefinition(DEFAULT_FORM_LOGIN_FILTER_ID, filterBean);
|
||||||
|
parserContext.getRegistry().registerBeanDefinition(DEFAULT_FORM_LOGIN_ENTRY_POINT_ID,
|
||||||
|
entryPointBuilder.getBeanDefinition());
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BeanDefinition createFilterBean(Element elt) {
|
||||||
|
BeanDefinitionBuilder filterBuilder =
|
||||||
|
BeanDefinitionBuilder.rootBeanDefinition(AuthenticationProcessingFilter.class);
|
||||||
|
|
||||||
|
String loginUrl = elt.getAttribute(LOGIN_URL_ATTRIBUTE);
|
||||||
|
|
||||||
|
if (StringUtils.hasText(loginUrl)) {
|
||||||
|
filterBuilder.addPropertyValue("filterProcessesUrl", loginUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
String defaultTargetUrl = elt.getAttribute(FORM_LOGIN_TARGET_URL_ATTRIBUTE);
|
||||||
|
|
||||||
|
if (!StringUtils.hasText(defaultTargetUrl)) {
|
||||||
|
defaultTargetUrl = DEFAULT_FORM_LOGIN_TARGET_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
filterBuilder.addPropertyValue("defaultTargetUrl", defaultTargetUrl);
|
||||||
|
|
||||||
|
String authenticationFailureUrl = elt.getAttribute(FORM_LOGIN_AUTH_FAILURE_URL_ATTRIBUTE);
|
||||||
|
|
||||||
|
if (!StringUtils.hasText(authenticationFailureUrl)) {
|
||||||
|
authenticationFailureUrl = DEFAULT_FORM_LOGIN_AUTH_FAILURE_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
filterBuilder.addPropertyValue("authenticationFailureUrl", authenticationFailureUrl);
|
||||||
|
// Set autowire to pick up the authentication manager.
|
||||||
|
filterBuilder.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE);
|
||||||
|
|
||||||
|
return filterBuilder.getBeanDefinition();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,34 +1,32 @@
|
||||||
package org.springframework.security.config;
|
package org.springframework.security.config;
|
||||||
|
|
||||||
import org.springframework.beans.factory.xml.ParserContext;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
|
||||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||||
import org.springframework.util.xml.DomUtils;
|
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.springframework.security.ConfigAttributeDefinition;
|
||||||
|
import org.springframework.security.ConfigAttributeEditor;
|
||||||
|
import org.springframework.security.context.HttpSessionContextIntegrationFilter;
|
||||||
|
import org.springframework.security.intercept.web.*;
|
||||||
|
import org.springframework.security.ui.ExceptionTranslationFilter;
|
||||||
|
import org.springframework.security.util.FilterChainProxy;
|
||||||
|
import org.springframework.security.util.RegexUrlPathMatcher;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.security.util.FilterChainProxy;
|
import org.springframework.util.xml.DomUtils;
|
||||||
import org.springframework.security.intercept.web.PathBasedFilterInvocationDefinitionMap;
|
|
||||||
import org.springframework.security.intercept.web.FilterSecurityInterceptor;
|
|
||||||
import org.springframework.security.intercept.web.FilterInvocationDefinitionMap;
|
|
||||||
import org.springframework.security.ConfigAttributeEditor;
|
|
||||||
import org.springframework.security.ConfigAttributeDefinition;
|
|
||||||
import org.springframework.security.ui.ExceptionTranslationFilter;
|
|
||||||
import org.springframework.security.ui.webapp.AuthenticationProcessingFilter;
|
|
||||||
import org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint;
|
|
||||||
import org.springframework.security.context.HttpSessionContextIntegrationFilter;
|
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
import java.util.List;
|
import javax.servlet.Filter;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up HTTP security: filter stack and protected URLs.
|
* Sets up HTTP security: filter stack and protected URLs.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @author luke
|
* @author Luke Taylor
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||||
|
@ -39,39 +37,23 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||||
public static final String DEFAULT_LOGOUT_FILTER_ID = "_logoutFilter";
|
public static final String DEFAULT_LOGOUT_FILTER_ID = "_logoutFilter";
|
||||||
public static final String DEFAULT_EXCEPTION_TRANSLATION_FILTER_ID = "_exceptionTranslationFilter";
|
public static final String DEFAULT_EXCEPTION_TRANSLATION_FILTER_ID = "_exceptionTranslationFilter";
|
||||||
public static final String DEFAULT_FILTER_SECURITY_INTERCEPTOR_ID = "_filterSecurityInterceptor";
|
public static final String DEFAULT_FILTER_SECURITY_INTERCEPTOR_ID = "_filterSecurityInterceptor";
|
||||||
public static final String DEFAULT_FORM_LOGIN_FILTER_ID = "_formLoginFilter";
|
|
||||||
public static final String DEFAULT_FORM_LOGIN_ENTRY_POINT_ID = "_formLoginEntryPoint";
|
|
||||||
|
|
||||||
public static final String LOGOUT_ELEMENT = "logout";
|
public static final String LOGOUT_ELEMENT = "logout";
|
||||||
public static final String FORM_LOGIN_ELEMENT = "form-login";
|
public static final String FORM_LOGIN_ELEMENT = "form-login";
|
||||||
|
public static final String BASIC_AUTH_ELEMENT = "http-basic";
|
||||||
|
|
||||||
|
static final String PATH_PATTERN_ATTRIBUTE = "pattern";
|
||||||
|
static final String PATTERN_TYPE_ATTRIBUTE = "pathType";
|
||||||
|
static final String PATTERN_TYPE_REGEX = "regex";
|
||||||
|
|
||||||
|
static final String FILTERS_ATTRIBUTE = "filters";
|
||||||
|
static final String NO_FILTERS_VALUE = "none";
|
||||||
|
static final Filter[] EMPTY_FILTER_CHAIN = new Filter[0];
|
||||||
|
|
||||||
private static final String PATH_ATTRIBUTE = "path";
|
|
||||||
private static final String FILTERS_ATTRIBUTE = "filters";
|
|
||||||
private static final String ACCESS_CONFIG_ATTRIBUTE = "access";
|
private static final String ACCESS_CONFIG_ATTRIBUTE = "access";
|
||||||
|
|
||||||
private static final String LOGIN_URL_ATTRIBUTE = "loginUrl";
|
|
||||||
|
|
||||||
private static final String FORM_LOGIN_TARGET_URL_ATTRIBUTE = "defaultTargetUrl";
|
|
||||||
private static final String DEFAULT_FORM_LOGIN_TARGET_URL = "/index";
|
|
||||||
|
|
||||||
private static final String FORM_LOGIN_AUTH_FAILURE_URL_ATTRIBUTE = "defaultTargetUrl";
|
|
||||||
// TODO: Change AbstractProcessingFilter to not need a failure URL and just write a failure message
|
|
||||||
// to the response if one isn't set.
|
|
||||||
private static final String DEFAULT_FORM_LOGIN_AUTH_FAILURE_URL = "/loginError";
|
|
||||||
|
|
||||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||||
// Create HttpSCIF, FilterInvocationInterceptor, ExceptionTranslationFilter
|
|
||||||
|
|
||||||
// Find other filter beans.
|
|
||||||
|
|
||||||
// Create appropriate bean list for config attributes to create FIDS
|
|
||||||
|
|
||||||
// Add any secure URLs with specific filter chains to FIDS as separate ConfigAttributes
|
|
||||||
|
|
||||||
// Add secure URLS with roles to objectDefinitionSource for FilterSecurityInterceptor
|
|
||||||
|
|
||||||
RootBeanDefinition filterChainProxy = new RootBeanDefinition(FilterChainProxy.class);
|
RootBeanDefinition filterChainProxy = new RootBeanDefinition(FilterChainProxy.class);
|
||||||
|
|
||||||
RootBeanDefinition httpSCIF = new RootBeanDefinition(HttpSessionContextIntegrationFilter.class);
|
RootBeanDefinition httpSCIF = new RootBeanDefinition(HttpSessionContextIntegrationFilter.class);
|
||||||
|
|
||||||
//TODO: Set session creation parameters based on session-creation attribute
|
//TODO: Set session creation parameters based on session-creation attribute
|
||||||
|
@ -79,22 +61,28 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||||
BeanDefinitionBuilder filterSecurityInterceptorBuilder
|
BeanDefinitionBuilder filterSecurityInterceptorBuilder
|
||||||
= BeanDefinitionBuilder.rootBeanDefinition(FilterSecurityInterceptor.class);
|
= BeanDefinitionBuilder.rootBeanDefinition(FilterSecurityInterceptor.class);
|
||||||
|
|
||||||
|
|
||||||
BeanDefinitionBuilder exceptionTranslationFilterBuilder
|
BeanDefinitionBuilder exceptionTranslationFilterBuilder
|
||||||
= BeanDefinitionBuilder.rootBeanDefinition(ExceptionTranslationFilter.class);
|
= BeanDefinitionBuilder.rootBeanDefinition(ExceptionTranslationFilter.class);
|
||||||
|
|
||||||
// Autowire for entry point (for now)
|
// Autowire for entry point (for now)
|
||||||
|
// TODO: Examine entry point beans in post processing and pick the correct one
|
||||||
|
// i.e. form login or cas if defined, then any other non-basic, non-digest, then basic or digest
|
||||||
exceptionTranslationFilterBuilder.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE);
|
exceptionTranslationFilterBuilder.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE);
|
||||||
|
|
||||||
// TODO: Get path type attribute and determine FilDefInvS class
|
// TODO: Get path type attribute and determine FilDefInvS class
|
||||||
PathBasedFilterInvocationDefinitionMap filterChainInvocationDefSource
|
|
||||||
= new PathBasedFilterInvocationDefinitionMap();
|
|
||||||
|
|
||||||
filterChainProxy.getPropertyValues().addPropertyValue("filterInvocationDefinitionSource",
|
FilterChainMap filterChainMap = new FilterChainMap();
|
||||||
filterChainInvocationDefSource);
|
|
||||||
|
|
||||||
PathBasedFilterInvocationDefinitionMap interceptorFilterInvDefSource
|
String patternType = element.getAttribute(PATTERN_TYPE_ATTRIBUTE);
|
||||||
= new PathBasedFilterInvocationDefinitionMap();
|
|
||||||
|
FilterInvocationDefinitionMap interceptorFilterInvDefSource = new PathBasedFilterInvocationDefinitionMap();
|
||||||
|
|
||||||
|
if (patternType.equals(PATTERN_TYPE_REGEX)) {
|
||||||
|
filterChainMap.setUrlPathMatcher(new RegexUrlPathMatcher());
|
||||||
|
interceptorFilterInvDefSource = new RegExpBasedFilterInvocationDefinitionMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
filterChainProxy.getPropertyValues().addPropertyValue("filterChainMap", filterChainMap);
|
||||||
|
|
||||||
filterSecurityInterceptorBuilder.addPropertyValue("objectDefinitionSource", interceptorFilterInvDefSource);
|
filterSecurityInterceptorBuilder.addPropertyValue("objectDefinitionSource", interceptorFilterInvDefSource);
|
||||||
|
|
||||||
|
@ -102,7 +90,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||||
filterSecurityInterceptorBuilder.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE);
|
filterSecurityInterceptorBuilder.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE);
|
||||||
|
|
||||||
parseInterceptUrls(DomUtils.getChildElementsByTagName(element, "intercept-url"),
|
parseInterceptUrls(DomUtils.getChildElementsByTagName(element, "intercept-url"),
|
||||||
filterChainInvocationDefSource, interceptorFilterInvDefSource);
|
filterChainMap, interceptorFilterInvDefSource);
|
||||||
// TODO: if empty, set a default set a default /**, omitting login url
|
// TODO: if empty, set a default set a default /**, omitting login url
|
||||||
|
|
||||||
BeanDefinitionRegistry registry = parserContext.getRegistry();
|
BeanDefinitionRegistry registry = parserContext.getRegistry();
|
||||||
|
@ -110,52 +98,21 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||||
Element logoutElt = DomUtils.getChildElementByTagName(element, LOGOUT_ELEMENT);
|
Element logoutElt = DomUtils.getChildElementByTagName(element, LOGOUT_ELEMENT);
|
||||||
|
|
||||||
if (logoutElt != null) {
|
if (logoutElt != null) {
|
||||||
BeanDefinition logoutFilter = new LogoutBeanDefinitionParser().parse(logoutElt, parserContext);
|
new LogoutBeanDefinitionParser().parse(logoutElt, parserContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
Element formLoginElt = DomUtils.getChildElementByTagName(element, FORM_LOGIN_ELEMENT);
|
Element formLoginElt = DomUtils.getChildElementByTagName(element, FORM_LOGIN_ELEMENT);
|
||||||
|
|
||||||
if (formLoginElt != null) {
|
if (formLoginElt != null) {
|
||||||
BeanDefinitionBuilder formLoginFilterBuilder =
|
new FormLoginBeanDefinitionParser().parse(formLoginElt, parserContext);
|
||||||
BeanDefinitionBuilder.rootBeanDefinition(AuthenticationProcessingFilter.class);
|
|
||||||
BeanDefinitionBuilder formLoginEntryPointBuilder =
|
|
||||||
BeanDefinitionBuilder.rootBeanDefinition(AuthenticationProcessingFilterEntryPoint.class);
|
|
||||||
|
|
||||||
// Temporary login value
|
|
||||||
formLoginEntryPointBuilder.addPropertyValue("loginFormUrl", "/login");
|
|
||||||
|
|
||||||
|
|
||||||
String loginUrl = formLoginElt.getAttribute(LOGIN_URL_ATTRIBUTE);
|
|
||||||
|
|
||||||
if (StringUtils.hasText(loginUrl)) {
|
|
||||||
formLoginFilterBuilder.addPropertyValue("filterProcessesUrl", loginUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
String defaultTargetUrl = formLoginElt.getAttribute(FORM_LOGIN_TARGET_URL_ATTRIBUTE);
|
|
||||||
|
|
||||||
if (!StringUtils.hasText(defaultTargetUrl)) {
|
|
||||||
defaultTargetUrl = DEFAULT_FORM_LOGIN_TARGET_URL;
|
|
||||||
}
|
|
||||||
|
|
||||||
formLoginFilterBuilder.addPropertyValue("defaultTargetUrl", defaultTargetUrl);
|
|
||||||
|
|
||||||
String authenticationFailureUrl = formLoginElt.getAttribute(FORM_LOGIN_AUTH_FAILURE_URL_ATTRIBUTE);
|
|
||||||
|
|
||||||
if (!StringUtils.hasText(authenticationFailureUrl)) {
|
|
||||||
authenticationFailureUrl = DEFAULT_FORM_LOGIN_AUTH_FAILURE_URL;
|
|
||||||
}
|
|
||||||
|
|
||||||
formLoginFilterBuilder.addPropertyValue("authenticationFailureUrl", authenticationFailureUrl);
|
|
||||||
// Set autowire to pick up the authentication manager.
|
|
||||||
formLoginFilterBuilder.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE);
|
|
||||||
|
|
||||||
|
|
||||||
registry.registerBeanDefinition(DEFAULT_FORM_LOGIN_FILTER_ID,
|
|
||||||
formLoginFilterBuilder.getBeanDefinition());
|
|
||||||
registry.registerBeanDefinition(DEFAULT_FORM_LOGIN_ENTRY_POINT_ID,
|
|
||||||
formLoginEntryPointBuilder.getBeanDefinition());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Element basicAuthElt = DomUtils.getChildElementByTagName(element, BASIC_AUTH_ELEMENT);
|
||||||
|
|
||||||
|
if (basicAuthElt != null) {
|
||||||
|
new BasicAuthenticationBeanDefinitionParser().parse(basicAuthElt, parserContext);
|
||||||
|
}
|
||||||
|
|
||||||
registry.registerBeanDefinition(DEFAULT_FILTER_CHAIN_PROXY_ID, filterChainProxy);
|
registry.registerBeanDefinition(DEFAULT_FILTER_CHAIN_PROXY_ID, filterChainProxy);
|
||||||
registry.registerBeanDefinition(DEFAULT_HTTP_SESSION_FILTER_ID, httpSCIF);
|
registry.registerBeanDefinition(DEFAULT_HTTP_SESSION_FILTER_ID, httpSCIF);
|
||||||
registry.registerBeanDefinition(DEFAULT_EXCEPTION_TRANSLATION_FILTER_ID,
|
registry.registerBeanDefinition(DEFAULT_EXCEPTION_TRANSLATION_FILTER_ID,
|
||||||
|
@ -168,15 +125,16 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||||
// app context has been created and all beans are available.
|
// app context has been created and all beans are available.
|
||||||
|
|
||||||
registry.registerBeanDefinition("__httpConfigBeanFactoryPostProcessor",
|
registry.registerBeanDefinition("__httpConfigBeanFactoryPostProcessor",
|
||||||
new RootBeanDefinition(HttpSecurityConfigPostProcessor.class));
|
new RootBeanDefinition(HttpSecurityConfigPostProcessor.class));
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the intercept-url elements and populates the FilterChainProxy's FilterInvocationDefinitionSource
|
* Parses the intercept-url elements and populates the FilterChainProxy's FilterChainMap and the
|
||||||
|
* FilterInvocationDefinitionSource used in FilterSecurityInterceptor.
|
||||||
*/
|
*/
|
||||||
private void parseInterceptUrls(List urlElts, FilterInvocationDefinitionMap filterChainInvocationDefSource,
|
private void parseInterceptUrls(List urlElts, FilterChainMap filterChainMap,
|
||||||
FilterInvocationDefinitionMap interceptorFilterInvDefSource) {
|
FilterInvocationDefinitionMap interceptorFilterInvDefSource) {
|
||||||
|
|
||||||
Iterator urlEltsIterator = urlElts.iterator();
|
Iterator urlEltsIterator = urlElts.iterator();
|
||||||
|
@ -186,7 +144,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||||
while (urlEltsIterator.hasNext()) {
|
while (urlEltsIterator.hasNext()) {
|
||||||
Element urlElt = (Element) urlEltsIterator.next();
|
Element urlElt = (Element) urlEltsIterator.next();
|
||||||
|
|
||||||
String path = urlElt.getAttribute(PATH_ATTRIBUTE);
|
String path = urlElt.getAttribute(PATH_PATTERN_ATTRIBUTE);
|
||||||
|
|
||||||
Assert.hasText(path, "path attribute cannot be empty or null");
|
Assert.hasText(path, "path attribute cannot be empty or null");
|
||||||
|
|
||||||
|
@ -204,11 +162,12 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
||||||
String filters = urlElt.getAttribute(FILTERS_ATTRIBUTE);
|
String filters = urlElt.getAttribute(FILTERS_ATTRIBUTE);
|
||||||
|
|
||||||
if (StringUtils.hasText(filters)) {
|
if (StringUtils.hasText(filters)) {
|
||||||
attributeEditor.setAsText(filters);
|
if (!filters.equals(NO_FILTERS_VALUE)) {
|
||||||
|
throw new IllegalStateException("Currently only 'none' is supported as the custom filters attribute");
|
||||||
|
}
|
||||||
|
|
||||||
|
filterChainMap.addSecureUrl(path, EMPTY_FILTER_CHAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,22 @@
|
||||||
package org.springframework.security.config;
|
package org.springframework.security.config;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.core.OrderComparator;
|
||||||
import org.springframework.security.util.FilterChainProxy;
|
import org.springframework.core.Ordered;
|
||||||
import org.springframework.security.context.HttpSessionContextIntegrationFilter;
|
|
||||||
import org.springframework.security.AuthenticationManager;
|
import org.springframework.security.AuthenticationManager;
|
||||||
|
import org.springframework.security.context.HttpSessionContextIntegrationFilter;
|
||||||
|
import org.springframework.security.intercept.web.FilterChainMap;
|
||||||
|
import org.springframework.security.ui.AuthenticationEntryPoint;
|
||||||
|
import org.springframework.security.util.FilterChainProxy;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import javax.servlet.Filter;
|
import javax.servlet.Filter;
|
||||||
import java.util.Map;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responsible for tying up the HTTP security configuration - building ordered filter stack and linking up
|
* Responsible for tying up the HTTP security configuration - building ordered filter stack and linking up
|
||||||
|
@ -18,36 +25,96 @@ import java.util.Map;
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor {
|
public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor, Ordered {
|
||||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
private Log logger = LogFactory.getLog(getClass());
|
||||||
FilterChainProxy filterChainProxy =
|
|
||||||
(FilterChainProxy) beanFactory.getBean(HttpSecurityBeanDefinitionParser.DEFAULT_FILTER_CHAIN_PROXY_ID);
|
|
||||||
|
|
||||||
|
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||||
HttpSessionContextIntegrationFilter httpSCIF = (HttpSessionContextIntegrationFilter)
|
HttpSessionContextIntegrationFilter httpSCIF = (HttpSessionContextIntegrationFilter)
|
||||||
beanFactory.getBean(HttpSecurityBeanDefinitionParser.DEFAULT_HTTP_SESSION_FILTER_ID);
|
beanFactory.getBean(HttpSecurityBeanDefinitionParser.DEFAULT_HTTP_SESSION_FILTER_ID);
|
||||||
|
|
||||||
AuthenticationManager authManager =
|
AuthenticationManager authManager =
|
||||||
(AuthenticationManager) getBeanOfType(AuthenticationManager.class, beanFactory);
|
(AuthenticationManager) getBeanOfType(AuthenticationManager.class, beanFactory);
|
||||||
|
|
||||||
|
configureAuthenticationEntryPoint(beanFactory);
|
||||||
|
|
||||||
//
|
configureFilterChain(beanFactory);
|
||||||
Map filters = beanFactory.getBeansOfType(Filter.class);
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects the entry point that should be used in ExceptionTranslationFilter. Strategy is
|
||||||
|
*
|
||||||
|
* <ol>
|
||||||
|
* <li>If only one use that.</li>
|
||||||
|
* <li>If more than one, check the default interactive login Ids in order of preference</li>
|
||||||
|
* <li>throw an exception (for now). TODO: Examine additional beans and types and make decision</li>
|
||||||
|
* </ol>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param beanFactory
|
||||||
|
*/
|
||||||
|
private void configureAuthenticationEntryPoint(ConfigurableListableBeanFactory beanFactory) {
|
||||||
|
logger.info("Selecting AuthenticationEntryPoint for use in ExceptionTranslationFilter");
|
||||||
|
|
||||||
|
BeanDefinition etf =
|
||||||
|
beanFactory.getBeanDefinition(HttpSecurityBeanDefinitionParser.DEFAULT_EXCEPTION_TRANSLATION_FILTER_ID);
|
||||||
|
Map entryPointMap = beanFactory.getBeansOfType(AuthenticationEntryPoint.class);
|
||||||
|
List entryPoints = new ArrayList(entryPointMap.values());
|
||||||
|
|
||||||
|
Assert.isTrue(entryPoints.size() > 0, "No AuthenticationEntryPoint instances defined");
|
||||||
|
|
||||||
|
AuthenticationEntryPoint mainEntryPoint = (AuthenticationEntryPoint)
|
||||||
|
entryPointMap.get(FormLoginBeanDefinitionParser.DEFAULT_FORM_LOGIN_ENTRY_POINT_ID);
|
||||||
|
|
||||||
|
if (mainEntryPoint == null) {
|
||||||
|
throw new SecurityConfigurationException("Failed to resolve authentication entry point");
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("Main AuthenticationEntryPoint set to " + mainEntryPoint);
|
||||||
|
|
||||||
|
etf.getPropertyValues().addPropertyValue("authenticationEntryPoint", mainEntryPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configureFilterChain(ConfigurableListableBeanFactory beanFactory) {
|
private void configureFilterChain(ConfigurableListableBeanFactory beanFactory) {
|
||||||
|
FilterChainProxy filterChainProxy =
|
||||||
|
(FilterChainProxy) beanFactory.getBean(HttpSecurityBeanDefinitionParser.DEFAULT_FILTER_CHAIN_PROXY_ID);
|
||||||
|
// Set the default match
|
||||||
|
List defaultFilterChain = orderFilters(beanFactory);
|
||||||
|
|
||||||
|
FilterChainMap filterMap = filterChainProxy.getFilterChainMap();
|
||||||
|
|
||||||
|
String allUrlsMatch = filterMap.getMatcher().getUniversalMatchPattern();
|
||||||
|
|
||||||
|
filterMap.addSecureUrl(allUrlsMatch, (Filter[]) defaultFilterChain.toArray(new Filter[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List orderFilters(ConfigurableListableBeanFactory beanFactory) {
|
||||||
|
Map filters = beanFactory.getBeansOfType(Filter.class);
|
||||||
|
|
||||||
|
Assert.notEmpty(filters, "No filters found in app context!");
|
||||||
|
|
||||||
|
Iterator ids = filters.keySet().iterator();
|
||||||
|
|
||||||
|
List orderedFilters = new ArrayList();
|
||||||
|
|
||||||
|
while (ids.hasNext()) {
|
||||||
|
String id = (String) ids.next();
|
||||||
|
Filter filter = (Filter) filters.get(id);
|
||||||
|
|
||||||
|
if (filter instanceof FilterChainProxy) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(filter instanceof Ordered)) {
|
||||||
|
// TODO: Possibly log this as a warning and skip this filter.
|
||||||
|
throw new IllegalArgumentException("Filter " + id + " must implement the Ordered interface");
|
||||||
|
}
|
||||||
|
|
||||||
|
orderedFilters.add(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.sort(orderedFilters, new OrderComparator());
|
||||||
|
|
||||||
|
return orderedFilters;
|
||||||
|
}
|
||||||
|
|
||||||
private Object getBeanOfType(Class clazz, ConfigurableListableBeanFactory beanFactory) {
|
private Object getBeanOfType(Class clazz, ConfigurableListableBeanFactory beanFactory) {
|
||||||
Map beans = beanFactory.getBeansOfType(clazz);
|
Map beans = beanFactory.getBeansOfType(clazz);
|
||||||
|
@ -56,4 +123,8 @@ public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor
|
||||||
|
|
||||||
return beans.values().toArray()[0];
|
return beans.values().toArray()[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getOrder() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
package org.springframework.security.ui.webapp;
|
||||||
|
|
||||||
|
import org.springframework.security.AuthenticationException;
|
||||||
|
import org.springframework.security.ui.AbstractProcessingFilter;
|
||||||
|
import org.springframework.security.ui.FilterChainOrderUtils;
|
||||||
|
import org.springframework.security.ui.SpringSecurityFilter;
|
||||||
|
import org.springframework.security.ui.rememberme.TokenBasedRememberMeServices;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For internal use with namespace configuration in the case where a user doesn't configure a login page.
|
||||||
|
* The configuration code will insert this filter in the chain instead.
|
||||||
|
*
|
||||||
|
* Will only work if a redirect is used to the login page.
|
||||||
|
*
|
||||||
|
* @author Luke Taylor
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class DefaultLoginPageGeneratingFilter extends SpringSecurityFilter {
|
||||||
|
public static final String DEFAULT_LOGIN_PAGE_URL = "/login";
|
||||||
|
private String authenticationUrl;
|
||||||
|
private String usernameParameter;
|
||||||
|
private String passwordParameter;
|
||||||
|
private String rememberMeParameter;
|
||||||
|
|
||||||
|
public DefaultLoginPageGeneratingFilter(AuthenticationProcessingFilter authFilter) {
|
||||||
|
authenticationUrl = authFilter.getDefaultFilterProcessesUrl();
|
||||||
|
usernameParameter = authFilter.getUsernameParameter();
|
||||||
|
passwordParameter = authFilter.getPasswordParameter();
|
||||||
|
|
||||||
|
if (authFilter.getRememberMeServices() instanceof TokenBasedRememberMeServices) {
|
||||||
|
rememberMeParameter = ((TokenBasedRememberMeServices)authFilter.getRememberMeServices()).getParameter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||||
|
if (isLoginUrlRequest(request)) {
|
||||||
|
response.getOutputStream().print(generateLoginPageHtml(request));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generateLoginPageHtml(HttpServletRequest request) {
|
||||||
|
boolean loginError = StringUtils.hasText(request.getParameter("login_error"));
|
||||||
|
String errorMsg = "none";
|
||||||
|
String lastUser = "";
|
||||||
|
|
||||||
|
if (loginError) {
|
||||||
|
HttpSession session = request.getSession(false);
|
||||||
|
|
||||||
|
if(session != null) {
|
||||||
|
errorMsg = ((AuthenticationException)
|
||||||
|
session.getAttribute(AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY)).getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "<html><head><title>Login Page</title></head><body>\n" +
|
||||||
|
(loginError ? ("<font color='red'>Your login attempt was not successful, try again.<br/><br/>Reason: " +
|
||||||
|
errorMsg + "</font>") : "") +
|
||||||
|
" <form action='" + request.getContextPath() + authenticationUrl + "' method='POST'>\n" +
|
||||||
|
" <table>\n" +
|
||||||
|
" <tr><td>User:</td><td><input type='text' name='" + usernameParameter + "' value='" + lastUser +
|
||||||
|
"'></td></tr>\n" +
|
||||||
|
" <tr><td>Password:</td><td><input type='password' name='"+ passwordParameter +"'></td></tr>\n" +
|
||||||
|
|
||||||
|
(rememberMeParameter == null ? "" :
|
||||||
|
" <tr><td><input type='checkbox' name='"+ rememberMeParameter +
|
||||||
|
"'></td><td>Remember me on this computer.</td></tr>\n"
|
||||||
|
) +
|
||||||
|
" <tr><td colspan='2'><input name=\"submit\" type=\"submit\"></td></tr>\n" +
|
||||||
|
" <tr><td colspan='2'><input name=\"reset\" type=\"reset\"></td></tr>\n" +
|
||||||
|
" </table>\n" +
|
||||||
|
" </form></body></html>";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getOrder() {
|
||||||
|
return FilterChainOrderUtils.LOGIN_PAGE_FILTER_ORDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isLoginUrlRequest(HttpServletRequest request) {
|
||||||
|
String uri = request.getRequestURI();
|
||||||
|
int pathParamIndex = uri.indexOf(';');
|
||||||
|
|
||||||
|
if (pathParamIndex > 0) {
|
||||||
|
// strip everything after the first semi-colon
|
||||||
|
uri = uri.substring(0, pathParamIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("".equals(request.getContextPath())) {
|
||||||
|
return uri.endsWith(DEFAULT_LOGIN_PAGE_URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return uri.endsWith(request.getContextPath() + DEFAULT_LOGIN_PAGE_URL);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,21 @@
|
||||||
package org.springframework.security.config;
|
package org.springframework.security.config;
|
||||||
|
|
||||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
import org.junit.AfterClass;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||||
|
import org.springframework.security.context.HttpSessionContextIntegrationFilter;
|
||||||
|
import org.springframework.security.intercept.web.FilterChainMap;
|
||||||
|
import org.springframework.security.intercept.web.FilterSecurityInterceptor;
|
||||||
|
import org.springframework.security.ui.ExceptionTranslationFilter;
|
||||||
|
import org.springframework.security.ui.basicauth.BasicProcessingFilter;
|
||||||
|
import org.springframework.security.ui.logout.LogoutFilter;
|
||||||
|
import org.springframework.security.ui.webapp.AuthenticationProcessingFilter;
|
||||||
|
import org.springframework.security.ui.webapp.DefaultLoginPageGeneratingFilter;
|
||||||
|
import org.springframework.security.util.FilterChainProxy;
|
||||||
|
|
||||||
|
import javax.servlet.Filter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
|
@ -16,8 +29,44 @@ public class HttpSecurityBeanDefinitionParserTests {
|
||||||
appContext = new ClassPathXmlApplicationContext("org/springframework/security/config/http-security.xml");
|
appContext = new ClassPathXmlApplicationContext("org/springframework/security/config/http-security.xml");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@AfterClass
|
||||||
public void testContextContainsExpectedBeansAndData() {
|
public static void closeAppContext() {
|
||||||
|
if (appContext != null) {
|
||||||
|
appContext.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void filterChainProxyShouldReturnEmptyFilterListForUnprotectedUrl() {
|
||||||
|
FilterChainProxy filterChainProxy =
|
||||||
|
(FilterChainProxy) appContext.getBean(HttpSecurityBeanDefinitionParser.DEFAULT_FILTER_CHAIN_PROXY_ID);
|
||||||
|
|
||||||
|
FilterChainMap filterChainMap = filterChainProxy.getFilterChainMap();
|
||||||
|
|
||||||
|
Filter[] filters = filterChainMap.getFilters("/unprotected");
|
||||||
|
|
||||||
|
assertTrue(filters.length == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void filterChainProxyShouldReturnCorrectFilterListForProtectedUrl() {
|
||||||
|
FilterChainProxy filterChainProxy =
|
||||||
|
(FilterChainProxy) appContext.getBean(HttpSecurityBeanDefinitionParser.DEFAULT_FILTER_CHAIN_PROXY_ID);
|
||||||
|
|
||||||
|
FilterChainMap filterChainMap = filterChainProxy.getFilterChainMap();
|
||||||
|
|
||||||
|
Filter[] filters = filterChainMap.getFilters("/someurl");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
assertTrue("Expected 7 filters in chain", filters.length == 7);
|
||||||
|
|
||||||
|
assertTrue(filters[0] instanceof HttpSessionContextIntegrationFilter);
|
||||||
|
assertTrue(filters[1] instanceof LogoutFilter);
|
||||||
|
assertTrue(filters[2] instanceof AuthenticationProcessingFilter);
|
||||||
|
assertTrue(filters[3] instanceof DefaultLoginPageGeneratingFilter);
|
||||||
|
assertTrue(filters[4] instanceof BasicProcessingFilter);
|
||||||
|
assertTrue(filters[5] instanceof ExceptionTranslationFilter);
|
||||||
|
assertTrue(filters[6] instanceof FilterSecurityInterceptor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,20 +6,22 @@
|
||||||
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">
|
||||||
|
|
||||||
<security:autoconfig />
|
<security:autoconfig />
|
||||||
|
|
||||||
<security:http createSession="ifRequired" pathType="ant" lowerCaseComparisons="true">
|
<security:http createSession="ifRequired" pathType="ant" lowerCaseComparisons="true">
|
||||||
<security:intercept-url path="/unprotected" filters="none"/>
|
<security:intercept-url pattern="/unprotected" filters="none"/>
|
||||||
<security:intercept-url path="/somepath" filters="filter1,filter2,filter3" access="ROLE_SPECIAL,ROLE_USER" />
|
<security:intercept-url pattern="/somepath" access="ROLE_SPECIAL,ROLE_USER" />
|
||||||
<security:intercept-url path="/**" access="ROLE_USER" />
|
<security:intercept-url pattern="/**" access="ROLE_USER" />
|
||||||
|
|
||||||
|
<!-- Default logout configuration -->
|
||||||
|
<security:logout logoutUrl="/j_spring_security_logout" logoutSuccessUrl="/" invalidateSession="true" />
|
||||||
|
|
||||||
<!-- Default form login configuration. Will create filter and entry point -->
|
<!-- Default form login configuration. Will create filter and entry point -->
|
||||||
<security:form-login loginUrl="/j_spring_security_check" />
|
<security:form-login loginUrl="/j_spring_security_check" />
|
||||||
|
|
||||||
<!-- Default logout configuration -->
|
<!-- Default basic auth configuration. Will create filter and entry point -->
|
||||||
<security:logout logoutUrl="/j_spring_security_logout" logoutSuccessUrl="/" invalidateSession="true" />
|
<security:http-basic realm="NamespaceTestRealm" />
|
||||||
|
</security:http>
|
||||||
</security:http>
|
|
||||||
|
|
||||||
|
|
||||||
<security:authentication-provider>
|
<security:authentication-provider>
|
||||||
|
@ -27,6 +29,6 @@ http://www.springframework.org/schema/security http://www.springframework.org/sc
|
||||||
<security:user name="bob" password="bobspassword" authorities="ROLE_A,ROLE_B" />
|
<security:user name="bob" password="bobspassword" authorities="ROLE_A,ROLE_B" />
|
||||||
<security:user name="bill" password="billspassword" authorities="ROLE_A,ROLE_B,AUTH_OTHER" />
|
<security:user name="bill" password="billspassword" authorities="ROLE_A,ROLE_B,AUTH_OTHER" />
|
||||||
</security:user-service>
|
</security:user-service>
|
||||||
</security:authentication-provider>
|
</security:authentication-provider>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
Loading…
Reference in New Issue