SEC-582: Namespace configuration implementation for remember-me support.

This commit is contained in:
Luke Taylor 2007-11-06 23:20:25 +00:00
parent b868143fb1
commit 9f2bc9a842
14 changed files with 275 additions and 36 deletions

View File

@ -4,12 +4,13 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.security.AccessDecisionManager;
import org.springframework.security.AuthenticationManager;
import org.springframework.security.providers.ProviderManager;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.vote.AffirmativeBased;
import org.springframework.security.vote.AuthenticatedVoter;
import org.springframework.security.vote.RoleVoter;
@ -93,6 +94,20 @@ public abstract class ConfigUtils {
getAuthenticationManager(beanFactory));
}
static UserDetailsService getUserDetailsService(ConfigurableListableBeanFactory bf) {
Map services = bf.getBeansOfType(UserDetailsService.class);
if (services.size() == 0) {
throw new IllegalArgumentException("No UserDetailsService registered.");
} else if (services.size() > 1) {
throw new IllegalArgumentException("More than one UserDetailsService registered. Please" +
"use a specific Id in yur configuration");
}
return (UserDetailsService) services.values().toArray()[0];
}
private static AuthenticationManager getAuthenticationManager(ConfigurableListableBeanFactory bf) {
Map authManagers = bf.getBeansOfType(AuthenticationManager.class);

View File

@ -29,7 +29,7 @@ public class FormLoginBeanDefinitionParser implements BeanDefinitionParser {
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 DEFAULT_FORM_LOGIN_TARGET_URL = "/";
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
@ -38,8 +38,13 @@ public class FormLoginBeanDefinitionParser implements BeanDefinitionParser {
public BeanDefinition parse(Element elt, ParserContext parserContext) {
ConfigUtils.registerProviderManagerIfNecessary(parserContext);
BeanDefinition filterBean = createFilterBean(elt);
filterBean.getPropertyValues().addPropertyValue("authenticationManager",
new RuntimeBeanReference(ConfigUtils.DEFAULT_AUTH_MANAGER_ID));
BeanDefinitionBuilder entryPointBuilder =
BeanDefinitionBuilder.rootBeanDefinition(AuthenticationProcessingFilterEntryPoint.class);
@ -90,8 +95,6 @@ public class FormLoginBeanDefinitionParser implements BeanDefinitionParser {
}
filterBuilder.addPropertyValue("authenticationFailureUrl", authenticationFailureUrl);
// Set autowire to pick up the authentication manager.
filterBuilder.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE);
return filterBuilder.getBeanDefinition();
}

View File

@ -21,7 +21,6 @@ import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
import javax.servlet.Filter;
import java.util.*;
/**
@ -44,6 +43,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
public static final String LOGOUT_ELEMENT = "logout";
public static final String FORM_LOGIN_ELEMENT = "form-login";
public static final String BASIC_AUTH_ELEMENT = "http-basic";
public static final String REMEMBER_ME_ELEMENT = "remember-me";
static final String PATH_PATTERN_ATTRIBUTE = "pattern";
static final String PATTERN_TYPE_ATTRIBUTE = "pathType";
@ -120,6 +120,12 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
new BasicAuthenticationBeanDefinitionParser().parse(basicAuthElt, parserContext);
}
Element rememberMeElt = DomUtils.getChildElementByTagName(element, REMEMBER_ME_ELEMENT);
if (rememberMeElt != null) {
new RememberMeBeanDefinitionParser().parse(rememberMeElt, parserContext);
}
registry.registerBeanDefinition(DEFAULT_FILTER_CHAIN_PROXY_ID, filterChainProxy);
registry.registerBeanDefinition(DEFAULT_HTTP_SESSION_FILTER_ID, httpSCIF);
registry.registerBeanDefinition(DEFAULT_EXCEPTION_TRANSLATION_FILTER_ID,

View File

@ -3,14 +3,17 @@ 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.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.OrderComparator;
import org.springframework.core.Ordered;
import org.springframework.security.AuthenticationManager;
import org.springframework.security.concurrent.ConcurrentSessionFilter;
import org.springframework.security.context.HttpSessionContextIntegrationFilter;
import org.springframework.security.ui.AbstractProcessingFilter;
import org.springframework.security.ui.AuthenticationEntryPoint;
import org.springframework.security.ui.rememberme.RememberMeServices;
import org.springframework.security.util.FilterChainProxy;
import org.springframework.util.Assert;
@ -38,11 +41,55 @@ public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor
ConfigUtils.configureSecurityInterceptor(beanFactory, securityInterceptor);
configureRememberMeSerices(beanFactory);
configureAuthenticationEntryPoint(beanFactory);
configureAuthenticationFilter(beanFactory);
configureFilterChain(beanFactory);
}
private void configureRememberMeSerices(ConfigurableListableBeanFactory beanFactory) {
try {
BeanDefinition rememberMeServices =
beanFactory.getBeanDefinition(RememberMeBeanDefinitionParser.DEFAULT_REMEMBER_ME_SERVICES_ID);
rememberMeServices.getPropertyValues().addPropertyValue("userDetailsService",
ConfigUtils.getUserDetailsService(beanFactory));
BeanDefinition logoutFilter =
beanFactory.getBeanDefinition(HttpSecurityBeanDefinitionParser.DEFAULT_FILTER_SECURITY_INTERCEPTOR_ID);
} catch (NoSuchBeanDefinitionException e) {
// ignore
}
}
/**
* Sets the authentication manager, (and remember-me services, if required) on any instances of
* AbstractProcessingFilter
*/
private void configureAuthenticationFilter(ConfigurableListableBeanFactory beanFactory) {
Map beans = beanFactory.getBeansOfType(RememberMeServices.class);
RememberMeServices rememberMeServices = null;
if (beans.size() > 0) {
rememberMeServices = (RememberMeServices) beans.values().toArray()[0];
}
Iterator authFilters = beanFactory.getBeansOfType(AbstractProcessingFilter.class).values().iterator();
while (authFilters.hasNext()) {
AbstractProcessingFilter filter = (AbstractProcessingFilter) authFilters.next();
if (rememberMeServices != null) {
logger.info("Using RememberMeServices " + rememberMeServices + " with filter " + filter);
filter.setRememberMeServices(rememberMeServices);
}
}
}
/**
* Selects the entry point that should be used in ExceptionTranslationFilter. Strategy is
*
@ -52,7 +99,6 @@ public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor
* <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");
@ -90,6 +136,15 @@ public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor
filterMap.put(allUrlsMatch, defaultFilterChain);
filterChainProxy.setFilterChainMap(filterMap);
Map sessionFilters = beanFactory.getBeansOfType(ConcurrentSessionFilter.class);
if (!sessionFilters.isEmpty()) {
logger.info("Concurrent session filter in use, setting 'forceEagerSessionCreation' to true");
HttpSessionContextIntegrationFilter scif = (HttpSessionContextIntegrationFilter)
beanFactory.getBean(HttpSecurityBeanDefinitionParser.DEFAULT_HTTP_SESSION_FILTER_ID);
scif.setForceEagerSessionCreation(true);
}
}
private List orderFilters(ConfigurableListableBeanFactory beanFactory) {

View File

@ -0,0 +1,72 @@
package org.springframework.security.config;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.ManagedList;
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.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.ui.rememberme.PersistentTokenBasedRememberMeServices;
import org.springframework.security.ui.rememberme.RememberMeProcessingFilter;
import org.springframework.security.ui.rememberme.TokenBasedRememberMeServices;
import org.springframework.security.providers.rememberme.RememberMeAuthenticationProvider;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* @author Luke Taylor
* @version $Id$
*/
public class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
protected final Log logger = LogFactory.getLog(getClass());
public static final String DEFAULT_REMEMBER_ME_FILTER_ID = "_rememberMeFilter";
public static final String DEFAULT_REMEMBER_ME_SERVICES_ID = "_rememberMeServices";
public BeanDefinition parse(Element element, ParserContext parserContext) {
BeanDefinition filter = new RootBeanDefinition(RememberMeProcessingFilter.class);
BeanDefinition services = new RootBeanDefinition(PersistentTokenBasedRememberMeServices.class);
filter.getPropertyValues().addPropertyValue("authenticationManager",
new RuntimeBeanReference(ConfigUtils.DEFAULT_AUTH_MANAGER_ID));
String tokenRepository = element.getAttribute("tokenRepository");
String dataSource = element.getAttribute("dataSource");
if (StringUtils.hasText(tokenRepository)) {
if (StringUtils.hasText(dataSource)) {
throw new SecurityConfigurationException("Specify tokenRepository or dataSource but not both");
}
services.getPropertyValues().addPropertyValue("tokenRepository", new RuntimeBeanReference(tokenRepository));
} else if (StringUtils.hasText(dataSource)) {
BeanDefinition tokenRepo = new RootBeanDefinition(JdbcTokenRepositoryImpl.class);
tokenRepo.getPropertyValues().addPropertyValue("dataSource", new RuntimeBeanReference(dataSource));
} else {
// Not persistent
services = new RootBeanDefinition(TokenBasedRememberMeServices.class);
}
String key = element.getAttribute("key");
services.getPropertyValues().addPropertyValue("key", key);
BeanDefinition authManager = ConfigUtils.registerProviderManagerIfNecessary(parserContext);
BeanDefinition provider = new RootBeanDefinition(RememberMeAuthenticationProvider.class);
provider.getPropertyValues().addPropertyValue("key", key);
ManagedList providers = (ManagedList) authManager.getPropertyValues().getPropertyValue("providers").getValue();
providers.add(provider);
filter.getPropertyValues().addPropertyValue("rememberMeServices",
new RuntimeBeanReference(DEFAULT_REMEMBER_ME_SERVICES_ID));
parserContext.getRegistry().registerBeanDefinition(DEFAULT_REMEMBER_ME_SERVICES_ID, services);
parserContext.getRegistry().registerBeanDefinition(DEFAULT_REMEMBER_ME_FILTER_ID, filter);
return null;
}
}

View File

@ -3,17 +3,20 @@ package org.springframework.security.ui.rememberme;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.security.Authentication;
import org.springframework.security.SpringSecurityMessageSource;
import org.springframework.security.providers.rememberme.RememberMeAuthenticationToken;
import org.springframework.security.ui.AuthenticationDetailsSource;
import org.springframework.security.ui.AuthenticationDetailsSourceImpl;
import org.springframework.security.ui.logout.LogoutHandler;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.context.support.MessageSourceAccessor;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
@ -25,7 +28,7 @@ import javax.servlet.http.HttpServletResponse;
* @author Luke Taylor
* @version $Id$
*/
public abstract class AbstractRememberMeServices implements RememberMeServices {
public abstract class AbstractRememberMeServices implements RememberMeServices, InitializingBean, LogoutHandler {
protected final Log logger = LogFactory.getLog(getClass());
@ -42,7 +45,14 @@ public abstract class AbstractRememberMeServices implements RememberMeServices {
private String parameter = DEFAULT_PARAMETER;
private boolean alwaysRemember;
private String key;
private long tokenValiditySeconds = 1209600; // 14 days
private int tokenValiditySeconds = 1209600; // 14 days
public void afterPropertiesSet() throws Exception {
Assert.hasLength(key);
Assert.hasLength(parameter);
Assert.hasLength(cookieName);
Assert.notNull(userDetailsService);
}
/**
* Template implementation which locates the Spring Security cookie, decodes it into
@ -261,13 +271,21 @@ public abstract class AbstractRememberMeServices implements RememberMeServices {
return cookie;
}
protected Cookie makeValidCookie(String value, HttpServletRequest request, long maxAge) {
protected Cookie makeValidCookie(String value, HttpServletRequest request, int maxAge) {
Cookie cookie = new Cookie(cookieName, value);
cookie.setMaxAge(new Long(maxAge).intValue());
cookie.setMaxAge(maxAge);
cookie.setPath(StringUtils.hasLength(request.getContextPath()) ? request.getContextPath() : "/");
return cookie;
}
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
if (logger.isDebugEnabled()) {
logger.debug( "Logout of user "
+ (authentication == null ? "Unknown" : authentication.getName()));
}
cancelCookie(request, response);
}
public void setCookieName(String cookieName) {
this.cookieName = cookieName;
@ -281,6 +299,10 @@ public abstract class AbstractRememberMeServices implements RememberMeServices {
this.parameter = parameter;
}
public String getParameter() {
return parameter;
}
protected UserDetailsService getUserDetailsService() {
return userDetailsService;
}
@ -293,11 +315,11 @@ public abstract class AbstractRememberMeServices implements RememberMeServices {
this.key = key;
}
public void setTokenValiditySeconds(long tokenValiditySeconds) {
public void setTokenValiditySeconds(int tokenValiditySeconds) {
this.tokenValiditySeconds = tokenValiditySeconds;
}
public long getTokenValiditySeconds() {
public int getTokenValiditySeconds() {
return tokenValiditySeconds;
}

View File

@ -0,0 +1,34 @@
package org.springframework.security.ui.rememberme;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
/**
*
* @author Luke Taylor
* @version $Id$
*/
public class JdbcTokenRepositoryImpl extends JdbcDaoSupport implements PersistentTokenRepository {
//~ Static fields/initializers =====================================================================================
public static final String DEF_TOKEN_BY_SERIES_QUERY =
"select username,series,token from persistent_logins where series = ?";
public static final String DEF_INSERT_TOKEN_STATEMENT =
"insert into persistent_logins (username,series,token) values(?,?,?)";
public static final String DEF_REMOVE_USER_TOKENS_STATEMENT =
"delete from persistent_logins where username = ?";
//~ Instance fields ================================================================================================
private String tokensBySeriesQuery = DEF_TOKEN_BY_SERIES_QUERY;
private String insertTokenStatement = DEF_INSERT_TOKEN_STATEMENT;
private String removeUserTokensStatement = DEF_REMOVE_USER_TOKENS_STATEMENT;
public void saveToken(PersistentRememberMeToken token) {
}
public PersistentRememberMeToken getTokenForSeries(String seriesId) {
return null;
}
public void removeAllTokens(String username) {
}
}

View File

@ -109,7 +109,10 @@ public class PersistentTokenBasedRememberMeServices extends AbstractRememberMeSe
}
private PersistentRememberMeToken createNewToken(String username, String series) {
logger.debug("Creating new persistent login token for user " + username);
if (logger.isDebugEnabled()) {
logger.debug(series == null ? "Creating new" : "Renewing" +
" persistent login token for user " + username);
}
if (series == null) {
byte[] newSeries = new byte[seriesLength];
@ -131,8 +134,7 @@ public class PersistentTokenBasedRememberMeServices extends AbstractRememberMeSe
private void addCookie(PersistentRememberMeToken token, HttpServletRequest request, HttpServletResponse response) {
String cookieValue = encodeCookie(new String[] {token.getSeries(), token.getTokenValue()});
long maxAge = System.currentTimeMillis() + getTokenValiditySeconds() * 1000;
response.addCookie(makeValidCookie(cookieValue, request, maxAge));
response.addCookie(makeValidCookie(cookieValue, request, getTokenValiditySeconds()));
}
public void setTokenRepository(PersistentTokenRepository tokenRepository) {

View File

@ -4,6 +4,7 @@ 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.AbstractRememberMeServices;
import org.springframework.security.ui.rememberme.TokenBasedRememberMeServices;
import org.springframework.util.StringUtils;
@ -35,8 +36,8 @@ public class DefaultLoginPageGeneratingFilter extends SpringSecurityFilter {
usernameParameter = authFilter.getUsernameParameter();
passwordParameter = authFilter.getPasswordParameter();
if (authFilter.getRememberMeServices() instanceof TokenBasedRememberMeServices) {
rememberMeParameter = ((TokenBasedRememberMeServices)authFilter.getRememberMeServices()).getParameter();
if (authFilter.getRememberMeServices() instanceof AbstractRememberMeServices) {
rememberMeParameter = ((AbstractRememberMeServices)authFilter.getRememberMeServices()).getParameter();
}
}

View File

@ -48,7 +48,7 @@ protect.attlist &=
http =
## Container element for HTTP security configuration
element http {http.attlist, intercept-url+, form-login?, http-basic?, logout?, concurrent-session-control? }
element http {http.attlist, (intercept-url+ & form-login? & http-basic? & logout? & concurrent-session-control? & remember-me?) }
http.attlist &=
## Controls the eagerness with which an HTTP session is created.
[ a:defaultValue = "ifRequired" ] attribute createSession {"ifRequired" | "always" | "never" }?
@ -135,6 +135,13 @@ concurrent-sessions.attlist &=
concurrent-sessions.attlist &=
attribute exceptionIfMaximumExceeded {"true" | "false"}?
remember-me =
element remember-me {remember-me.attlist}
remember-me.attlist &=
attribute key {xsd:string}
remember-me.attlist &=
(attribute tokenRepository {xsd:string} | attribute datasource {xsd:string})?
authentication-provider =
element authentication-provider {authentication-provider.attlist, (user-service | jdbc-user-service)}
authentication-provider.attlist &= empty
@ -144,7 +151,6 @@ user-service =
user-service.attlist &=
attribute properties {xsd:string}*
user =
element user {user.attlist, empty}
user.attlist &=

View File

@ -72,13 +72,14 @@
<xs:documentation>Container element for HTTP security configuration</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="security:intercept-url"/>
<xs:element minOccurs="0" ref="security:form-login"/>
<xs:element minOccurs="0" ref="security:http-basic"/>
<xs:element minOccurs="0" ref="security:logout"/>
<xs:element minOccurs="0" ref="security:concurrent-session-control"/>
</xs:sequence>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="security:intercept-url"/>
<xs:element ref="security:form-login"/>
<xs:element ref="security:http-basic"/>
<xs:element ref="security:logout"/>
<xs:element ref="security:concurrent-session-control"/>
<xs:element ref="security:remember-me"/>
</xs:choice>
<xs:attributeGroup ref="security:http.attlist"/>
</xs:complexType>
</xs:element>
@ -241,6 +242,16 @@
</xs:simpleType>
</xs:attribute>
</xs:attributeGroup>
<xs:element name="remember-me">
<xs:complexType>
<xs:attributeGroup ref="security:remember-me.attlist"/>
</xs:complexType>
</xs:element>
<xs:attributeGroup name="remember-me.attlist">
<xs:attribute name="key" use="required" type="xs:string"/>
<xs:attribute name="tokenRepository" type="xs:string"/>
<xs:attribute name="datasource" type="xs:string"/>
</xs:attributeGroup>
<xs:element name="authentication-provider">
<xs:complexType>
<xs:choice>

View File

@ -1,20 +1,22 @@
package org.springframework.security.config;
import org.junit.AfterClass;
import static org.junit.Assert.assertTrue;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.security.concurrent.ConcurrentSessionFilter;
import org.springframework.security.context.HttpSessionContextIntegrationFilter;
import org.springframework.security.intercept.web.FilterSecurityInterceptor;
import org.springframework.security.ui.ExceptionTranslationFilter;
import org.springframework.security.ui.rememberme.RememberMeProcessingFilter;
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 org.junit.AfterClass;
import static org.junit.Assert.*;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.Iterator;
import java.util.List;
@ -54,7 +56,7 @@ public class HttpSecurityBeanDefinitionParserTests {
List filterList = filterChainProxy.getFilters("/someurl");
assertTrue("Expected 8 filters in chain", filterList.size() == 8);
assertEquals("Expected 9 filters in chain", 9, filterList.size());
Iterator filters = filterList.iterator();
@ -64,6 +66,7 @@ public class HttpSecurityBeanDefinitionParserTests {
assertTrue(filters.next() instanceof AuthenticationProcessingFilter);
assertTrue(filters.next() instanceof DefaultLoginPageGeneratingFilter);
assertTrue(filters.next() instanceof BasicProcessingFilter);
assertTrue(filters.next() instanceof RememberMeProcessingFilter);
assertTrue(filters.next() instanceof ExceptionTranslationFilter);
assertTrue(filters.next() instanceof FilterSecurityInterceptor);
}

View File

@ -7,20 +7,22 @@
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
<security:http createSession="ifRequired" pathType="ant" lowerCaseComparisons="true">
<security:intercept-url pattern="/unprotected" filters="none"/>
<security:intercept-url pattern="/unprotected" filters="none" />
<security:intercept-url pattern="/somepath" access="ROLE_SPECIAL,ROLE_USER" />
<security:intercept-url pattern="/**" access="ROLE_USER" />
<!-- 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 basic auth configuration. Will create filter and entry point -->
<security:http-basic realm="NamespaceTestRealm" />
<security:http-basic realm="NamespaceTestRealm" />
<!-- Default logout configuration -->
<security:logout logoutUrl="/j_spring_security_logout" logoutSuccessUrl="/" invalidateSession="true" />
<security:concurrent-session-control maxSessions="1"/>
<security:remember-me key="doesntmatter" tokenRepository="tokenRepo"/>
</security:http>
<security:authentication-provider>
@ -29,4 +31,9 @@ http://www.springframework.org/schema/security http://www.springframework.org/sc
<security:user name="bill" password="billspassword" authorities="ROLE_A,ROLE_B,AUTH_OTHER" />
</security:user-service>
</security:authentication-provider>
<bean name="tokenRepo" class="org.springframework.security.ui.rememberme.InMemoryTokenRepositoryImpl"/>
<!-- bean name="rememberMeServices" class="org.springframework.security.ui.rememberme.NullRememberMeServices"/ -->
</beans>

View File

@ -22,8 +22,10 @@ http://www.springframework.org/schema/security http://www.springframework.org/sc
<security:logout />
<security:concurrent-session-control maxSessions="1" exceptionIfMaximumExceeded="true"/>
<security:remember-me key="doesntmatter" tokenRepository="tokenRepo"/>
</security:http>
<bean name="tokenRepo" class="org.springframework.security.ui.rememberme.InMemoryTokenRepositoryImpl"/>
<security:authentication-provider>
<security:user-service>