1
0
mirror of synced 2026-07-09 04:40:13 +00:00

Compare commits

..

3 Commits

Author SHA1 Message Date
Ben Alex a899084581 Move to appropriate location. 2008-05-02 10:57:48 +00:00
Ben Alex e8ea1441d7 SEC-811: Backport to 2.0.1. 2008-05-02 10:47:56 +00:00
Luke Taylor 543d2cb007 [maven-release-plugin] copy for tag spring-security-parent-2.0.1 2008-05-01 20:08:33 +00:00
142 changed files with 1745 additions and 3876 deletions
+4 -4
View File
@@ -3,13 +3,13 @@
<parent>
<artifactId>spring-security-parent</artifactId>
<groupId>org.springframework.security</groupId>
<version>2.0.2</version>
<version>2.0.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-acl</artifactId>
<name>Spring Security - ACL module</name>
<version>2.0.2</version>
<version>2.0.1</version>
<packaging>bundle</packaging>
<dependencies>
@@ -48,12 +48,12 @@
<properties>
<spring.osgi.export>
org.springframework.security.*;version=${pom.version.osgi}
org.springframework.security.*;version=${pom.version}
</spring.osgi.export>
<spring.osgi.import>
net.sf.ehcache.*;version="[1.4.1, 2.0.0)";resolution:=optional,
org.springframework.security.*;version="[${pom.version.osgi},${pom.version.osgi}]",
org.springframework.security.*;version="[${pom.version},${pom.version}]",
org.springframework.context.*;version="${spring.version.osgi}",
org.springframework.dao.*;version="${spring.version.osgi}";resolution:=optional,
org.springframework.jdbc.*;version="${spring.version.osgi}";resolution:=optional,
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-adapters</artifactId>
<version>2.0.2</version>
<version>2.0.1</version>
</parent>
<artifactId>spring-security-catalina</artifactId>
<name>Spring Security - Catalina adapter</name>
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-adapters</artifactId>
<version>2.0.2</version>
<version>2.0.1</version>
</parent>
<artifactId>spring-security-jboss</artifactId>
<name>Spring Security - JBoss adapter</name>
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-adapters</artifactId>
<version>2.0.2</version>
<version>2.0.1</version>
</parent>
<artifactId>spring-security-jetty</artifactId>
<name>Spring Security - Jetty adapter</name>
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-parent</artifactId>
<version>2.0.2</version>
<version>2.0.1</version>
</parent>
<artifactId>spring-security-adapters</artifactId>
<name>Spring Security - Adapters</name>
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-adapters</artifactId>
<version>2.0.2</version>
<version>2.0.1</version>
</parent>
<artifactId>spring-security-resin</artifactId>
<name>Spring Security - Resin adapter</name>
+3 -3
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-parent</artifactId>
<version>2.0.2</version>
<version>2.0.1</version>
</parent>
<artifactId>spring-security-cas-client</artifactId>
<name>Spring Security - CAS support</name>
@@ -42,11 +42,11 @@
<properties>
<spring.osgi.export>
org.springframework.security.*;version=${pom.version.osgi}
org.springframework.security.*;version=${pom.version}
</spring.osgi.export>
<spring.osgi.import>
org.springframework.security.*;version="[${pom.version.osgi},${pom.version.osgi}]",
org.springframework.security.*;version="[${pom.version},${pom.version}]",
org.springframework.beans.*;version="${spring.version.osgi}",
org.springframework.context.*;version="${spring.version.osgi}",
org.springframework.dao.*;version="${spring.version.osgi}";resolution:=optional,
@@ -30,14 +30,12 @@ import org.springframework.util.Assert;
/**
* Used by the <code>ExceptionTranslationFilter</code> to commence authentication via the JA-SIG Central
* Authentication Service (CAS).
* <p>
* The user's browser will be redirected to the JA-SIG CAS enterprise-wide login page.
* This page is specified by the <code>loginUrl</code> property. Once login is complete, the CAS login page will
* Used by the <code>SecurityEnforcementFilter</code> to commence authentication via the JA-SIG Central
* Authentication Service (CAS).<P>The user's browser will be redirected to the JA-SIG CAS enterprise-wide login
* page. This page is specified by the <code>loginUrl</code> property. Once login is complete, the CAS login page will
* redirect to the page indicated by the <code>service</code> property. The <code>service</code> is a HTTP URL
* belonging to the current application. The <code>service</code> URL is monitored by the {@link CasProcessingFilter},
* which will validate the CAS login was successful.
* which will validate the CAS login was successful.</p>
*
* @author Ben Alex
* @author Scott Battaglia
@@ -67,8 +65,8 @@ public class CasProcessingFilterEntryPoint implements AuthenticationEntryPoint,
}
public void commence(final ServletRequest servletRequest, final ServletResponse servletResponse,
final AuthenticationException authenticationException) throws IOException, ServletException {
final AuthenticationException authenticationException)
throws IOException, ServletException {
final HttpServletResponse response = (HttpServletResponse) servletResponse;
final String urlEncodedService = CommonUtils.constructServiceUrl(null, response, this.serviceProperties.getService(), null, "ticket", this.encodeServiceUrlWithSessionId);
final String redirectUrl = CommonUtils.constructRedirectUrl(this.loginUrl, "service", urlEncodedService, this.serviceProperties.isSendRenew(), false);
@@ -21,10 +21,9 @@ import org.springframework.util.Assert;
/**
* Stores properties related to this CAS service.
* <p>
* Each web application capable of processing CAS tickets is known as a service.
* <p>Each web application capable of processing CAS tickets is known as a service.
* This class stores the properties that are relevant to the local CAS service, being the application
* that is being secured by Spring Security.
* that is being secured by Spring Security.</p>
*
* @author Ben Alex
* @version $Id$
@@ -43,8 +42,7 @@ public class ServiceProperties implements InitializingBean {
/**
* Represents the service the user is authenticating to.
* <p>
* This service is the callback URL belonging to the local Spring Security System for Spring secured application.
* <p>This service is the callback URL belonging to the local Spring Security System for Spring secured application.
* For example,
* <pre>
* https://www.mycompany.com/application/j_spring_cas_security_check
@@ -58,12 +56,10 @@ public class ServiceProperties implements InitializingBean {
/**
* Indicates whether the <code>renew</code> parameter should be sent to the CAS login URL and CAS
* validation URL.
* <p>
* If <code>true</code>, it will force CAS to authenticate the user again (even if the
* validation URL.<p>If <code>true</code>, it will force CAS to authenticate the user again (even if the
* user has previously authenticated). During ticket validation it will require the ticket was generated as a
* consequence of an explicit login. High security applications would probably set this to <code>true</code>.
* Defaults to <code>false</code>, providing automated single sign on.
* Defaults to <code>false</code>, providing automated single sign on.</p>
*
* @return whether to send the <code>renew</code> parameter to CAS
*/
+2 -2
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-parent</artifactId>
<version>2.0.2</version>
<version>2.0.1</version>
</parent>
<packaging>bundle</packaging>
<artifactId>spring-security-core-tiger</artifactId>
@@ -89,7 +89,7 @@
<spring.osgi.import>
javax.annotation.*;version="[1.0.0, 2.0.0)",
org.springframework.security.*;version="[${pom.version.osgi},${pom.version.osgi}]",
org.springframework.security.*;version="[${pom.version},${pom.version}]",
org.springframework.core.*;version="${spring.version.osgi}"
</spring.osgi.import>
@@ -1,12 +0,0 @@
# Logging
#
# $Id: log4j.properties 2385 2007-12-20 20:53:26Z luke_t $
log4j.rootCategory=DEBUG, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p %c - %m%n
log4j.category.org.springframework.security=DEBUG
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-parent</artifactId>
<version>2.0.2</version>
<version>2.0.1</version>
</parent>
<packaging>bundle</packaging>
<artifactId>spring-security-core</artifactId>
@@ -90,7 +90,7 @@ public class SimpleAttributes2GrantedAuthoritiesMapper implements Attributes2Gra
return attributePrefix == null ? "" : attributePrefix;
}
public void setAttributePrefix(String string) {
public void seAttributePrefix(String string) {
attributePrefix = string;
}
@@ -21,7 +21,6 @@ import org.springframework.security.ui.FilterChainOrder;
import org.springframework.security.ui.SpringSecurityFilter;
import org.springframework.security.ui.logout.LogoutHandler;
import org.springframework.security.ui.logout.SecurityContextLogoutHandler;
import org.springframework.security.util.UrlUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
@@ -61,7 +60,6 @@ public class ConcurrentSessionFilter extends SpringSecurityFilter implements Ini
public void afterPropertiesSet() throws Exception {
Assert.notNull(sessionRegistry, "SessionRegistry required");
Assert.isTrue(UrlUtils.isValidRedirectUrl(expiredUrl), expiredUrl + " isn't a valid redirect URL");
}
public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
@@ -23,12 +23,12 @@ public abstract class AbstractUserDetailsServiceBeanDefinitionParser implements
/** UserDetailsService bean Id. For use in a stateful context (i.e. in AuthenticationProviderBDP) */
private String id;
protected abstract String getBeanClassName(Element element);
protected abstract Class getBeanClass(Element element);
protected abstract void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder);
public BeanDefinition parse(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(getBeanClassName(element));
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(getBeanClass(element));
doParse(element, parserContext, builder);
@@ -3,40 +3,27 @@ package org.springframework.security.config;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* Registers an alias name for the default ProviderManager used by the namespace
* Just registers an alias name for the default ProviderManager used by the namespace
* configuration, allowing users to reference it in their beans and clearly see where the name is
* coming from. Also allows the ConcurrentSessionController to be set on the ProviderManager.
* coming from.
*
* @author Luke Taylor
* @version $Id$
*/
public class AuthenticationManagerBeanDefinitionParser implements BeanDefinitionParser {
private static final String ATT_SESSION_CONTROLLER_REF = "session-controller-ref";
private static final String ATT_ALIAS = "alias";
private static final String ATT_ALIAS = "alias";
public BeanDefinition parse(Element element, ParserContext parserContext) {
BeanDefinition authManager = ConfigUtils.registerProviderManagerIfNecessary(parserContext);
String alias = element.getAttribute(ATT_ALIAS);
if (!StringUtils.hasText(alias)) {
parserContext.getReaderContext().error(ATT_ALIAS + " is required.", element );
}
String sessionControllerRef = element.getAttribute(ATT_SESSION_CONTROLLER_REF);
if (StringUtils.hasText(sessionControllerRef)) {
ConfigUtils.setSessionControllerOnAuthenticationManager(parserContext,
BeanIds.CONCURRENT_SESSION_CONTROLLER, element);
authManager.getPropertyValues().addPropertyValue("sessionController",
new RuntimeBeanReference(sessionControllerRef));
}
parserContext.getRegistry().registerAlias(BeanIds.AUTHENTICATION_MANAGER, alias);
@@ -1,5 +1,7 @@
package org.springframework.security.config;
import org.springframework.beans.factory.config.BeanDefinition;
/**
* Contains all the default Bean IDs created by the namespace support in Spring Security 2.
* <p>
@@ -16,8 +18,7 @@ public abstract class BeanIds {
/** Package protected as end users shouldn't really be using this BFPP directly */
static final String INTERCEPT_METHODS_BEAN_FACTORY_POST_PROCESSOR = "_interceptMethodsBeanfactoryPP";
static final String CONTEXT_SOURCE_SETTING_POST_PROCESSOR = "_contextSettingPostProcessor";
static final String ENTRY_POINT_INJECTION_POST_PROCESSOR = "_entryPointInjectionBeanPostProcessor";
static final String USER_DETAILS_SERVICE_INJECTION_POST_PROCESSOR = "_userServiceInjectionPostProcessor";
static final String HTTP_POST_PROCESSOR = "_httpConfigBeanFactoryPostProcessor";
static final String FILTER_CHAIN_POST_PROCESSOR = "_filterChainProxyPostProcessor";
static final String FILTER_LIST = "_filterChainList";
@@ -62,7 +63,7 @@ public abstract class BeanIds {
public static final String CONTEXT_SOURCE = "_securityContextSource";
public static final String PORT_MAPPER = "_portMapper";
public static final String X509_FILTER = "_x509ProcessingFilter";
public static final String X509_AUTH_PROVIDER = "_x509AuthenticationProvider";
public static final String X509_AUTH_PROVIDER = "_x509AuthenitcationProvider";
public static final String PRE_AUTH_ENTRY_POINT = "_preAuthenticatedProcessingFilterEntryPoint";
public static final String REMEMBER_ME_SERVICES_INJECTION_POST_PROCESSOR = "_rememberMeServicesInjectionBeanPostProcessor";
@@ -29,8 +29,7 @@ public class ConcurrentSessionsBeanDefinitionParser implements BeanDefinitionPar
static final String ATT_EXPIRY_URL = "expired-url";
static final String ATT_MAX_SESSIONS = "max-sessions";
static final String ATT_EXCEPTION_IF_MAX_EXCEEDED = "exception-if-maximum-exceeded";
static final String ATT_SESSION_REGISTRY_ALIAS = "session-registry-alias";
static final String ATT_SESSION_REGISTRY_REF = "session-registry-ref";
static final String ATT_SESSION_REGISTRY_ALIAS = "session-registry-alias";
public BeanDefinition parse(Element element, ParserContext parserContext) {
CompositeComponentDefinition compositeDef =
@@ -39,43 +38,26 @@ public class ConcurrentSessionsBeanDefinitionParser implements BeanDefinitionPar
BeanDefinitionRegistry beanRegistry = parserContext.getRegistry();
String sessionRegistryId = element.getAttribute(ATT_SESSION_REGISTRY_REF);
if (!StringUtils.hasText(sessionRegistryId)) {
RootBeanDefinition sessionRegistry = new RootBeanDefinition(SessionRegistryImpl.class);
beanRegistry.registerBeanDefinition(BeanIds.SESSION_REGISTRY, sessionRegistry);
parserContext.registerComponent(new BeanComponentDefinition(sessionRegistry, BeanIds.SESSION_REGISTRY));
sessionRegistryId = BeanIds.SESSION_REGISTRY;
} else {
// Register the default ID as an alias so that things like session fixation filter can access it
beanRegistry.registerAlias(sessionRegistryId, BeanIds.SESSION_REGISTRY);
}
String registryAlias = element.getAttribute(ATT_SESSION_REGISTRY_ALIAS);
if (StringUtils.hasText(registryAlias)) {
beanRegistry.registerAlias(sessionRegistryId, registryAlias);
}
RootBeanDefinition sessionRegistry = new RootBeanDefinition(SessionRegistryImpl.class);
BeanDefinitionBuilder filterBuilder =
BeanDefinitionBuilder.rootBeanDefinition(ConcurrentSessionFilter.class);
filterBuilder.addPropertyValue("sessionRegistry", new RuntimeBeanReference(sessionRegistryId));
BeanDefinitionBuilder controllerBuilder
= BeanDefinitionBuilder.rootBeanDefinition(ConcurrentSessionControllerImpl.class);
controllerBuilder.addPropertyValue("sessionRegistry", new RuntimeBeanReference(BeanIds.SESSION_REGISTRY));
filterBuilder.addPropertyValue("sessionRegistry", new RuntimeBeanReference(BeanIds.SESSION_REGISTRY));
Object source = parserContext.extractSource(element);
filterBuilder.setSource(source);
filterBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
controllerBuilder.setSource(source);
controllerBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String expiryUrl = element.getAttribute(ATT_EXPIRY_URL);
if (StringUtils.hasText(expiryUrl)) {
ConfigUtils.validateHttpRedirect(expiryUrl, parserContext, source);
filterBuilder.addPropertyValue("expiredUrl", expiryUrl);
}
BeanDefinitionBuilder controllerBuilder
= BeanDefinitionBuilder.rootBeanDefinition(ConcurrentSessionControllerImpl.class);
controllerBuilder.setSource(source);
controllerBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
controllerBuilder.addPropertyValue("sessionRegistry", new RuntimeBeanReference(sessionRegistryId));
}
String maxSessions = element.getAttribute(ATT_MAX_SESSIONS);
@@ -90,14 +72,23 @@ public class ConcurrentSessionsBeanDefinitionParser implements BeanDefinitionPar
}
BeanDefinition controller = controllerBuilder.getBeanDefinition();
beanRegistry.registerBeanDefinition(BeanIds.SESSION_REGISTRY, sessionRegistry);
parserContext.registerComponent(new BeanComponentDefinition(sessionRegistry, BeanIds.SESSION_REGISTRY));
String registryAlias = element.getAttribute(ATT_SESSION_REGISTRY_ALIAS);
if (StringUtils.hasText(registryAlias)) {
beanRegistry.registerAlias(BeanIds.SESSION_REGISTRY, registryAlias);
}
beanRegistry.registerBeanDefinition(BeanIds.CONCURRENT_SESSION_CONTROLLER, controller);
parserContext.registerComponent(new BeanComponentDefinition(controller, BeanIds.CONCURRENT_SESSION_CONTROLLER));
beanRegistry.registerBeanDefinition(BeanIds.CONCURRENT_SESSION_FILTER, filterBuilder.getBeanDefinition());
parserContext.registerComponent(new BeanComponentDefinition(filterBuilder.getBeanDefinition(), BeanIds.CONCURRENT_SESSION_FILTER));
ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.CONCURRENT_SESSION_FILTER));
ConfigUtils.setSessionControllerOnAuthenticationManager(parserContext, BeanIds.CONCURRENT_SESSION_CONTROLLER, element);
BeanDefinition providerManager = ConfigUtils.registerProviderManagerIfNecessary(parserContext);
providerManager.getPropertyValues().addPropertyValue("sessionController", controller);
parserContext.popAndRegisterContainingComponent();
@@ -1,13 +1,11 @@
package org.springframework.security.config;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.RuntimeBeanReference;
@@ -18,12 +16,10 @@ import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.security.afterinvocation.AfterInvocationProviderManager;
import org.springframework.security.providers.ProviderManager;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.util.UrlUtils;
import org.springframework.security.vote.AffirmativeBased;
import org.springframework.security.vote.AuthenticatedVoter;
import org.springframework.security.vote.RoleVoter;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* Utility methods used internally by the Spring Security namespace configuration code.
@@ -92,6 +88,28 @@ public abstract class ConfigUtils {
return authManager;
}
/**
* Obtains a user details service for use in RememberMeServices etc. Will return a caching version
* if available so should not be used for beans which need to separate the two.
*/
static RuntimeBeanReference getUserDetailsService(ConfigurableListableBeanFactory bf) {
String[] services = bf.getBeanNamesForType(CachingUserDetailsService.class, false, false);
if (services.length == 0) {
services = bf.getBeanNamesForType(UserDetailsService.class);
}
if (services.length == 0) {
throw new IllegalArgumentException("No UserDetailsService registered.");
} else if (services.length > 1) {
throw new IllegalArgumentException("More than one UserDetailsService registered. Please " +
"use a specific Id in your configuration");
}
return new RuntimeBeanReference(services[0]);
}
static ManagedList getRegisteredProviders(ParserContext parserContext) {
BeanDefinition authManager = registerProviderManagerIfNecessary(parserContext);
return (ManagedList) authManager.getPropertyValues().getPropertyValue("providers").getValue();
@@ -162,25 +180,12 @@ public abstract class ConfigUtils {
/**
* Checks the value of an XML attribute which represents a redirect URL.
* If not empty or starting with "$" (potential placeholder), "/" or "http" it will raise an error.
* If not empty or starting with "/" or "http" it will raise an error.
*/
static void validateHttpRedirect(String url, ParserContext pc, Object source) {
if (UrlUtils.isValidRedirectUrl(url) || url.startsWith("$")) {
if (!StringUtils.hasText(url) || url.startsWith("/") || url.toLowerCase().startsWith("http")) {
return;
}
pc.getReaderContext().warning(url + " is not a valid redirect URL (must start with '/' or http(s))", source);
}
static void setSessionControllerOnAuthenticationManager(ParserContext pc, String beanName, Element sourceElt) {
BeanDefinition authManager = registerProviderManagerIfNecessary(pc);
PropertyValue pv = authManager.getPropertyValues().getPropertyValue("sessionController");
if (pv != null && pv.getValue() != null) {
pc.getReaderContext().error("A session controller has already been set on the authentication manager. " +
"The <concurrent-session-control> element isn't compatible with a custom session controller",
pc.extractSource(sourceElt));
}
authManager.getPropertyValues().addPropertyValue("sessionController", new RuntimeBeanReference(beanName));
pc.getReaderContext().error(url + " is not a valid redirect URL (must start with '/' or http(s))", source);
}
}
@@ -3,7 +3,6 @@ package org.springframework.security.config;
import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.w3c.dom.Node;
@@ -17,7 +16,7 @@ import org.w3c.dom.Node;
*/
public class CustomAuthenticationProviderBeanDefinitionDecorator implements BeanDefinitionDecorator {
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder holder, ParserContext parserContext) {
ConfigUtils.getRegisteredProviders(parserContext).add(new RuntimeBeanReference(holder.getBeanName()));
ConfigUtils.getRegisteredProviders(parserContext).add(holder.getBeanDefinition());
return holder;
}
@@ -1,59 +0,0 @@
package org.springframework.security.config;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.security.ui.AuthenticationEntryPoint;
import org.springframework.security.ui.ExceptionTranslationFilter;
import org.springframework.util.Assert;
/**
*
* @author Luke Taylor
* @since 2.0.2
*/
public class EntryPointInjectionBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
private final Log logger = LogFactory.getLog(getClass());
private ConfigurableListableBeanFactory beanFactory;
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!BeanIds.EXCEPTION_TRANSLATION_FILTER.equals(beanName)) {
return bean;
}
logger.info("Selecting AuthenticationEntryPoint for use in ExceptionTranslationFilter");
ExceptionTranslationFilter etf = (ExceptionTranslationFilter) beanFactory.getBean(BeanIds.EXCEPTION_TRANSLATION_FILTER);
Object entryPoint = null;
if (beanFactory.containsBean(BeanIds.MAIN_ENTRY_POINT)) {
entryPoint = beanFactory.getBean(BeanIds.MAIN_ENTRY_POINT);
logger.info("Using main configured AuthenticationEntryPoint.");
} else {
Map entryPoints = beanFactory.getBeansOfType(AuthenticationEntryPoint.class);
Assert.isTrue(entryPoints.size() != 0, "No AuthenticationEntryPoint instances defined");
Assert.isTrue(entryPoints.size() == 1, "More than one AuthenticationEntryPoint defined in context");
entryPoint = entryPoints.values().toArray()[0];
}
logger.info("Using bean '" + entryPoint + "' as the entry point.");
etf.setAuthenticationEntryPoint((AuthenticationEntryPoint) entryPoint);
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
}
}
@@ -44,7 +44,7 @@ public class FilterChainProxyPostProcessor implements BeanPostProcessor, BeanFac
private ListableBeanFactory beanFactory;
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(!BeanIds.FILTER_CHAIN_PROXY.equals(beanName)) {
if(!beanName.equals(BeanIds.FILTER_CHAIN_PROXY)) {
return bean;
}
@@ -1,6 +1,5 @@
package org.springframework.security.config;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
@@ -55,18 +54,6 @@ public class FormLoginBeanDefinitionParser implements BeanDefinitionParser {
Object source = null;
// Copy values from the session fixation protection filter
final Boolean sessionFixationProtectionEnabled =
new Boolean(pc.getRegistry().containsBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER));
Boolean migrateSessionAttributes = Boolean.FALSE;
if (sessionFixationProtectionEnabled.booleanValue()) {
PropertyValue pv =
pc.getRegistry().getBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER)
.getPropertyValues().getPropertyValue("migrateSessionAttributes");
migrateSessionAttributes = (Boolean)pv.getValue();
}
if (elt != null) {
source = pc.extractSource(elt);
loginUrl = elt.getAttribute(ATT_LOGIN_URL);
@@ -92,20 +79,10 @@ public class FormLoginBeanDefinitionParser implements BeanDefinitionParser {
filterBean.getPropertyValues().addPropertyValue("authenticationManager",
new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER));
filterBean.getPropertyValues().addPropertyValue("invalidateSessionOnSuccessfulAuthentication",
sessionFixationProtectionEnabled);
filterBean.getPropertyValues().addPropertyValue("migrateInvalidatedSessionAttributes",
migrateSessionAttributes);
if (pc.getRegistry().containsBeanDefinition(BeanIds.REMEMBER_ME_SERVICES)) {
filterBean.getPropertyValues().addPropertyValue("rememberMeServices",
new RuntimeBeanReference(BeanIds.REMEMBER_ME_SERVICES) );
}
if (pc.getRegistry().containsBeanDefinition(BeanIds.SESSION_REGISTRY)) {
filterBean.getPropertyValues().addPropertyValue("sessionRegistry",
new RuntimeBeanReference(BeanIds.SESSION_REGISTRY));
}
BeanDefinitionBuilder entryPointBuilder =
BeanDefinitionBuilder.rootBeanDefinition(AuthenticationProcessingFilterEntryPoint.class);
@@ -181,14 +181,11 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
new X509BeanDefinitionParser().parse(x509Elt, parserContext);
}
// Register the post processors which will tie up the loose ends in the configuration once the app context has been created and all beans are available.
RootBeanDefinition postProcessor = new RootBeanDefinition(EntryPointInjectionBeanPostProcessor.class);
// Register the post processor which will tie up the loose ends in the configuration once the app context has been created and all beans are available.
RootBeanDefinition postProcessor = new RootBeanDefinition(HttpSecurityConfigPostProcessor.class);
postProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(BeanIds.ENTRY_POINT_INJECTION_POST_PROCESSOR, postProcessor);
RootBeanDefinition postProcessor2 = new RootBeanDefinition(UserDetailsServiceInjectionBeanPostProcessor.class);
postProcessor2.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(BeanIds.USER_DETAILS_SERVICE_INJECTION_POST_PROCESSOR, postProcessor2);
registry.registerBeanDefinition(BeanIds.HTTP_POST_PROCESSOR, postProcessor);
return null;
}
@@ -279,11 +276,8 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
builder.addPropertyValue("observeOncePerRequest", Boolean.FALSE);
}
DefaultFilterInvocationDefinitionSource fids =
new DefaultFilterInvocationDefinitionSource(matcher, filterInvocationDefinitionMap);
fids.setStripQueryStringFromUrls(matcher instanceof AntUrlPathMatcher);
builder.addPropertyValue("objectDefinitionSource", fids);
builder.addPropertyValue("objectDefinitionSource",
new DefaultFilterInvocationDefinitionSource(matcher, filterInvocationDefinitionMap));
pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_SECURITY_INTERCEPTOR, builder.getBeanDefinition());
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FILTER_SECURITY_INTERCEPTOR));
}
@@ -294,7 +288,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
new RuntimeBeanReference(BeanIds.CHANNEL_DECISION_MANAGER));
DefaultFilterInvocationDefinitionSource channelFilterInvDefSource =
new DefaultFilterInvocationDefinitionSource(matcher, channelRequestMap);
channelFilterInvDefSource.setStripQueryStringFromUrls(matcher instanceof AntUrlPathMatcher);
channelFilter.getPropertyValues().addPropertyValue("filterInvocationDefinitionSource",
channelFilterInvDefSource);
@@ -389,8 +383,9 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
}
BeanDefinition openIDProvider = openIDProviderBuilder.getBeanDefinition();
ConfigUtils.getRegisteredProviders(pc).add(openIDProvider);
pc.getRegistry().registerBeanDefinition(BeanIds.OPEN_ID_PROVIDER, openIDProvider);
ConfigUtils.getRegisteredProviders(pc).add(new RuntimeBeanReference(BeanIds.OPEN_ID_PROVIDER));
}
boolean needLoginPage = false;
@@ -0,0 +1,150 @@
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.PropertyValue;
import org.springframework.beans.factory.BeanFactory;
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.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.Ordered;
import org.springframework.security.ui.AuthenticationEntryPoint;
import org.springframework.security.userdetails.UserDetailsByNameServiceWrapper;
import org.springframework.util.Assert;
/**
* Responsible for tying up the HTTP security configuration once all the beans are registered.
* This class does not actually instantiate any beans (for example, it should not call {@link BeanFactory#getBean(String)}).
* All the wiring up should be done using bean definitions or bean references to avoid this. This approach should avoid any
* conflict with other processors.
*
* @author Luke Taylor
* @author Ben Alex
* @version $Id$
* @since 2.0
*/
public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor, Ordered {
private Log logger = LogFactory.getLog(getClass());
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
injectUserDetailsServiceIntoRememberMeServices(beanFactory);
injectUserDetailsServiceIntoX509Provider(beanFactory);
injectUserDetailsServiceIntoOpenIDProvider(beanFactory);
injectAuthenticationEntryPointIntoExceptionTranslationFilter(beanFactory);
}
private void injectUserDetailsServiceIntoRememberMeServices(ConfigurableListableBeanFactory bf) {
try {
BeanDefinition rememberMeServices = bf.getBeanDefinition(BeanIds.REMEMBER_ME_SERVICES);
PropertyValue pv = rememberMeServices.getPropertyValues().getPropertyValue("userDetailsService");
if (pv == null) {
rememberMeServices.getPropertyValues().addPropertyValue("userDetailsService",
ConfigUtils.getUserDetailsService(bf));
} else {
RuntimeBeanReference cachingUserService = getCachingUserService(bf, pv.getValue());
if (cachingUserService != null) {
rememberMeServices.getPropertyValues().addPropertyValue("userDetailsService", cachingUserService);
}
}
} catch (NoSuchBeanDefinitionException e) {
// ignore
}
}
private void injectUserDetailsServiceIntoX509Provider(ConfigurableListableBeanFactory bf) {
try {
BeanDefinition x509AuthProvider = bf.getBeanDefinition(BeanIds.X509_AUTH_PROVIDER);
PropertyValue pv = x509AuthProvider.getPropertyValues().getPropertyValue("preAuthenticatedUserDetailsService");
if (pv == null) {
BeanDefinitionBuilder preAuthUserService = BeanDefinitionBuilder.rootBeanDefinition(UserDetailsByNameServiceWrapper.class);
preAuthUserService.addPropertyValue("userDetailsService", ConfigUtils.getUserDetailsService(bf));
x509AuthProvider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService",
preAuthUserService.getBeanDefinition());
} else {
RootBeanDefinition preAuthUserService = (RootBeanDefinition) pv.getValue();
Object userService =
preAuthUserService.getPropertyValues().getPropertyValue("userDetailsService").getValue();
RuntimeBeanReference cachingUserService = getCachingUserService(bf, userService);
if (cachingUserService != null) {
preAuthUserService.getPropertyValues().addPropertyValue("userDetailsService", cachingUserService);
}
}
} catch (NoSuchBeanDefinitionException e) {
// ignore
}
}
private void injectUserDetailsServiceIntoOpenIDProvider(ConfigurableListableBeanFactory beanFactory) {
try {
BeanDefinition openIDProvider = beanFactory.getBeanDefinition(BeanIds.OPEN_ID_PROVIDER);
PropertyValue pv = openIDProvider.getPropertyValues().getPropertyValue("userDetailsService");
if (pv == null) {
openIDProvider.getPropertyValues().addPropertyValue("userDetailsService",
ConfigUtils.getUserDetailsService(beanFactory));
}
} catch (NoSuchBeanDefinitionException e) {
// ignore
}
}
private RuntimeBeanReference getCachingUserService(ConfigurableListableBeanFactory bf, Object userServiceRef) {
Assert.isInstanceOf(RuntimeBeanReference.class, userServiceRef,
"userDetailsService property value must be a RuntimeBeanReference");
String id = ((RuntimeBeanReference)userServiceRef).getBeanName();
// Overwrite with the caching version if available
String cachingId = id + AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX;
if (bf.containsBeanDefinition(cachingId)) {
return new RuntimeBeanReference(cachingId);
}
return null;
}
/**
* Selects the entry point that should be used in ExceptionTranslationFilter. If an entry point has been
* set during parsing of form, openID and basic authentication information, or via a custom reference
* (using <tt>custom-entry-point</tt>, then that will be used. Otherwise there
* must be a single entry point bean and that will be used.
*
* Todo: this could probably be more easily be done in a BeanPostProcessor for ExceptionTranslationFilter.
*
*/
private void injectAuthenticationEntryPointIntoExceptionTranslationFilter(ConfigurableListableBeanFactory beanFactory) {
logger.info("Selecting AuthenticationEntryPoint for use in ExceptionTranslationFilter");
BeanDefinition etf =
beanFactory.getBeanDefinition(BeanIds.EXCEPTION_TRANSLATION_FILTER);
String entryPoint = null;
if (beanFactory.containsBean(BeanIds.MAIN_ENTRY_POINT)) {
entryPoint = BeanIds.MAIN_ENTRY_POINT;
logger.info("Using main configured AuthenticationEntryPoint set to " + BeanIds.MAIN_ENTRY_POINT);
} else {
String[] entryPoints = beanFactory.getBeanNamesForType(AuthenticationEntryPoint.class);
Assert.isTrue(entryPoints.length != 0, "No AuthenticationEntryPoint instances defined");
Assert.isTrue(entryPoints.length == 1, "More than one AuthenticationEntryPoint defined in context");
entryPoint = entryPoints[0];
}
logger.info("Using bean '" + entryPoint + "' as the entry point.");
etf.getPropertyValues().addPropertyValue("authenticationEntryPoint", new RuntimeBeanReference(entryPoint));
}
public int getOrder() {
return HIGHEST_PRECEDENCE + 1;
}
}
@@ -1,5 +1,6 @@
package org.springframework.security.config;
import org.springframework.security.userdetails.jdbc.JdbcUserDetailsManager;
import org.springframework.util.StringUtils;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
@@ -17,8 +18,8 @@ public class JdbcUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
static final String ATT_GROUP_AUTHORITIES_QUERY = "group-authorities-by-username-query";
static final String ATT_ROLE_PREFIX = "role-prefix";
protected String getBeanClassName(Element element) {
return "org.springframework.security.userdetails.jdbc.JdbcUserDetailsManager";
protected Class getBeanClass(Element element) {
return JdbcUserDetailsManager.class;
}
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
@@ -1,8 +1,11 @@
package org.springframework.security.config;
import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
import org.springframework.security.providers.ldap.LdapAuthenticationProvider;
import org.springframework.security.providers.ldap.authenticator.BindAuthenticator;
import org.springframework.security.providers.ldap.authenticator.PasswordComparisonAuthenticator;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
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;
@@ -27,16 +30,12 @@ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser {
private static final String ATT_USER_PASSWORD = "password-attribute";
private static final String ATT_HASH = PasswordEncoderParser.ATT_HASH;
private static final String DEF_USER_SEARCH_FILTER = "uid={0}";
private static final String PROVIDER_CLASS = "org.springframework.security.providers.ldap.LdapAuthenticationProvider";
private static final String BIND_AUTH_CLASS = "org.springframework.security.providers.ldap.authenticator.BindAuthenticator";
private static final String PASSWD_AUTH_CLASS = "org.springframework.security.providers.ldap.authenticator.PasswordComparisonAuthenticator";
private static final String DEF_USER_SEARCH_FILTER="uid={0}";
public BeanDefinition parse(Element elt, ParserContext parserContext) {
RuntimeBeanReference contextSource = LdapUserServiceBeanDefinitionParser.parseServerReference(elt, parserContext);
BeanDefinition searchBean = LdapUserServiceBeanDefinitionParser.parseSearchBean(elt, parserContext);
RootBeanDefinition searchBean = LdapUserServiceBeanDefinitionParser.parseSearchBean(elt, parserContext);
String userDnPattern = elt.getAttribute(ATT_USER_DN_PATTERN);
String[] userDnPatternArray = new String[0];
@@ -46,25 +45,22 @@ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser {
// TODO: Validate the pattern and make sure it is a valid DN.
} else if (searchBean == null) {
logger.info("No search information or DN pattern specified. Using default search filter '" + DEF_USER_SEARCH_FILTER + "'");
BeanDefinitionBuilder searchBeanBuilder = BeanDefinitionBuilder.rootBeanDefinition(LdapUserServiceBeanDefinitionParser.LDAP_SEARCH_CLASS);
searchBeanBuilder.setSource(elt);
searchBeanBuilder.addConstructorArg("");
searchBeanBuilder.addConstructorArg(DEF_USER_SEARCH_FILTER);
searchBeanBuilder.addConstructorArg(contextSource);
searchBean = searchBeanBuilder.getBeanDefinition();
searchBean = new RootBeanDefinition(FilterBasedLdapUserSearch.class);
searchBean.setSource(elt);
searchBean.getConstructorArgumentValues().addIndexedArgumentValue(0, "");
searchBean.getConstructorArgumentValues().addIndexedArgumentValue(1, DEF_USER_SEARCH_FILTER);
searchBean.getConstructorArgumentValues().addIndexedArgumentValue(2, contextSource);
}
BeanDefinitionBuilder authenticatorBuilder =
BeanDefinitionBuilder.rootBeanDefinition(BIND_AUTH_CLASS);
RootBeanDefinition authenticator = new RootBeanDefinition(BindAuthenticator.class);
Element passwordCompareElt = DomUtils.getChildElementByTagName(elt, Elements.LDAP_PASSWORD_COMPARE);
if (passwordCompareElt != null) {
authenticatorBuilder =
BeanDefinitionBuilder.rootBeanDefinition(PASSWD_AUTH_CLASS);
authenticator = new RootBeanDefinition(PasswordComparisonAuthenticator.class);
String passwordAttribute = passwordCompareElt.getAttribute(ATT_USER_PASSWORD);
if (StringUtils.hasText(passwordAttribute)) {
authenticatorBuilder.addPropertyValue("passwordAttributeName", passwordAttribute);
authenticator.getPropertyValues().addPropertyValue("passwordAttributeName", passwordAttribute);
}
Element passwordEncoderElement = DomUtils.getChildElementByTagName(passwordCompareElt, Elements.PASSWORD_ENCODER);
@@ -74,34 +70,33 @@ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser {
if (StringUtils.hasText(hash)) {
parserContext.getReaderContext().warning("Attribute 'hash' cannot be used with 'password-encoder' and " +
"will be ignored.", parserContext.extractSource(elt));
}
}
PasswordEncoderParser pep = new PasswordEncoderParser(passwordEncoderElement, parserContext);
authenticatorBuilder.addPropertyValue("passwordEncoder", pep.getPasswordEncoder());
authenticator.getPropertyValues().addPropertyValue("passwordEncoder", pep.getPasswordEncoder());
if (pep.getSaltSource() != null) {
parserContext.getReaderContext().warning("Salt source information isn't valid when used with LDAP",
passwordEncoderElement);
parserContext.getReaderContext().warning("Salt source information isn't valid when used with LDAP", passwordEncoderElement);
}
} else if (StringUtils.hasText(hash)) {
Class encoderClass = (Class) PasswordEncoderParser.ENCODER_CLASSES.get(hash);
authenticatorBuilder.addPropertyValue("passwordEncoder", new RootBeanDefinition(encoderClass));
authenticator.getPropertyValues().addPropertyValue("passwordEncoder", new RootBeanDefinition(encoderClass));
}
}
}
authenticatorBuilder.addConstructorArg(contextSource);
authenticatorBuilder.addPropertyValue("userDnPatterns", userDnPatternArray);
authenticator.getConstructorArgumentValues().addGenericArgumentValue(contextSource);
authenticator.getPropertyValues().addPropertyValue("userDnPatterns", userDnPatternArray);
if (searchBean != null) {
authenticatorBuilder.addPropertyValue("userSearch", searchBean);
authenticator.getPropertyValues().addPropertyValue("userSearch", searchBean);
}
BeanDefinitionBuilder ldapProvider = BeanDefinitionBuilder.rootBeanDefinition(PROVIDER_CLASS);
ldapProvider.addConstructorArg(authenticatorBuilder.getBeanDefinition());
ldapProvider.addConstructorArg(LdapUserServiceBeanDefinitionParser.parseAuthoritiesPopulator(elt, parserContext));
ldapProvider.addPropertyValue("userDetailsContextMapper",
RootBeanDefinition ldapProvider = new RootBeanDefinition(LdapAuthenticationProvider.class);
ldapProvider.getConstructorArgumentValues().addGenericArgumentValue(authenticator);
ldapProvider.getConstructorArgumentValues().addGenericArgumentValue(LdapUserServiceBeanDefinitionParser.parseAuthoritiesPopulator(elt, parserContext));
ldapProvider.getPropertyValues().addPropertyValue("userDetailsContextMapper",
LdapUserServiceBeanDefinitionParser.parseUserDetailsClass(elt, parserContext));
ConfigUtils.getRegisteredProviders(parserContext).add(ldapProvider.getBeanDefinition());
ConfigUtils.getRegisteredProviders(parserContext).add(ldapProvider);
return null;
}
@@ -1,10 +1,6 @@
package org.springframework.security.config;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
@@ -12,6 +8,7 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedSet;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
@@ -23,9 +20,7 @@ import org.apache.commons.logging.LogFactory;
* @version $Id$
*/
public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
private static final String CONTEXT_SOURCE_CLASS="org.springframework.security.ldap.DefaultSpringSecurityContextSource";
private final Log logger = LogFactory.getLog(getClass());
private Log logger = LogFactory.getLog(getClass());
/** Defines the Url of the ldap server to use. If not specified, an embedded apache DS instance will be created */
private static final String ATT_URL = "url";
@@ -58,8 +53,7 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
if (!StringUtils.hasText(url)) {
contextSource = createEmbeddedServer(elt, parserContext);
} else {
contextSource = new RootBeanDefinition();
contextSource.setBeanClassName(CONTEXT_SOURCE_CLASS);
contextSource = new RootBeanDefinition(DefaultSpringSecurityContextSource.class);
contextSource.getConstructorArgumentValues().addIndexedArgumentValue(0, url);
}
@@ -98,22 +92,17 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
*/
private RootBeanDefinition createEmbeddedServer(Element element, ParserContext parserContext) {
Object source = parserContext.extractSource(element);
BeanDefinitionBuilder configuration =
BeanDefinitionBuilder.rootBeanDefinition("org.apache.directory.server.configuration.MutableServerStartupConfiguration");
BeanDefinitionBuilder partition =
BeanDefinitionBuilder.rootBeanDefinition("org.apache.directory.server.core.partition.impl.btree.MutableBTreePartitionConfiguration");
BeanDefinitionBuilder configuration = BeanDefinitionBuilder.rootBeanDefinition("org.apache.directory.server.configuration.MutableServerStartupConfiguration");
BeanDefinitionBuilder partition = BeanDefinitionBuilder.rootBeanDefinition("org.apache.directory.server.core.partition.impl.btree.MutableBTreePartitionConfiguration");
configuration.setSource(source);
partition.setSource(source);
Attributes rootAttributes = new BasicAttributes("dc", "springsecurity");
Attribute a = new BasicAttribute("objectClass");
a.add("top");
a.add("domain");
a.add("extensibleObject");
rootAttributes.put(a);
DirContextAdapter rootContext = new DirContextAdapter();
rootContext.setAttributeValues("objectClass", new String[] {"top", "domain", "extensibleObject"});
rootContext.setAttributeValue("dc", "springsecurity");
partition.addPropertyValue("name", "springsecurity");
partition.addPropertyValue("contextEntry", rootAttributes);
partition.addPropertyValue("contextEntry", rootContext.getAttributes());
String suffix = element.getAttribute(ATT_ROOT_SUFFIX);
@@ -142,15 +131,15 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
String url = "ldap://127.0.0.1:" + port + "/" + suffix;
BeanDefinitionBuilder contextSource = BeanDefinitionBuilder.rootBeanDefinition(CONTEXT_SOURCE_CLASS);
contextSource.addConstructorArg(url);
contextSource.addPropertyValue("userDn", "uid=admin,ou=system");
contextSource.addPropertyValue("password", "secret");
RootBeanDefinition contextSource = new RootBeanDefinition(DefaultSpringSecurityContextSource.class);
contextSource.getConstructorArgumentValues().addIndexedArgumentValue(0, url);
contextSource.getPropertyValues().addPropertyValue("userDn", "uid=admin,ou=system");
contextSource.getPropertyValues().addPropertyValue("password", "secret");
RootBeanDefinition apacheContainer = new RootBeanDefinition("org.springframework.security.config.ApacheDSContainer", null, null);
apacheContainer.setSource(source);
apacheContainer.getConstructorArgumentValues().addGenericArgumentValue(configuration.getBeanDefinition());
apacheContainer.getConstructorArgumentValues().addGenericArgumentValue(contextSource.getBeanDefinition());
apacheContainer.getConstructorArgumentValues().addGenericArgumentValue(contextSource);
String ldifs = element.getAttribute(ATT_LDIF_FILE);
if (!StringUtils.hasText(ldifs)) {
@@ -168,6 +157,6 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
parserContext.getRegistry().registerBeanDefinition(BeanIds.EMBEDDED_APACHE_DS, apacheContainer);
return (RootBeanDefinition) contextSource.getBeanDefinition();
return contextSource;
}
}
@@ -1,5 +1,11 @@
package org.springframework.security.config;
import org.springframework.security.userdetails.ldap.InetOrgPersonContextMapper;
import org.springframework.security.userdetails.ldap.LdapUserDetailsMapper;
import org.springframework.security.userdetails.ldap.LdapUserDetailsService;
import org.springframework.security.userdetails.ldap.PersonContextMapper;
import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
import org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.RootBeanDefinition;
@@ -29,15 +35,9 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
static final String ATT_USER_CLASS = "user-details-class";
static final String OPT_PERSON = "person";
static final String OPT_INETORGPERSON = "inetOrgPerson";
public static final String LDAP_SEARCH_CLASS = "org.springframework.security.ldap.search.FilterBasedLdapUserSearch";
public static final String PERSON_MAPPER_CLASS = "org.springframework.security.userdetails.ldap.PersonContextMapper";
public static final String INET_ORG_PERSON_MAPPER_CLASS = "org.springframework.security.userdetails.ldap.InetOrgPersonContextMapper";
public static final String LDAP_USER_MAPPER_CLASS = "org.springframework.security.userdetails.ldap.LdapUserDetailsMapper";
public static final String LDAP_AUTHORITIES_POPULATOR_CLASS = "org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator";
protected String getBeanClassName(Element element) {
return "org.springframework.security.userdetails.ldap.LdapUserDetailsService";
protected Class getBeanClass(Element element) {
return LdapUserDetailsService.class;
}
protected void doParse(Element elt, ParserContext parserContext, BeanDefinitionBuilder builder) {
@@ -68,7 +68,7 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
return null;
}
BeanDefinitionBuilder searchBuilder = BeanDefinitionBuilder.rootBeanDefinition(LDAP_SEARCH_CLASS);
BeanDefinitionBuilder searchBuilder = BeanDefinitionBuilder.rootBeanDefinition(FilterBasedLdapUserSearch.class);
searchBuilder.setSource(source);
searchBuilder.addConstructorArg(userSearchBase);
searchBuilder.addConstructorArg(userSearchFilter);
@@ -96,12 +96,12 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
static RootBeanDefinition parseUserDetailsClass(Element elt, ParserContext parserContext) {
String userDetailsClass = elt.getAttribute(ATT_USER_CLASS);
if (OPT_PERSON.equals(userDetailsClass)) {
return new RootBeanDefinition(PERSON_MAPPER_CLASS, null, null);
if(OPT_PERSON.equals(userDetailsClass)) {
return new RootBeanDefinition(PersonContextMapper.class);
} else if (OPT_INETORGPERSON.equals(userDetailsClass)) {
return new RootBeanDefinition(INET_ORG_PERSON_MAPPER_CLASS, null, null);
return new RootBeanDefinition(InetOrgPersonContextMapper.class);
}
return new RootBeanDefinition(LDAP_USER_MAPPER_CLASS, null, null);
return new RootBeanDefinition(LdapUserDetailsMapper.class);
}
static RootBeanDefinition parseAuthoritiesPopulator(Element elt, ParserContext parserContext) {
@@ -118,19 +118,18 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
groupSearchBase = DEF_GROUP_SEARCH_BASE;
}
BeanDefinitionBuilder populator = BeanDefinitionBuilder.rootBeanDefinition(LDAP_AUTHORITIES_POPULATOR_CLASS);
BeanDefinitionBuilder populator = BeanDefinitionBuilder.rootBeanDefinition(DefaultLdapAuthoritiesPopulator.class);
populator.setSource(parserContext.extractSource(elt));
populator.addConstructorArg(parseServerReference(elt, parserContext));
populator.addConstructorArg(groupSearchBase);
populator.addPropertyValue("groupSearchFilter", groupSearchFilter);
populator.addPropertyValue("searchSubtree", Boolean.TRUE);
if (StringUtils.hasText(rolePrefix)) {
if ("none".equals(rolePrefix)) {
rolePrefix = "";
}
populator.addPropertyValue("rolePrefix", rolePrefix);
}
}
if (StringUtils.hasLength(groupRoleAttribute)) {
populator.addPropertyValue("groupRoleAttribute", groupRoleAttribute);
@@ -23,7 +23,7 @@ public class MethodSecurityInterceptorPostProcessor implements BeanPostProcessor
private BeanFactory beanFactory;
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(!BeanIds.METHOD_SECURITY_INTERCEPTOR.equals(beanName)) {
if(!beanName.equals(BeanIds.METHOD_SECURITY_INTERCEPTOR)) {
return bean;
}
@@ -35,7 +35,6 @@ public class PasswordEncoderParser {
static final String ATT_BASE_64 = "base64";
static final String OPT_HASH_PLAINTEXT = "plaintext";
static final String OPT_HASH_SHA = "sha";
static final String OPT_HASH_SHA256 = "sha-256";
static final String OPT_HASH_MD4 = "md4";
static final String OPT_HASH_MD5 = "md5";
static final String OPT_HASH_LDAP_SHA = "{sha}";
@@ -46,7 +45,6 @@ public class PasswordEncoderParser {
ENCODER_CLASSES = new HashMap();
ENCODER_CLASSES.put(OPT_HASH_PLAINTEXT, PlaintextPasswordEncoder.class);
ENCODER_CLASSES.put(OPT_HASH_SHA, ShaPasswordEncoder.class);
ENCODER_CLASSES.put(OPT_HASH_SHA256, ShaPasswordEncoder.class);
ENCODER_CLASSES.put(OPT_HASH_MD4, Md4PasswordEncoder.class);
ENCODER_CLASSES.put(OPT_HASH_MD5, Md5PasswordEncoder.class);
ENCODER_CLASSES.put(OPT_HASH_LDAP_SHA, LdapShaPasswordEncoder.class);
@@ -76,11 +74,6 @@ public class PasswordEncoderParser {
} else {
Class beanClass = (Class) ENCODER_CLASSES.get(hash);
RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass);
if (OPT_HASH_SHA256.equals(hash)) {
beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, new Integer(256));
}
beanDefinition.setSource(parserContext.extractSource(element));
if (useBase64) {
if (BaseDigestPasswordEncoder.class.isAssignableFrom(beanClass)) {
@@ -23,14 +23,12 @@ import org.w3c.dom.Element;
*/
public class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
static final String ATT_KEY = "key";
static final String DEF_KEY = "SpringSecured";
static final String DEF_KEY = "doesNotMatter";
static final String ATT_DATA_SOURCE = "data-source-ref";
static final String ATT_SERVICES_REF = "services-ref";
static final String ATT_DATA_SOURCE = "data-source";
static final String ATT_TOKEN_REPOSITORY = "token-repository-ref";
static final String ATT_USER_SERVICE_REF = "user-service-ref";
static final String ATT_TOKEN_VALIDITY = "token-validity-seconds";
protected final Log logger = LogFactory.getLog(getClass());
public BeanDefinition parse(Element element, ParserContext parserContext) {
@@ -39,46 +37,32 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
String key = null;
Object source = null;
String userServiceRef = null;
String rememberMeServicesRef = null;
String tokenValiditySeconds = null;
if (element != null) {
tokenRepository = element.getAttribute(ATT_TOKEN_REPOSITORY);
dataSource = element.getAttribute(ATT_DATA_SOURCE);
key = element.getAttribute(ATT_KEY);
userServiceRef = element.getAttribute(ATT_USER_SERVICE_REF);
rememberMeServicesRef = element.getAttribute(ATT_SERVICES_REF);
tokenValiditySeconds = element.getAttribute(ATT_TOKEN_VALIDITY);
userServiceRef = element.getAttribute(ATT_USER_SERVICE_REF);
source = parserContext.extractSource(element);
}
if (!StringUtils.hasText(key)) {
key = DEF_KEY;
}
RootBeanDefinition services = null;
RootBeanDefinition filter = new RootBeanDefinition(RememberMeProcessingFilter.class);
RootBeanDefinition services = new RootBeanDefinition(PersistentTokenBasedRememberMeServices.class);
filter.getPropertyValues().addPropertyValue("authenticationManager",
new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER));
boolean dataSourceSet = StringUtils.hasText(dataSource);
boolean tokenRepoSet = StringUtils.hasText(tokenRepository);
boolean servicesRefSet = StringUtils.hasText(rememberMeServicesRef);
boolean userServiceSet = StringUtils.hasText(userServiceRef);
boolean tokenValiditySet = StringUtils.hasText(tokenValiditySeconds);
if (servicesRefSet && (dataSourceSet || tokenRepoSet || userServiceSet || tokenValiditySet)) {
parserContext.getReaderContext().error(ATT_SERVICES_REF + " can't be used in combination with attributes "
+ ATT_TOKEN_REPOSITORY + "," + ATT_DATA_SOURCE + ", " + ATT_USER_SERVICE_REF + " or " + ATT_TOKEN_VALIDITY, source);
}
if (dataSourceSet && tokenRepoSet) {
parserContext.getReaderContext().error("Specify " + ATT_TOKEN_REPOSITORY + " or " +
ATT_DATA_SOURCE +" but not both", source);
parserContext.getReaderContext().error("Specify tokenRepository or dataSource but not both", element);
}
boolean isPersistent = dataSourceSet | tokenRepoSet;
if (isPersistent) {
Object tokenRepo;
services = new RootBeanDefinition(PersistentTokenBasedRememberMeServices.class);
if (tokenRepoSet) {
tokenRepo = new RuntimeBeanReference(tokenRepository);
@@ -88,51 +72,39 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser {
new RuntimeBeanReference(dataSource));
}
services.getPropertyValues().addPropertyValue("tokenRepository", tokenRepo);
} else if (!servicesRefSet) {
} else {
isPersistent = false;
services = new RootBeanDefinition(TokenBasedRememberMeServices.class);
}
if (services != null) {
if (userServiceSet) {
services.getPropertyValues().addPropertyValue("userDetailsService", new RuntimeBeanReference(userServiceRef));
}
if (tokenValiditySet) {
services.getPropertyValues().addPropertyValue("tokenValiditySeconds", new Integer(tokenValiditySeconds));
}
services.setSource(source);
services.getPropertyValues().addPropertyValue(ATT_KEY, key);
parserContext.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES, services);
} else {
parserContext.getRegistry().registerAlias(rememberMeServicesRef, BeanIds.REMEMBER_ME_SERVICES);
if (!StringUtils.hasText(key) && !isPersistent) {
key = DEF_KEY;
}
registerProvider(parserContext, source, key);
registerFilter(parserContext, source);
return null;
}
private void registerProvider(ParserContext pc, Object source, String key) {
BeanDefinition authManager = ConfigUtils.registerProviderManagerIfNecessary(pc);
BeanDefinition authManager = ConfigUtils.registerProviderManagerIfNecessary(parserContext);
RootBeanDefinition provider = new RootBeanDefinition(RememberMeAuthenticationProvider.class);
provider.setSource(source);
provider.getPropertyValues().addPropertyValue(ATT_KEY, key);
ManagedList providers = (ManagedList) authManager.getPropertyValues().getPropertyValue("providers").getValue();
providers.add(provider);
}
private void registerFilter(ParserContext pc, Object source) {
RootBeanDefinition filter = new RootBeanDefinition(RememberMeProcessingFilter.class);
filter.setSource(source);
filter.getPropertyValues().addPropertyValue("authenticationManager",
new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER));
services.setSource(source);
provider.setSource(source);
if (StringUtils.hasText(userServiceRef)) {
services.getPropertyValues().addPropertyValue("userDetailsService", new RuntimeBeanReference(userServiceRef));
}
provider.getPropertyValues().addPropertyValue(ATT_KEY, key);
services.getPropertyValues().addPropertyValue(ATT_KEY, key);
ManagedList providers = (ManagedList) authManager.getPropertyValues().getPropertyValue("providers").getValue();
providers.add(provider);
filter.getPropertyValues().addPropertyValue("rememberMeServices",
new RuntimeBeanReference(BeanIds.REMEMBER_ME_SERVICES));
pc.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_FILTER, filter);
ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.REMEMBER_ME_FILTER));
parserContext.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES, services);
parserContext.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_FILTER, filter);
ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.REMEMBER_ME_FILTER));
return null;
}
}
@@ -33,7 +33,7 @@ public class RememberMeServicesInjectionBeanPostProcessor implements BeanPostPro
logger.info("Setting RememberMeServices on bean " + beanName);
pf.setRememberMeServices(getRememberMeServices());
}
} else if (BeanIds.BASIC_AUTHENTICATION_FILTER.equals(beanName)) {
} else if (beanName.equals(BeanIds.BASIC_AUTHENTICATION_FILTER)) {
// NB: For remember-me to be sent back, a user must submit a "_spring_security_remember_me" with their login request.
// Most of the time a user won't present such a parameter with their BASIC authentication request.
// In the future we might support setting the AbstractRememberMeServices.alwaysRemember = true, but I am reluctant to
@@ -1,139 +0,0 @@
package org.springframework.security.config;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.security.providers.preauth.PreAuthenticatedAuthenticationProvider;
import org.springframework.security.ui.rememberme.AbstractRememberMeServices;
import org.springframework.security.userdetails.UserDetailsByNameServiceWrapper;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.util.Assert;
/**
*
* @author Luke Taylor
* @since 2.0.2
*/
public class UserDetailsServiceInjectionBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
private final Log logger = LogFactory.getLog(getClass());
private ConfigurableListableBeanFactory beanFactory;
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (BeanIds.X509_AUTH_PROVIDER.equals(beanName)) {
injectUserDetailsServiceIntoX509Provider((PreAuthenticatedAuthenticationProvider) bean);
} else if (BeanIds.REMEMBER_ME_SERVICES.equals(beanName)) {
injectUserDetailsServiceIntoRememberMeServices((AbstractRememberMeServices)bean);
} else if (BeanIds.OPEN_ID_PROVIDER.equals(beanName)) {
injectUserDetailsServiceIntoOpenIDProvider(bean);
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
private void injectUserDetailsServiceIntoRememberMeServices(AbstractRememberMeServices services) {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(BeanIds.REMEMBER_ME_SERVICES);
PropertyValue pv = beanDefinition.getPropertyValues().getPropertyValue("userDetailsService");
if (pv == null) {
services.setUserDetailsService(getUserDetailsService());
} else {
UserDetailsService cachingUserService = getCachingUserService(pv.getValue());
if (cachingUserService != null) {
services.setUserDetailsService(cachingUserService);
}
}
}
private void injectUserDetailsServiceIntoX509Provider(PreAuthenticatedAuthenticationProvider provider) {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(BeanIds.X509_AUTH_PROVIDER);
PropertyValue pv = beanDefinition.getPropertyValues().getPropertyValue("preAuthenticatedUserDetailsService");
UserDetailsByNameServiceWrapper wrapper = new UserDetailsByNameServiceWrapper();
if (pv == null) {
wrapper.setUserDetailsService(getUserDetailsService());
provider.setPreAuthenticatedUserDetailsService(wrapper);
} else {
RootBeanDefinition preAuthUserService = (RootBeanDefinition) pv.getValue();
Object userService =
preAuthUserService.getPropertyValues().getPropertyValue("userDetailsService").getValue();
UserDetailsService cachingUserService = getCachingUserService(userService);
if (cachingUserService != null) {
wrapper.setUserDetailsService(cachingUserService);
provider.setPreAuthenticatedUserDetailsService(wrapper);
}
}
}
private void injectUserDetailsServiceIntoOpenIDProvider(Object bean) {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(BeanIds.OPEN_ID_PROVIDER);
PropertyValue pv = beanDefinition.getPropertyValues().getPropertyValue("userDetailsService");
if (pv == null) {
BeanWrapperImpl beanWrapper = new BeanWrapperImpl(bean);
beanWrapper.setPropertyValue("userDetailsService", getUserDetailsService());
}
}
/**
* Obtains a user details service for use in RememberMeServices etc. Will return a caching version
* if available so should not be used for beans which need to separate the two.
*/
UserDetailsService getUserDetailsService() {
Map beans = beanFactory.getBeansOfType(CachingUserDetailsService.class);
if (beans.size() == 0) {
beans = beanFactory.getBeansOfType(UserDetailsService.class);
}
if (beans.size() == 0) {
throw new SecurityConfigurationException("No UserDetailsService registered.");
} else if (beans.size() > 1) {
throw new SecurityConfigurationException("More than one UserDetailsService registered. Please " +
"use a specific Id in your configuration");
}
return (UserDetailsService) beans.values().toArray()[0];
}
private UserDetailsService getCachingUserService(Object userServiceRef) {
Assert.isInstanceOf(RuntimeBeanReference.class, userServiceRef,
"userDetailsService property value must be a RuntimeBeanReference");
String id = ((RuntimeBeanReference)userServiceRef).getBeanName();
// Overwrite with the caching version if available
String cachingId = id + AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX;
if (beanFactory.containsBeanDefinition(cachingId)) {
return (UserDetailsService) beanFactory.getBean(cachingId);
}
return null;
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
}
}
@@ -6,6 +6,7 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.security.userdetails.memory.InMemoryDaoImpl;
import org.springframework.security.userdetails.memory.UserMap;
import org.springframework.security.userdetails.User;
import org.springframework.security.util.AuthorityUtils;
@@ -32,8 +33,8 @@ public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceB
static final String ATT_DISABLED = "disabled";
static final String ATT_LOCKED = "locked";
protected String getBeanClassName(Element element) {
return "org.springframework.security.userdetails.memory.InMemoryDaoImpl";
protected Class getBeanClass(Element element) {
return InMemoryDaoImpl.class;
}
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
@@ -45,8 +45,8 @@ public class X509BeanDefinitionParser implements BeanDefinitionParser {
}
BeanDefinition provider = new RootBeanDefinition(PreAuthenticatedAuthenticationProvider.class);
ConfigUtils.getRegisteredProviders(parserContext).add(provider);
parserContext.getRegistry().registerBeanDefinition(BeanIds.X509_AUTH_PROVIDER, provider);
ConfigUtils.getRegisteredProviders(parserContext).add(new RuntimeBeanReference(BeanIds.X509_AUTH_PROVIDER));
String userServiceRef = element.getAttribute(ATT_USER_SERVICE_REF);
@@ -61,7 +61,7 @@ import java.util.Collection;
* interceptor. It will also implement the proper handling of secure object invocations, namely:
* <ol>
* <li>Obtain the {@link Authentication} object from the {@link SecurityContextHolder}.</li>
* <li>Determine if the request relates to a secured or public invocation by looking up the secure object request
* <li>Determine if the request relates to a secured or public invocation by ooking up the secure object request
* against the {@link ObjectDefinitionSource}.</li>
* <li>For an invocation that is secured (there is a
* <code>ConfigAttributeDefinition</code> for the secure object invocation):
@@ -142,7 +142,7 @@ public final class ProtectPointcutPostProcessor implements BeanPostProcessor {
}
public void addPointcut(String pointcutExpression, ConfigAttributeDefinition definition) {
Assert.hasText(pointcutExpression, "An AspectJ pointcut expression is required");
Assert.hasText(pointcutExpression, "An AspecTJ pointcut expression is required");
Assert.notNull(definition, "ConfigAttributeDefinition required");
pointcutMap.put(pointcutExpression, definition);
@@ -78,7 +78,7 @@ public class DefaultFilterInvocationDefinitionSource implements FilterInvocation
DefaultFilterInvocationDefinitionSource(UrlMatcher urlMatcher) {
this.urlMatcher = urlMatcher;
}
/**
* Builds the internal request map from the supplied map. The key elements should be of type {@link RequestKey},
* which contains a URL path and an optional HTTP method (may be null). The path stored in the key will depend on
@@ -252,7 +252,7 @@ public class DefaultFilterInvocationDefinitionSource implements FilterInvocation
return urlMatcher.requiresLowerCaseUrl();
}
public void setStripQueryStringFromUrls(boolean stripQueryStringFromUrls) {
protected void setStripQueryStringFromUrls(boolean stripQueryStringFromUrls) {
this.stripQueryStringFromUrls = stripQueryStringFromUrls;
}
}
@@ -17,6 +17,8 @@ package org.springframework.security.ldap;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.ldap.LdapDataAccessException;
import org.springframework.ldap.core.DirContextOperations;
@@ -40,6 +42,7 @@ public interface LdapAuthoritiesPopulator {
*
* @return the granted authorities for the given user.
*
* @throws LdapDataAccessException if there is a problem accessing the directory.
*/
GrantedAuthority[] getGrantedAuthorities(DirContextOperations userData, String username);
}
@@ -22,7 +22,6 @@ import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapEncoder;
import org.springframework.util.Assert;
import org.apache.commons.logging.Log;
@@ -136,16 +135,9 @@ public class SpringSecurityLdapTemplate extends org.springframework.ldap.core.Ld
* @return the set of String values for the attribute as a union of the values found in all the matching entries.
*/
public Set searchForSingleAttributeValues(final String base, final String filter, final Object[] params,
final String attributeName) {
// Escape the params acording to RFC2254
Object[] encodedParams = new String[params.length];
for (int i=0; i < params.length; i++) {
encodedParams[i] = LdapEncoder.filterEncode(params[i].toString());
}
String formattedFilter = MessageFormat.format(filter, encodedParams);
logger.debug("Using filter: " + formattedFilter);
final String attributeName) {
String formattedFilter = MessageFormat.format(filter, params);
final HashSet set = new HashSet();
@@ -69,13 +69,13 @@ import java.util.Set;
* <pre>
* &lt;bean id="ldapAuthoritiesPopulator"
* class="org.springframework.security.providers.ldap.populator.DefaultLdapAuthoritiesPopulator">
* &lt;constructor-arg ref="contextSource"/>
* &lt;constructor-arg value="ou=groups"/>
* &lt;property name="groupRoleAttribute" value="ou"/>
* &lt;constructor-arg>&lt;ref local="contextSource"/>&lt;/constructor-arg>
* &lt;constructor-arg>&lt;value>ou=groups&lt;/value>&lt;/constructor-arg>
* &lt;property name="groupRoleAttribute">&lt;value>ou&lt;/value>&lt;/property>
* &lt;!-- the following properties are shown with their default values -->
* &lt;property name="searchSubTree" value="false"/>
* &lt;property name="rolePrefix" value="ROLE_"/>
* &lt;property name="convertToUpperCase" value="true"/>
* &lt;property name="searchSubTree">&lt;value>false&lt;/value>&lt;/property>
* &lt;property name="rolePrefix">&lt;value>ROLE_&lt;/value>&lt;/property>
* &lt;property name="convertToUpperCase">&lt;value>true&lt;/value>&lt;/property>
* &lt;/bean>
* </pre>
* A search for roles for user "uid=ben,ou=people,dc=springframework,dc=org" would return the single granted authority
@@ -284,10 +284,6 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
this.groupSearchFilter = groupSearchFilter;
}
/**
* Sets the prefix which will be prepended to the values loaded from the directory.
* Defaults to "ROLE_" for compatibility with <tt>RoleVoter/tt>.
*/
public void setRolePrefix(String rolePrefix) {
Assert.notNull(rolePrefix, "rolePrefix must not be null");
this.rolePrefix = rolePrefix;
@@ -21,9 +21,7 @@ import org.springframework.security.AuthenticationException;
import org.springframework.security.AuthenticationManager;
import org.springframework.security.util.RedirectUtils;
import org.springframework.security.util.SessionUtils;
import org.springframework.security.util.UrlUtils;
import org.springframework.security.concurrent.SessionRegistry;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.event.authentication.InteractiveAuthenticationSuccessEvent;
@@ -45,6 +43,10 @@ import org.springframework.util.Assert;
import java.io.IOException;
import java.util.Properties;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
@@ -208,18 +210,13 @@ public abstract class AbstractProcessingFilter extends SpringSecurityFilter impl
private boolean allowSessionCreation = true;
private boolean serverSideRedirect = false;
private SessionRegistry sessionRegistry;
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
Assert.hasLength(filterProcessesUrl, "filterProcessesUrl must be specified");
Assert.isTrue(UrlUtils.isValidRedirectUrl(filterProcessesUrl), filterProcessesUrl + " isn't a valid redirect URL");
Assert.hasLength(defaultTargetUrl, "defaultTargetUrl must be specified");
Assert.isTrue(UrlUtils.isValidRedirectUrl(defaultTargetUrl), defaultTargetUrl + " isn't a valid redirect URL");
// Assert.hasLength(authenticationFailureUrl, "authenticationFailureUrl must be specified");
Assert.isTrue(UrlUtils.isValidRedirectUrl(authenticationFailureUrl), authenticationFailureUrl + " isn't a valid redirect URL");
Assert.notNull(authenticationManager, "authenticationManager must be specified");
Assert.notNull(rememberMeServices, "rememberMeServices cannot be null");
Assert.notNull(targetUrlResolver, "targetUrlResolver cannot be null");
@@ -358,7 +355,7 @@ public abstract class AbstractProcessingFilter extends SpringSecurityFilter impl
}
if (invalidateSessionOnSuccessfulAuthentication) {
SessionUtils.startNewSessionIfRequired(request, migrateInvalidatedSessionAttributes, sessionRegistry);
SessionUtils.startNewSessionIfRequired(request, migrateInvalidatedSessionAttributes, null);
}
String targetUrl = determineTargetUrl(request);
@@ -570,13 +567,5 @@ public abstract class AbstractProcessingFilter extends SpringSecurityFilter impl
*/
public void setServerSideRedirect(boolean serverSideRedirect) {
this.serverSideRedirect = serverSideRedirect;
}
/**
* The session registry needs to be set if session fixation attack protection is in use (and concurrent
* session control is enabled).
*/
public void setSessionRegistry(SessionRegistry sessionRegistry) {
this.sessionRegistry = sessionRegistry;
}
}
}
@@ -54,7 +54,7 @@ public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
//~ Methods ========================================================================================================
public void handle(ServletRequest request, ServletResponse response, AccessDeniedException accessDeniedException)
throws IOException, ServletException {
throws IOException, ServletException {
if (errorPage != null) {
// Put exception into request scope (perhaps of use to a view)
((HttpServletRequest) request).setAttribute(SPRING_SECURITY_ACCESS_DENIED_EXCEPTION_KEY,
@@ -80,7 +80,7 @@ public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
*/
public void setErrorPage(String errorPage) {
if ((errorPage != null) && !errorPage.startsWith("/")) {
throw new IllegalArgumentException("errorPage must begin with '/'");
throw new IllegalArgumentException("ErrorPage must begin with '/'");
}
this.errorPage = errorPage;
@@ -22,7 +22,8 @@ public abstract class FilterChainOrder {
public static final int CHANNEL_FILTER = FILTER_CHAIN_FIRST;
public static final int CONCURRENT_SESSION_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++;
public static final int HTTP_SESSION_CONTEXT_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++;
public static final int HTTP_SESSION_CONTEXT_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++;
public static final int SESSION_FIXATION_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++;
public static final int LOGOUT_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++;
public static final int X509_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++;
public static final int PRE_AUTH_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++;
@@ -36,7 +37,6 @@ public abstract class FilterChainOrder {
public static final int ANONYMOUS_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++;
public static final int EXCEPTION_TRANSLATION_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++;
public static final int NTLM_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++;
public static final int SESSION_FIXATION_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++;
public static final int FILTER_SECURITY_INTERCEPTOR = FILTER_CHAIN_FIRST + INTERVAL * i++;
public static final int SWITCH_USER_FILTER = FILTER_CHAIN_FIRST + INTERVAL * i++;
@@ -46,6 +46,7 @@ public abstract class FilterChainOrder {
filterNameToOrder.put("FIRST", new Integer(Integer.MIN_VALUE));
filterNameToOrder.put("CHANNEL_FILTER", new Integer(CHANNEL_FILTER));
filterNameToOrder.put("CONCURRENT_SESSION_FILTER", new Integer(CONCURRENT_SESSION_FILTER));
filterNameToOrder.put("SESSION_CONTEXT_INTEGRATION_FILTER", new Integer(HTTP_SESSION_CONTEXT_FILTER));
filterNameToOrder.put("LOGOUT_FILTER", new Integer(LOGOUT_FILTER));
filterNameToOrder.put("X509_FILTER", new Integer(X509_FILTER));
filterNameToOrder.put("PRE_AUTH_FILTER", new Integer(PRE_AUTH_FILTER));
@@ -58,7 +59,6 @@ public abstract class FilterChainOrder {
filterNameToOrder.put("ANONYMOUS_FILTER", new Integer(ANONYMOUS_FILTER));
filterNameToOrder.put("EXCEPTION_TRANSLATION_FILTER", new Integer(EXCEPTION_TRANSLATION_FILTER));
filterNameToOrder.put("NTLM_FILTER", new Integer(NTLM_FILTER));
filterNameToOrder.put("SESSION_CONTEXT_INTEGRATION_FILTER", new Integer(HTTP_SESSION_CONTEXT_FILTER));
filterNameToOrder.put("FILTER_SECURITY_INTERCEPTOR", new Integer(FILTER_SECURITY_INTERCEPTOR));
filterNameToOrder.put("SWITCH_USER_FILTER", new Integer(SWITCH_USER_FILTER));
filterNameToOrder.put("LAST", new Integer(Integer.MAX_VALUE));
@@ -6,23 +6,24 @@ import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServletResponseWrapper;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationTrustResolver;
import org.springframework.security.AuthenticationTrustResolverImpl;
import org.springframework.security.concurrent.SessionRegistry;
import org.springframework.security.context.HttpSessionContextIntegrationFilter;
import org.springframework.security.context.SecurityContext;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.util.SessionUtils;
/**
* Detects that a user has been authenticated since the start of the request and starts a new session.
* <p>
* This is essentially a generalization of the functionality that was implemented for SEC-399.
* Additionally, it will update the configured SessionRegistry if one is in use, thus preventing problems when used
* with Spring Security's concurrent session control.
* This is essentially a generalization of the functionality that was implemented for SEC-399. Additionally, it will
* update the configured SessionRegistry if one is in use, thus preventing problems when used with Spring Security's
* concurrent session control.
* <p>
* If the response has already been committed when the filter checks the authentication state, then it isn't possible
* to create a new session and the filter will print a warning to that effect.
*
* @author Martin Algesten
* @author Luke Taylor
@@ -54,17 +55,22 @@ public class SessionFixationProtectionFilter extends SpringSecurityFilter {
}
request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
HttpSession session = request.getSession();
SecurityContext sessionSecurityContext =
(SecurityContext) session.getAttribute(HttpSessionContextIntegrationFilter.SPRING_SECURITY_CONTEXT_KEY);
if (sessionSecurityContext == null && isAuthenticated()) {
// The user has been authenticated during the current request, so do the session migration
startNewSessionIfRequired(request, response);
if (isAuthenticated()) {
// We don't have to worry about session fixation attack if already authenticated
chain.doFilter(request, response);
return;
}
SessionFixationProtectionResponseWrapper wrapper =
new SessionFixationProtectionResponseWrapper(response, request);
try {
chain.doFilter(request, wrapper);
} finally {
if (!wrapper.isNewSessionStarted()) {
startNewSessionIfRequired(request, response);
}
}
chain.doFilter(request, response);
}
private boolean isAuthenticated() {
@@ -86,12 +92,83 @@ public class SessionFixationProtectionFilter extends SpringSecurityFilter {
}
/**
* Called when the a user wasn't authenticated at the start of the request but has been during it
* Called when the an initially unauthenticated request completes or a redirect or sendError occurs.
* <p>
* A new session will be created, the session attributes copied to it (if
* <tt>migrateSessionAttributes</tt> is set) and the sessionRegistry updated with the new session information.
* If the user is now authenticated, a new session will be created, the session attributes copied to it (if
* <tt>migrateSessionAttributes</tt> is set and the sessionRegistry updated with the new session information.
*/
protected void startNewSessionIfRequired(HttpServletRequest request, HttpServletResponse response) {
SessionUtils.startNewSessionIfRequired(request, migrateSessionAttributes, sessionRegistry);
protected void startNewSessionIfRequired(HttpServletRequest request, HttpServletResponse response) {
if (isAuthenticated()) {
if (request.getSession(false) != null && response.isCommitted()) {
logger.warn("Response is already committed. Unable to create new session.");
}
SessionUtils.startNewSessionIfRequired(request, migrateSessionAttributes, sessionRegistry);
}
}
/**
* Response wrapper to handle the situation where we need to migrate the session after a redirect or sendError.
* Similar in function to Martin Algesten's OnRedirectUpdateSessionResponseWrapper used in
* HttpSessionContextIntegrationFilter.
* <p>
* Only used to wrap the response if the conditions are right at the start of the request to potentially
* require starting a new session, i.e. that the user isn't authenticated and a session existed to begin with.
*/
class SessionFixationProtectionResponseWrapper extends HttpServletResponseWrapper {
private HttpServletRequest request;
private boolean newSessionStarted;
SessionFixationProtectionResponseWrapper(HttpServletResponse response, HttpServletRequest request) {
super(response);
this.request = request;
}
/**
* Makes sure a new session is created before calling the
* superclass <code>sendError()</code>
*/
public void sendError(int sc) throws IOException {
startNewSession();
super.sendError(sc);
}
/**
* Makes sure a new session is created before calling the
* superclass <code>sendError()</code>
*/
public void sendError(int sc, String msg) throws IOException {
startNewSession();
super.sendError(sc, msg);
}
/**
* Makes sure a new session is created before calling the
* superclass <code>sendRedirect()</code>
*/
public void sendRedirect(String location) throws IOException {
startNewSession();
super.sendRedirect(location);
}
public void flushBuffer() throws IOException {
startNewSession();
super.flushBuffer();
}
/**
* Calls <code>startNewSessionIfRequired()</code>
*/
private void startNewSession() {
if (newSessionStarted) {
return;
}
startNewSessionIfRequired(request, this);
newSessionStarted = true;
}
boolean isNewSessionStarted() {
return newSessionStarted;
}
}
}
@@ -25,7 +25,6 @@ import org.springframework.security.ui.savedrequest.SavedRequest;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Default implementation for {@link TargetUrlResolver}
* <p>
@@ -47,10 +46,11 @@ public class TargetUrlResolverImpl implements TargetUrlResolver {
/**
* If <code>true</code>, will only use <code>SavedRequest</code> to determine the target URL on successful
* authentication if the request that caused the authentication request was a GET.
* It will then return null for a POST/PUT request.
* Defaults to false.
* It will return null for a POST/PUT request.
* In most cases it's meaningless to redirect to a URL generated by a POST/PUT request.
* Defaults to true.
*/
private boolean justUseSavedRequestOnGet = false;
private boolean justUseSavedRequestOnGet = true;
/* (non-Javadoc)
* @see org.acegisecurity.ui.TargetUrlResolver#determineTargetUrl(org.acegisecurity.ui.savedrequest.SavedRequest, javax.servlet.http.HttpServletRequest, org.acegisecurity.Authentication)
@@ -93,7 +93,6 @@ public class BasicProcessingFilter extends SpringSecurityFilter implements Initi
private AuthenticationManager authenticationManager;
private RememberMeServices rememberMeServices;
private boolean ignoreFailure = false;
private String credentialsCharset = "UTF-8";
//~ Methods ========================================================================================================
@@ -115,8 +114,8 @@ public class BasicProcessingFilter extends SpringSecurityFilter implements Initi
}
if ((header != null) && header.startsWith("Basic ")) {
byte[] base64Token = header.substring(6).getBytes("UTF-8");
String token = new String(Base64.decodeBase64(base64Token), getCredentialsCharset(httpRequest));
String base64Token = header.substring(6);
String token = new String(Base64.decodeBase64(base64Token.getBytes()));
String username = "";
String password = "";
@@ -173,7 +172,7 @@ public class BasicProcessingFilter extends SpringSecurityFilter implements Initi
chain.doFilter(httpRequest, httpResponse);
}
private boolean authenticationIsRequired(String username) {
private boolean authenticationIsRequired(String username) {
// Only reauthenticate if username doesn't match SecurityContextHolder and user isn't authenticated
// (see SEC-53)
Authentication existingAuth = SecurityContextHolder.getContext().getAuthentication();
@@ -236,16 +235,7 @@ public class BasicProcessingFilter extends SpringSecurityFilter implements Initi
this.rememberMeServices = rememberMeServices;
}
public void setCredentialsCharset(String credentialsCharset) {
Assert.hasText(credentialsCharset, "credentialsCharset cannot be null or empty");
this.credentialsCharset = credentialsCharset;
}
protected String getCredentialsCharset(HttpServletRequest httpRequest) {
return credentialsCharset;
}
public int getOrder() {
public int getOrder() {
return FilterChainOrder.BASIC_PROCESSING_FILTER;
}
}
@@ -26,7 +26,6 @@ import org.springframework.security.Authentication;
import org.springframework.security.ui.SpringSecurityFilter;
import org.springframework.security.ui.FilterChainOrder;
import org.springframework.security.util.RedirectUtils;
import org.springframework.security.util.UrlUtils;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -59,7 +58,6 @@ public class LogoutFilter extends SpringSecurityFilter {
public LogoutFilter(String logoutSuccessUrl, LogoutHandler[] handlers) {
Assert.notEmpty(handlers, "LogoutHandlers are required");
this.logoutSuccessUrl = logoutSuccessUrl;
Assert.isTrue(UrlUtils.isValidRedirectUrl(logoutSuccessUrl), logoutSuccessUrl + " isn't a valid redirect URL");
this.handlers = handlers;
}
@@ -132,7 +130,7 @@ public class LogoutFilter extends SpringSecurityFilter {
String targetUrl = request.getParameter("logoutSuccessUrl");
if(!StringUtils.hasLength(targetUrl)) {
targetUrl = getLogoutSuccessUrl();
targetUrl = logoutSuccessUrl;
}
if (!StringUtils.hasLength(targetUrl)) {
@@ -163,14 +161,9 @@ public class LogoutFilter extends SpringSecurityFilter {
public void setFilterProcessesUrl(String filterProcessesUrl) {
Assert.hasText(filterProcessesUrl, "FilterProcessesUrl required");
Assert.isTrue(UrlUtils.isValidRedirectUrl(filterProcessesUrl), filterProcessesUrl + " isn't a valid redirect URL");
this.filterProcessesUrl = filterProcessesUrl;
}
protected String getLogoutSuccessUrl() {
return logoutSuccessUrl;
}
protected String getFilterProcessesUrl() {
return filterProcessesUrl;
}
@@ -24,182 +24,171 @@ import org.apache.commons.logging.LogFactory;
* @since 2.0
*/
final class WASSecurityHelper {
private static final Log logger = LogFactory.getLog(WASSecurityHelper.class);
private static final Log logger = LogFactory.getLog(WASSecurityHelper.class);
private static final String USER_REGISTRY = "UserRegistry";
private static final String USER_REGISTRY = "UserRegistry";
private static Method getRunAsSubject = null;
private static Method getRunAsSubject = null;
private static Method getGroupsForUser = null;
private static Method getWSCredentialFromSubject = null;
private static Method getSecurityName = null;
private static Method getGroupsForUser = null;
// SEC-803
private static Class wsCredentialClass = null;
/**
* Get the security name for the given subject.
*
* @param subject
* The subject for which to retrieve the security name
* @return String the security name for the given subject
*/
private static final String getSecurityName(final Subject subject) {
if (logger.isDebugEnabled()) {
logger.debug("Determining Websphere security name for subject " + subject);
}
String userSecurityName = null;
if (subject != null) {
// SEC-803
Object credential = subject.getPublicCredentials(getWSCredentialClass()).iterator().next();
if (credential != null) {
userSecurityName = (String)invokeMethod(getSecurityNameMethod(),credential,null);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Websphere security name is " + userSecurityName + " for subject " + subject);
}
return userSecurityName;
}
private static Method getSecurityName = null;
/**
* Get the current RunAs subject.
*
* @return Subject the current RunAs subject
*/
private static final Subject getRunAsSubject() {
logger.debug("Retrieving WebSphere RunAs subject");
// get Subject: WSSubject.getCallerSubject ();
return (Subject) invokeMethod(getRunAsSubjectMethod(), null, new Object[] {});
}
/**
* Get the security name for the given subject.
*
* @param subject
* The subject for which to retrieve the security name
* @return String the security name for the given subject
*/
private static final String getSecurityName(final Subject subject) {
if (logger.isDebugEnabled()) {
logger.debug("Determining Websphere security name for subject " + subject);
}
String userSecurityName = null;
if (subject != null) {
Object credential = invokeMethod(getWSCredentialFromSubjectMethod(),null,new Object[]{subject});
if (credential != null) {
userSecurityName = (String)invokeMethod(getSecurityNameMethod(),credential,null);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Websphere security name is " + userSecurityName + " for subject " + subject);
}
return userSecurityName;
}
/**
* Get the WebSphere group names for the given subject.
*
* @param subject
* The subject for which to retrieve the WebSphere group names
* @return the WebSphere group names for the given subject
*/
private static final String[] getWebSphereGroups(final Subject subject) {
return getWebSphereGroups(getSecurityName(subject));
}
/**
* Get the current RunAs subject.
*
* @return Subject the current RunAs subject
*/
private static final Subject getRunAsSubject() {
logger.debug("Retrieving WebSphere RunAs subject");
// get Subject: WSSubject.getCallerSubject ();
return (Subject) invokeMethod(getRunAsSubjectMethod(), null, new Object[] {});
}
/**
* Get the WebSphere group names for the given security name.
*
* @param securityName
* The securityname for which to retrieve the WebSphere group names
* @return the WebSphere group names for the given security name
*/
private static final String[] getWebSphereGroups(final String securityName) {
Context ic = null;
try {
// TODO: Cache UserRegistry object
ic = new InitialContext();
Object objRef = ic.lookup(USER_REGISTRY);
Object userReg = PortableRemoteObject.narrow(objRef, Class.forName ("com.ibm.websphere.security.UserRegistry"));
if (logger.isDebugEnabled()) {
logger.debug("Determining WebSphere groups for user " + securityName + " using WebSphere UserRegistry " + userReg);
}
final Collection groups = (Collection) invokeMethod(getGroupsForUserMethod(), userReg, new Object[]{ securityName });
if (logger.isDebugEnabled()) {
logger.debug("Groups for user " + securityName + ": " + groups.toString());
}
String[] result = new String[groups.size()];
return (String[]) groups.toArray(result);
} catch (Exception e) {
logger.error("Exception occured while looking up groups for user", e);
throw new RuntimeException("Exception occured while looking up groups for user", e);
} finally {
try {
ic.close();
} catch (NamingException e) {
logger.debug("Exception occured while closing context", e);
}
}
}
/**
* Get the WebSphere group names for the given subject.
*
* @param subject
* The subject for which to retrieve the WebSphere group names
* @return the WebSphere group names for the given subject
*/
private static final String[] getWebSphereGroups(final Subject subject) {
return getWebSphereGroups(getSecurityName(subject));
}
/**
* @return
*/
public static final String[] getGroupsForCurrentUser() {
return getWebSphereGroups(getRunAsSubject());
}
/**
* Get the WebSphere group names for the given security name.
*
* @param securityName
* The securityname for which to retrieve the WebSphere group names
* @return the WebSphere group names for the given security name
*/
private static final String[] getWebSphereGroups(final String securityName) {
Context ic = null;
try {
// TODO: Cache UserRegistry object
ic = new InitialContext();
Object objRef = ic.lookup(USER_REGISTRY);
Object userReg = PortableRemoteObject.narrow(objRef, Class.forName ("com.ibm.websphere.security.UserRegistry"));
if (logger.isDebugEnabled()) {
logger.debug("Determining WebSphere groups for user " + securityName + " using WebSphere UserRegistry " + userReg);
}
final Collection groups = (Collection) invokeMethod(getGroupsForUserMethod(), userReg, new Object[]{ securityName });
if (logger.isDebugEnabled()) {
logger.debug("Groups for user " + securityName + ": " + groups.toString());
}
String[] result = new String[groups.size()];
return (String[]) groups.toArray(result);
} catch (Exception e) {
logger.error("Exception occured while looking up groups for user", e);
throw new RuntimeException("Exception occured while looking up groups for user", e);
} finally {
try {
ic.close();
} catch (NamingException e) {
logger.debug("Exception occured while closing context", e);
}
}
}
public static final String getCurrentUserName() {
return getSecurityName(getRunAsSubject());
}
private static final Object invokeMethod(Method method, Object instance, Object[] args)
{
try {
return method.invoke(instance,args);
} catch (IllegalArgumentException e) {
logger.error("Error while invoking method "+method.getClass().getName()+"."+method.getName()+"("+ Arrays.asList(args)+")",e);
throw new RuntimeException("Error while invoking method "+method.getClass().getName()+"."+method.getName()+"("+Arrays.asList(args)+")",e);
} catch (IllegalAccessException e) {
logger.error("Error while invoking method "+method.getClass().getName()+"."+method.getName()+"("+Arrays.asList(args)+")",e);
throw new RuntimeException("Error while invoking method "+method.getClass().getName()+"."+method.getName()+"("+Arrays.asList(args)+")",e);
} catch (InvocationTargetException e) {
logger.error("Error while invoking method "+method.getClass().getName()+"."+method.getName()+"("+Arrays.asList(args)+")",e);
throw new RuntimeException("Error while invoking method "+method.getClass().getName()+"."+method.getName()+"("+Arrays.asList(args)+")",e);
}
}
/**
* @return
*/
public static final String[] getGroupsForCurrentUser() {
return getWebSphereGroups(getRunAsSubject());
}
private static final Method getMethod(String className, String methodName, String[] parameterTypeNames) {
try {
Class c = Class.forName(className);
final int len = parameterTypeNames.length;
Class[] parameterTypes = new Class[len];
for (int i = 0; i < len; i++) {
parameterTypes[i] = Class.forName(parameterTypeNames[i]);
}
return c.getDeclaredMethod(methodName, parameterTypes);
} catch (ClassNotFoundException e) {
logger.error("Required class"+className+" not found");
throw new RuntimeException("Required class"+className+" not found",e);
} catch (NoSuchMethodException e) {
logger.error("Required method "+methodName+" with parameter types ("+ Arrays.asList(parameterTypeNames) +") not found on class "+className);
throw new RuntimeException("Required class"+className+" not found",e);
}
}
public static final String getCurrentUserName() {
return getSecurityName(getRunAsSubject());
}
private static final Object invokeMethod(Method method, Object instance, Object[] args)
{
try {
return method.invoke(instance,args);
} catch (IllegalArgumentException e) {
logger.error("Error while invoking method "+method.getClass().getName()+"."+method.getName()+"("+ Arrays.asList(args)+")",e);
throw new RuntimeException("Error while invoking method "+method.getClass().getName()+"."+method.getName()+"("+Arrays.asList(args)+")",e);
} catch (IllegalAccessException e) {
logger.error("Error while invoking method "+method.getClass().getName()+"."+method.getName()+"("+Arrays.asList(args)+")",e);
throw new RuntimeException("Error while invoking method "+method.getClass().getName()+"."+method.getName()+"("+Arrays.asList(args)+")",e);
} catch (InvocationTargetException e) {
logger.error("Error while invoking method "+method.getClass().getName()+"."+method.getName()+"("+Arrays.asList(args)+")",e);
throw new RuntimeException("Error while invoking method "+method.getClass().getName()+"."+method.getName()+"("+Arrays.asList(args)+")",e);
}
}
private static final Method getRunAsSubjectMethod() {
if (getRunAsSubject == null) {
getRunAsSubject = getMethod("com.ibm.websphere.security.auth.WSSubject", "getRunAsSubject", new String[] {});
}
return getRunAsSubject;
}
private static final Method getMethod(String className, String methodName, String[] parameterTypeNames) {
try {
Class c = Class.forName(className);
final int len = parameterTypeNames.length;
Class[] parameterTypes = new Class[len];
for (int i = 0; i < len; i++) {
parameterTypes[i] = Class.forName(parameterTypeNames[i]);
}
return c.getDeclaredMethod(methodName, parameterTypes);
} catch (ClassNotFoundException e) {
logger.error("Required class"+className+" not found");
throw new RuntimeException("Required class"+className+" not found",e);
} catch (NoSuchMethodException e) {
logger.error("Required method "+methodName+" with parameter types ("+ Arrays.asList(parameterTypeNames) +") not found on class "+className);
throw new RuntimeException("Required class"+className+" not found",e);
}
}
private static final Method getGroupsForUserMethod() {
if (getGroupsForUser == null) {
getGroupsForUser = getMethod("com.ibm.websphere.security.UserRegistry", "getGroupsForUser", new String[] { "java.lang.String" });
}
return getGroupsForUser;
}
private static final Method getRunAsSubjectMethod() {
if (getRunAsSubject == null) {
getRunAsSubject = getMethod("com.ibm.websphere.security.auth.WSSubject", "getRunAsSubject", new String[] {});
}
return getRunAsSubject;
}
private static final Method getSecurityNameMethod() {
if (getSecurityName == null) {
getSecurityName = getMethod("com.ibm.websphere.security.cred.WSCredential", "getSecurityName", new String[] {});
}
return getSecurityName;
}
// SEC-803
private static final Class getWSCredentialClass() {
if (wsCredentialClass == null) {
wsCredentialClass = getClass("com.ibm.websphere.security.cred.WSCredential");
}
return wsCredentialClass;
}
private static final Class getClass(String className) {
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
logger.error("Required class " + className + " not found");
throw new RuntimeException("Required class " + className + " not found",e);
}
}
private static final Method getWSCredentialFromSubjectMethod() {
if (getWSCredentialFromSubject == null) {
getWSCredentialFromSubject = getMethod("com.ibm.ws.security.auth.SubjectHelper", "getWSCredentialFromSubject",
new String[] { "javax.security.auth.Subject" });
}
return getWSCredentialFromSubject;
}
private static final Method getGroupsForUserMethod() {
if (getGroupsForUser == null) {
getGroupsForUser = getMethod("com.ibm.websphere.security.UserRegistry", "getGroupsForUser", new String[] { "java.lang.String" });
}
return getGroupsForUser;
}
private static final Method getSecurityNameMethod() {
if (getSecurityName == null) {
getSecurityName = getMethod("com.ibm.websphere.security.cred.WSCredential", "getSecurityName", new String[] {});
}
return getSecurityName;
}
}
@@ -1,7 +1,6 @@
package org.springframework.security.ui.preauth.websphere;
import java.util.Arrays;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
@@ -69,8 +68,8 @@ public class WebSpherePreAuthenticatedAuthenticationDetailsSource extends Authen
String[] webSphereGroups = WASSecurityHelper.getGroupsForCurrentUser();
GrantedAuthority[] userGas = webSphereGroups2GrantedAuthoritiesMapper.getGrantedAuthorities(webSphereGroups);
if (LOG.isDebugEnabled()) {
LOG.debug("WebSphere groups: " + Arrays.asList(webSphereGroups) + " mapped to Granted Authorities: "
+ Arrays.asList(userGas));
LOG.debug("WebSphere groups [" + ArrayUtils.toString(webSphereGroups) + "] mapped to Granted Authorities: ["
+ ArrayUtils.toString(userGas) + "]");
}
return userGas;
}
@@ -313,14 +313,7 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
this.alwaysRemember = alwaysRemember;
}
/**
* Sets the name of the parameter which should be checked for to see if a remember-me has been requested
* during a login request. This should be the same name you assign to the checkbox in your login form.
*
* @param parameter the HTTP request parameter
*/
public void setParameter(String parameter) {
Assert.hasText(parameter, "Parameter name cannot be null");
this.parameter = parameter;
}
@@ -333,7 +326,6 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
}
public void setUserDetailsService(UserDetailsService userDetailsService) {
Assert.notNull(userDetailsService, "UserDetailsService canot be null");
this.userDetailsService = userDetailsService;
}
@@ -356,9 +348,4 @@ public abstract class AbstractRememberMeServices implements RememberMeServices,
protected AuthenticationDetailsSource getAuthenticationDetailsSource() {
return authenticationDetailsSource;
}
public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {
Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource cannot be null");
this.authenticationDetailsSource = authenticationDetailsSource;
}
}
@@ -152,7 +152,7 @@ public class TokenBasedRememberMeServices extends AbstractRememberMeServices {
}
int tokenLifetime = calculateLoginLifetime(request, successfulAuthentication);
long expiryTime = System.currentTimeMillis() + 1000L*tokenLifetime;
long expiryTime = System.currentTimeMillis() + 1000*tokenLifetime;
String signatureValue = makeTokenSignature(expiryTime, username, password);
@@ -22,7 +22,6 @@ import org.springframework.security.providers.UsernamePasswordAuthenticationToke
import org.springframework.security.ui.AbstractProcessingFilter;
import org.springframework.security.ui.FilterChainOrder;
import org.springframework.security.util.TextUtils;
import org.springframework.util.Assert;
import javax.servlet.http.HttpServletRequest;
@@ -73,7 +72,7 @@ public class AuthenticationProcessingFilter extends AbstractProcessingFilter {
HttpSession session = request.getSession(false);
if (session != null || getAllowSessionCreation()) {
request.getSession().setAttribute(SPRING_SECURITY_LAST_USERNAME_KEY, TextUtils.escapeEntities(username));
request.getSession().setAttribute(SPRING_SECURITY_LAST_USERNAME_KEY, username);
}
// Allow subclasses to set the "details" property
@@ -76,7 +76,8 @@ public class DefaultLoginPageGeneratingFilter extends SpringSecurityFilter {
protected void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
if (isLoginUrlRequest(request)) {
String loginPageHtml = generateLoginPageHtml(request);
response.setContentType("text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html");
response.setContentLength(loginPageHtml.length());
response.getOutputStream().print(loginPageHtml);
@@ -126,7 +126,7 @@ public class RoleHierarchyImpl implements RoleHierarchy {
* references a set of the reachable lower roles.
*/
private void buildRolesReachableInOneStepMap() {
String parsingRegex = "(\\s*([^\\s>]+)\\s*\\>\\s*([^\\s>]+))";
String parsingRegex = "(\\s*(\\w+)\\s*\\>\\s*(\\w+))";
Pattern pattern = Pattern.compile(parsingRegex);
Matcher roleHierarchyMatcher = pattern.matcher(roleHierarchyStringRepresentation);
@@ -15,17 +15,19 @@ import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsManager;
import org.springframework.security.userdetails.GroupManager;
import org.springframework.context.ApplicationContextException;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.object.MappingSqlQuery;
import org.springframework.jdbc.object.SqlQuery;
import org.springframework.jdbc.object.SqlUpdate;
import org.springframework.util.Assert;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.sql.PreparedStatement;
import javax.sql.DataSource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.List;
/**
@@ -114,6 +116,28 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
private String groupAuthoritiesSql = DEF_GROUP_AUTHORITIES_QUERY_SQL;
private String deleteGroupAuthoritySql = DEF_DELETE_GROUP_AUTHORITY_SQL;
private SqlUpdate insertUser;
private SqlUpdate deleteUser;
private SqlUpdate updateUser;
private SqlUpdate insertAuthority;
private SqlUpdate deleteUserAuthorities;
private SqlQuery userExistsQuery;
private SqlUpdate changePassword;
private SqlQuery findAllGroupsQuery;
private SqlQuery findUsersInGroupQuery;
private SqlUpdate insertGroup;
private SqlQuery findGroupIdQuery;
private SqlUpdate insertGroupAuthority;
private SqlUpdate deleteGroup;
private SqlUpdate deleteGroupMembers;
private SqlUpdate deleteGroupAuthorities;
private SqlUpdate renameGroup;
private SqlUpdate insertGroupMember;
private SqlUpdate deleteGroupMember;
private SqlQuery groupAuthoritiesQuery;
private SqlUpdate deleteGroupAuthority;
private AuthenticationManager authenticationManager;
private UserCache userCache = new NullUserCache();
@@ -126,36 +150,43 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
"not be performed.");
}
insertUser = new InsertUser(getDataSource());
deleteUser = new DeleteUser(getDataSource());
updateUser = new UpdateUser(getDataSource());
insertAuthority = new InsertAuthority(getDataSource());
deleteUserAuthorities = new DeleteUserAuthorities(getDataSource());
userExistsQuery = new UserExistsQuery(getDataSource());
changePassword = new ChangePassword(getDataSource());
findAllGroupsQuery = new AllGroupsQuery(getDataSource());
findUsersInGroupQuery = new GroupMembersQuery(getDataSource());
insertGroup = new InsertGroup(getDataSource());
findGroupIdQuery = new FindGroupIdQuery(getDataSource());
insertGroupAuthority = new InsertGroupAuthority(getDataSource());
deleteGroup = new DeleteGroup(getDataSource());
deleteGroupAuthorities = new DeleteGroupAuthorities(getDataSource());
deleteGroupMembers = new DeleteGroupMembers(getDataSource());
renameGroup = new RenameGroup(getDataSource());
insertGroupMember = new InsertGroupMember(getDataSource());
deleteGroupMember = new DeleteGroupMember (getDataSource());
groupAuthoritiesQuery = new GroupAuthoritiesByGroupNameMapping(getDataSource());
deleteGroupAuthority = new DeleteGroupAuthority(getDataSource());
super.initDao();
}
//~ UserDetailsManager implementation ==============================================================================
public void createUser(final UserDetails user) {
public void createUser(UserDetails user) {
validateUserDetails(user);
getJdbcTemplate().update(createUserSql, new PreparedStatementSetter() {
public void setValues(PreparedStatement ps) throws SQLException {
ps.setString(1, user.getUsername());
ps.setString(2, user.getPassword());
ps.setBoolean(3, user.isEnabled());
}
});
insertUser.update(new Object[] {user.getUsername(), user.getPassword(), Boolean.valueOf(user.isEnabled())});
insertUserAuthorities(user);
}
public void updateUser(final UserDetails user) {
public void updateUser(UserDetails user) {
validateUserDetails(user);
getJdbcTemplate().update(updateUserSql, new PreparedStatementSetter() {
public void setValues(PreparedStatement ps) throws SQLException {
ps.setString(1, user.getPassword());
ps.setBoolean(2, user.isEnabled());
ps.setString(3, user.getUsername());
}
});
deleteUserAuthorities(user.getUsername());
updateUser.update(new Object[] {user.getPassword(), Boolean.valueOf(user.isEnabled()), user.getUsername()});
deleteUserAuthorities.update(user.getUsername());
insertUserAuthorities(user);
userCache.removeUserFromCache(user.getUsername());
@@ -163,20 +194,15 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
private void insertUserAuthorities(UserDetails user) {
for (int i=0; i < user.getAuthorities().length; i++) {
getJdbcTemplate().update(createAuthoritySql,
new Object[] {user.getUsername(), user.getAuthorities()[i].getAuthority()});
insertAuthority.update(user.getUsername(), user.getAuthorities()[i].getAuthority());
}
}
public void deleteUser(String username) {
deleteUserAuthorities(username);
getJdbcTemplate().update(deleteUserSql, new Object[] {username});
deleteUserAuthorities.update(username);
deleteUser.update(username);
userCache.removeUserFromCache(username);
}
private void deleteUserAuthorities(String username) {
getJdbcTemplate().update(deleteUserAuthoritiesSql, new Object[] {username});
}
public void changePassword(String oldPassword, String newPassword) throws AuthenticationException {
Authentication currentUser = SecurityContextHolder.getContext().getAuthentication();
@@ -200,7 +226,7 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
logger.debug("Changing password for user '"+ username + "'");
getJdbcTemplate().update(changePasswordSql, new String[] {newPassword, username});
changePassword.update(new String[] {newPassword, username});
SecurityContextHolder.getContext().setAuthentication(createNewAuthentication(currentUser, newPassword));
@@ -218,10 +244,10 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
}
public boolean userExists(String username) {
List users = getJdbcTemplate().queryForList(userExistsSql, new Object[] {username});
List users = userExistsQuery.execute(username);
if (users.size() > 1) {
throw new IncorrectResultSizeDataAccessException("More than one user found with name '" + username + "'", 1);
throw new IllegalStateException("More than one user found with name '" + username + "'");
}
return users.size() == 1;
@@ -230,33 +256,26 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
//~ GroupManager implementation ====================================================================================
public String[] findAllGroups() {
return (String[]) getJdbcTemplate().queryForList(findAllGroupsSql, String.class).toArray(new String[0]);
return (String[]) findAllGroupsQuery.execute().toArray(new String[0]);
}
public String[] findUsersInGroup(String groupName) {
Assert.hasText(groupName);
return (String[]) getJdbcTemplate().queryForList(findUsersInGroupSql, new String[] {groupName}, String.class).toArray(new String[0]);
return (String[]) findUsersInGroupQuery.execute(groupName).toArray(new String[0]);
}
public void createGroup(final String groupName, final GrantedAuthority[] authorities) {
public void createGroup(String groupName, GrantedAuthority[] authorities) {
Assert.hasText(groupName);
Assert.notNull(authorities);
logger.debug("Creating new group '" + groupName + "' with authorities " +
AuthorityUtils.authorityArrayToSet(authorities));
getJdbcTemplate().update(insertGroupSql, new String[] {groupName});
final int groupId = findGroupId(groupName);
insertGroup.update(groupName);
Integer id = (Integer) findGroupIdQuery.findObject(groupName);
for (int i=0; i < authorities.length; i++) {
final String authority = authorities[i].getAuthority();
getJdbcTemplate().update(insertGroupAuthoritySql, new PreparedStatementSetter() {
public void setValues(PreparedStatement ps) throws SQLException {
ps.setInt(1, groupId);
ps.setString(2, authority);
}
});
insertGroupAuthority.update( new Object[] {id, authorities[i].getAuthority()});
}
}
@@ -264,15 +283,10 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
logger.debug("Deleting group '" + groupName + "'");
Assert.hasText(groupName);
final int id = findGroupId(groupName);
PreparedStatementSetter groupIdPSS = new PreparedStatementSetter() {
public void setValues(PreparedStatement ps) throws SQLException {
ps.setInt(1, id);
}
};
getJdbcTemplate().update(deleteGroupMembersSql, groupIdPSS);
getJdbcTemplate().update(deleteGroupAuthoritiesSql, groupIdPSS);
getJdbcTemplate().update(deleteGroupSql, groupIdPSS);
int id = ((Integer) findGroupIdQuery.findObject(groupName)).intValue();
deleteGroupMembers.update(id);
deleteGroupAuthorities.update(id);
deleteGroup.update(id);
}
public void renameGroup(String oldName, String newName) {
@@ -280,90 +294,54 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
Assert.hasText(oldName);
Assert.hasText(newName);
getJdbcTemplate().update(renameGroupSql, new String[] {newName, oldName});
renameGroup.update(newName, oldName);
}
public void addUserToGroup(final String username, final String groupName) {
public void addUserToGroup(String username, String groupName) {
logger.debug("Adding user '" + username + "' to group '" + groupName + "'");
Assert.hasText(username);
Assert.hasText(groupName);
final int id = findGroupId(groupName);
getJdbcTemplate().update(insertGroupMemberSql, new PreparedStatementSetter() {
public void setValues(PreparedStatement ps) throws SQLException {
ps.setInt(1, id);
ps.setString(2, username);
}
});
Integer id = (Integer) findGroupIdQuery.findObject(groupName);
insertGroupMember.update(new Object[] {id, username});
userCache.removeUserFromCache(username);
}
public void removeUserFromGroup(final String username, final String groupName) {
public void removeUserFromGroup(String username, String groupName) {
logger.debug("Removing user '" + username + "' to group '" + groupName + "'");
Assert.hasText(username);
Assert.hasText(groupName);
final int id = findGroupId(groupName);
getJdbcTemplate().update(deleteGroupMemberSql, new PreparedStatementSetter() {
public void setValues(PreparedStatement ps) throws SQLException {
ps.setInt(1, id);
ps.setString(2, username);
}
});
Integer id = (Integer) findGroupIdQuery.findObject(groupName);
deleteGroupMember.update(new Object[] {id, username});
userCache.removeUserFromCache(username);
}
public GrantedAuthority[] findGroupAuthorities(String groupName) {
logger.debug("Loading authorities for group '" + groupName + "'");
Assert.hasText(groupName);
List authorities = getJdbcTemplate().query(groupAuthoritiesSql, new String[] {groupName}, new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
String roleName = getRolePrefix() + rs.getString(3);
GrantedAuthorityImpl authority = new GrantedAuthorityImpl(roleName);
return authority;
}
});
return (GrantedAuthority[]) authorities.toArray(new GrantedAuthority[0]);
return (GrantedAuthority[]) groupAuthoritiesQuery.execute(groupName).toArray(new GrantedAuthority[0]);
}
public void removeGroupAuthority(String groupName, final GrantedAuthority authority) {
public void removeGroupAuthority(String groupName, GrantedAuthority authority) {
logger.debug("Removing authority '" + authority + "' from group '" + groupName + "'");
Assert.hasText(groupName);
Assert.notNull(authority);
final int id = findGroupId(groupName);
getJdbcTemplate().update(deleteGroupAuthoritySql, new PreparedStatementSetter() {
public void setValues(PreparedStatement ps) throws SQLException {
ps.setInt(1, id);
ps.setString(2, authority.getAuthority());
}
});
Integer id = (Integer) findGroupIdQuery.findObject(groupName);
deleteGroupAuthority.update(new Object[] {id, authority});
}
public void addGroupAuthority(final String groupName, final GrantedAuthority authority) {
public void addGroupAuthority(String groupName, GrantedAuthority authority) {
logger.debug("Adding authority '" + authority + "' to group '" + groupName + "'");
Assert.hasText(groupName);
Assert.notNull(authority);
final int id = findGroupId(groupName);
getJdbcTemplate().update(insertGroupAuthoritySql, new PreparedStatementSetter() {
public void setValues(PreparedStatement ps) throws SQLException {
ps.setInt(1, id);
ps.setString(2, authority.getAuthority());
}
});
}
private int findGroupId(String group) {
return getJdbcTemplate().queryForInt(findGroupIdSql, new Object[] {group});
Integer id = (Integer) findGroupIdQuery.findObject(groupName);
insertGroupAuthority.update(new Object[] {id, authority.getAuthority()});
}
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
@@ -433,4 +411,201 @@ public class JdbcUserDetailsManager extends JdbcDaoImpl implements UserDetailsMa
Assert.hasText(authorities[i].getAuthority(), "getAuthority() method must return a non-empty string");
}
}
//~ Inner Classes ==================================================================================================
private class InsertUser extends SqlUpdate {
public InsertUser(DataSource ds) {
super(ds, createUserSql);
declareParameter(new SqlParameter(Types.VARCHAR));
declareParameter(new SqlParameter(Types.VARCHAR));
declareParameter(new SqlParameter(Types.BOOLEAN));
compile();
}
}
private class DeleteUser extends SqlUpdate {
public DeleteUser(DataSource ds) {
super(ds, deleteUserSql);
declareParameter(new SqlParameter(Types.VARCHAR));
compile();
}
}
private class InsertAuthority extends SqlUpdate {
public InsertAuthority(DataSource ds) {
super(ds, createAuthoritySql);
declareParameter(new SqlParameter(Types.VARCHAR));
declareParameter(new SqlParameter(Types.VARCHAR));
compile();
}
}
private class DeleteUserAuthorities extends SqlUpdate {
public DeleteUserAuthorities(DataSource ds) {
super(ds, deleteUserAuthoritiesSql);
declareParameter(new SqlParameter(Types.VARCHAR));
compile();
}
}
private class UpdateUser extends SqlUpdate {
public UpdateUser(DataSource ds) {
super(ds, updateUserSql);
declareParameter(new SqlParameter(Types.VARCHAR));
declareParameter(new SqlParameter(Types.BOOLEAN));
declareParameter(new SqlParameter(Types.VARCHAR));
compile();
}
}
private class ChangePassword extends SqlUpdate {
public ChangePassword(DataSource ds) {
super(ds, changePasswordSql);
declareParameter(new SqlParameter(Types.VARCHAR));
declareParameter(new SqlParameter(Types.VARCHAR));
compile();
}
}
private class UserExistsQuery extends MappingSqlQuery {
public UserExistsQuery(DataSource ds) {
super(ds, userExistsSql);
declareParameter(new SqlParameter(Types.VARCHAR));
compile();
}
protected Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getString(1);
}
}
private class AllGroupsQuery extends MappingSqlQuery {
public AllGroupsQuery(DataSource ds) {
super(ds, findAllGroupsSql);
compile();
}
protected Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getString(1);
}
}
private class GroupMembersQuery extends MappingSqlQuery {
public GroupMembersQuery(DataSource ds) {
super(ds, findUsersInGroupSql);
declareParameter(new SqlParameter(Types.VARCHAR));
compile();
}
protected Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getString(1);
}
}
private class InsertGroup extends SqlUpdate {
public InsertGroup(DataSource ds) {
super(ds, insertGroupSql);
declareParameter(new SqlParameter(Types.VARCHAR));
compile();
}
}
private class FindGroupIdQuery extends MappingSqlQuery {
public FindGroupIdQuery(DataSource ds) {
super(ds, findGroupIdSql);
declareParameter(new SqlParameter(Types.INTEGER));
compile();
}
protected Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return new Integer(rs.getInt(1));
}
}
private class InsertGroupAuthority extends SqlUpdate {
public InsertGroupAuthority(DataSource ds) {
super(ds, insertGroupAuthoritySql);
declareParameter(new SqlParameter(Types.INTEGER));
declareParameter(new SqlParameter(Types.VARCHAR));
compile();
}
}
protected class DeleteGroup extends SqlUpdate {
public DeleteGroup(DataSource ds) {
super(ds, deleteGroupSql);
declareParameter(new SqlParameter(Types.INTEGER));
compile();
}
}
private class DeleteGroupMembers extends SqlUpdate {
public DeleteGroupMembers(DataSource ds) {
super(ds, deleteGroupMembersSql);
declareParameter(new SqlParameter(Types.INTEGER));
compile();
}
}
protected class DeleteGroupAuthorities extends SqlUpdate {
public DeleteGroupAuthorities(DataSource ds) {
super(ds, deleteGroupAuthoritiesSql);
declareParameter(new SqlParameter(Types.INTEGER));
compile();
}
}
private class RenameGroup extends SqlUpdate {
public RenameGroup(DataSource ds) {
super(ds, renameGroupSql);
declareParameter(new SqlParameter(Types.VARCHAR));
declareParameter(new SqlParameter(Types.VARCHAR));
compile();
}
}
protected class InsertGroupMember extends SqlUpdate {
public InsertGroupMember(DataSource ds) {
super(ds, insertGroupMemberSql);
declareParameter(new SqlParameter(Types.INTEGER));
declareParameter(new SqlParameter(Types.VARCHAR));
compile();
}
}
private class DeleteGroupMember extends SqlUpdate {
public DeleteGroupMember(DataSource ds) {
super(ds, deleteGroupMemberSql);
declareParameter(new SqlParameter(Types.INTEGER));
declareParameter(new SqlParameter(Types.VARCHAR));
compile();
}
}
private class GroupAuthoritiesByGroupNameMapping extends MappingSqlQuery {
protected GroupAuthoritiesByGroupNameMapping(DataSource ds) {
super(ds, groupAuthoritiesSql);
declareParameter(new SqlParameter(Types.VARCHAR));
compile();
}
protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
String roleName = getRolePrefix() + rs.getString(3);
GrantedAuthorityImpl authority = new GrantedAuthorityImpl(roleName);
return authority;
}
}
private class DeleteGroupAuthority extends SqlUpdate {
public DeleteGroupAuthority(DataSource ds) {
super(ds, deleteGroupAuthoritySql);
declareParameter(new SqlParameter(Types.INTEGER));
declareParameter(new SqlParameter(Types.VARCHAR));
compile();
}
}
}
@@ -15,7 +15,7 @@ public class InMemoryXmlApplicationContext extends AbstractXmlApplicationContext
" xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'\n" +
" xsi:schemaLocation='http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd\n" +
"http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd\n" +
"http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.2.xsd'>\n";
"http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.1.xsd'>\n";
private static final String BEANS_CLOSE = "</b:beans>\n";
Resource inMemoryXml;
@@ -1,33 +0,0 @@
package org.springframework.security.util;
/**
* Utilities for working with Strings and text.
*
* @author Luke Taylor
* @version $Id$
*/
public abstract class TextUtils {
public static String escapeEntities(String s) {
StringBuffer sb = new StringBuffer();
for (int i=0; i < s.length(); i++) {
char c = s.charAt(i);
if(c == '<') {
sb.append("&lt;");
} else if (c == '>') {
sb.append("&gt;");
} else if (c == '"') {
sb.append("&#034;");
} else if (c == '\'') {
sb.append("&#039;");
} else {
sb.append(c);
}
}
return sb.toString();
}
}
@@ -18,7 +18,6 @@ package org.springframework.security.util;
import org.springframework.security.intercept.web.FilterInvocation;
import org.springframework.security.ui.savedrequest.SavedRequest;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
@@ -42,6 +41,16 @@ public final class UrlUtils {
* Obtains the full URL the client used to make the request.<p>Note that the server port will not be shown
* if it is the default server port for HTTP or HTTPS (ie 80 and 443 respectively).</p>
*
* @param scheme DOCUMENT ME!
* @param serverName DOCUMENT ME!
* @param serverPort DOCUMENT ME!
* @param contextPath DOCUMENT ME!
* @param requestUrl DOCUMENT ME!
* @param servletPath DOCUMENT ME!
* @param requestURI DOCUMENT ME!
* @param pathInfo DOCUMENT ME!
* @param queryString DOCUMENT ME!
*
* @return the full URL
*/
private static String buildFullRequestUrl(String scheme, String serverName, int serverPort, String contextPath,
@@ -64,6 +73,12 @@ public final class UrlUtils {
/**
* Obtains the web application-specific fragment of the URL.
*
* @param servletPath DOCUMENT ME!
* @param requestURI DOCUMENT ME!
* @param contextPath DOCUMENT ME!
* @param pathInfo DOCUMENT ME!
* @param queryString DOCUMENT ME!
*
* @return the URL, excluding any server name, context path or servlet path
*/
private static String buildRequestUrl(String servletPath, String requestURI, String contextPath, String pathInfo,
@@ -102,8 +117,4 @@ public final class UrlUtils {
return buildRequestUrl(sr.getServletPath(), sr.getRequestURI(), sr.getContextPath(), sr.getPathInfo(),
sr.getQueryString());
}
public static boolean isValidRedirectUrl(String url) {
return !StringUtils.hasText(url) || url.startsWith("/") || url.toLowerCase().startsWith("http");
}
}
@@ -25,9 +25,9 @@ import org.springframework.security.GrantedAuthority;
/**
* Votes if any {@link ConfigAttribute#getAttribute()} starts with a prefix
* indicating that it is a role. The default prefix string is <Code>ROLE_</code>,
* but this may be overridden to any value. It may also be set to empty, which
* but this may be overriden to any value. It may also be set to empty, which
* means that essentially any attribute will be voted on. As described further
* below, the effect of an empty prefix may not be quite desirable.
* below, the effect of an empty prefix may not be quite desireable.
* <p>
* Abstains from voting if no configuration attribute commences with the role
* prefix. Votes to grant access if there is an exact matching
@@ -40,7 +40,7 @@ import org.springframework.security.GrantedAuthority;
* ConfigAttribute. When there are different categories of ConfigAttributes
* used, this will not be optimal since the voter will be voting for attributes
* which do not represent roles. However, this option may be of some use when
* using pre-existing role names without a prefix, and no ability exists to
* using preexisting role names without a prefix, and no ability exists to
* prefix them with a role prefix on reading them in, such as provided for
* example in {@link org.springframework.security.userdetails.jdbc.JdbcDaoImpl}.
* <p>
@@ -62,8 +62,8 @@ public class RoleVoter implements AccessDecisionVoter {
}
/**
* Allows the default role prefix of <code>ROLE_</code> to be overridden.
* May be set to an empty value, although this is usually not desirable.
* Allows the default role prefix of <code>ROLE_</code> to be overriden.
* May be set to an empty value, although this is usually not desireable.
*
* @param rolePrefix the new prefix
*/
@@ -28,15 +28,12 @@ import org.apache.commons.logging.LogFactory;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import java.util.Map.Entry;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
@@ -119,6 +116,9 @@ public class SavedRequestAwareWrapper extends SecurityContextHolderAwareRequestW
//~ Methods ========================================================================================================
/**
* The default behavior of this method is to return getCookies() on the wrapped request object.
*/
public Cookie[] getCookies() {
if (savedRequest == null) {
return super.getCookies();
@@ -129,6 +129,10 @@ public class SavedRequestAwareWrapper extends SecurityContextHolderAwareRequestW
}
}
/**
* The default behavior of this method is to return getDateHeader(String name) on the wrapped request
* object.
*/
public long getDateHeader(String name) {
if (savedRequest == null) {
return super.getDateHeader(name);
@@ -150,6 +154,9 @@ public class SavedRequestAwareWrapper extends SecurityContextHolderAwareRequestW
}
}
/**
* The default behavior of this method is to return getHeader(String name) on the wrapped request object.
*/
public String getHeader(String name) {
if (savedRequest == null) {
return super.getHeader(name);
@@ -167,6 +174,9 @@ public class SavedRequestAwareWrapper extends SecurityContextHolderAwareRequestW
}
}
/**
* The default behavior of this method is to return getHeaderNames() on the wrapped request object.
*/
public Enumeration getHeaderNames() {
if (savedRequest == null) {
return super.getHeaderNames();
@@ -175,6 +185,9 @@ public class SavedRequestAwareWrapper extends SecurityContextHolderAwareRequestW
}
}
/**
* The default behavior of this method is to return getHeaders(String name) on the wrapped request object.
*/
public Enumeration getHeaders(String name) {
if (savedRequest == null) {
return super.getHeaders(name);
@@ -183,6 +196,10 @@ public class SavedRequestAwareWrapper extends SecurityContextHolderAwareRequestW
}
}
/**
* The default behavior of this method is to return getIntHeader(String name) on the wrapped request
* object.
*/
public int getIntHeader(String name) {
if (savedRequest == null) {
return super.getIntHeader(name);
@@ -197,6 +214,9 @@ public class SavedRequestAwareWrapper extends SecurityContextHolderAwareRequestW
}
}
/**
* The default behavior of this method is to return getLocale() on the wrapped request object.
*/
public Locale getLocale() {
if (savedRequest == null) {
return super.getLocale();
@@ -218,6 +238,10 @@ public class SavedRequestAwareWrapper extends SecurityContextHolderAwareRequestW
}
}
/**
* The default behavior of this method is to return getLocales() on the wrapped request object.
*
*/
public Enumeration getLocales() {
if (savedRequest == null) {
return super.getLocales();
@@ -235,6 +259,10 @@ public class SavedRequestAwareWrapper extends SecurityContextHolderAwareRequestW
}
}
/**
* The default behavior of this method is to return getMethod() on the wrapped request object.
*
*/
public String getMethod() {
if (savedRequest == null) {
return super.getMethod();
@@ -244,90 +272,80 @@ public class SavedRequestAwareWrapper extends SecurityContextHolderAwareRequestW
}
/**
* If the parameter is available from the wrapped request then either
* <ol>
* <li>There is no saved request (it a normal request)</li>
* <li>There is a saved request, but the request has been forwarded/included to a URL with parameters, either
* supplementing or overriding the saved request values.</li>
* </ol>
* In both cases the value from the wrapped request should be used.
* <p>
* If the value from the wrapped request is null, an attempt will be made to retrieve the parameter
* from the SavedRequest, if available..
* The default behavior of this method is to return getParameter(String name) on the wrapped request
* object.
*/
public String getParameter(String name) {
String value = super.getParameter(name);
if (value != null || savedRequest == null) {
return value;
/*
if (savedRequest == null) {
return super.getParameter(name);
} else {
String value = null;
String[] values = savedRequest.getParameterValues(name);
if (values == null)
return null;
for (int i = 0; i < values.length; i++) {
value = values[i];
break;
}
return value;
}
*/
//we do not get value from super.getParameter because there is a bug in Jetty servlet-container
String value = null;
String[] values = null;
if (savedRequest == null) {
values = super.getParameterValues(name);
} else {
values = savedRequest.getParameterValues(name);
}
String[] values = savedRequest.getParameterValues(name);
if (values == null)
return null;
for (int i = 0; i < values.length; i++) {
value = values[i];
break;
}
if (values == null) {
return null;
}
return value;
for (int i = 0; i < values.length; i++) {
value = values[i];
break;
}
return value;
}
/**
* The default behavior of this method is to return getParameterMap() on the wrapped request object.
*/
public Map getParameterMap() {
Map parameters = super.getParameterMap();
if (savedRequest == null) {
return parameters;
if (savedRequest == null) {
return super.getParameterMap();
} else {
return savedRequest.getParameterMap();
}
// We have a saved request so merge the values, with the wrapped request taking precedence (see getParameter())
Map newParameters = new HashMap(savedRequest.getParameterMap().size() + parameters.size());
newParameters.putAll(parameters);
Iterator savedParams = savedRequest.getParameterMap().entrySet().iterator();
while (savedParams.hasNext()) {
Map.Entry entry = (Entry) savedParams.next();
String name = (String) entry.getKey();
String[] savedParamValues = (String[]) entry.getValue();
if (newParameters.containsKey(name)) {
// merge values
String[] existingValues = (String[]) newParameters.get(name);
String[] mergedValues = new String[savedParamValues.length + existingValues.length];
System.arraycopy(existingValues, 0, mergedValues, 0, existingValues.length);
System.arraycopy(savedParamValues, 0, mergedValues, existingValues.length, savedParamValues.length);
newParameters.put(name, mergedValues);
} else {
newParameters.put(name, savedParamValues);
}
}
return newParameters;
}
/**
* The default behavior of this method is to return getParameterNames() on the wrapped request object.
*/
public Enumeration getParameterNames() {
return new Enumerator(getParameterMap().keySet());
if (savedRequest == null) {
return super.getParameterNames();
} else {
return new Enumerator(savedRequest.getParameterNames());
}
}
/**
* The default behavior of this method is to return getParameterValues(String name) on the wrapped request
* object.
*/
public String[] getParameterValues(String name) {
String[] savedRequestParams = savedRequest == null ? null : savedRequest.getParameterValues(name);
String[] wrappedRequestParams = super.getParameterValues(name);
if (savedRequestParams == null && wrappedRequestParams == null) {
return null;
}
List combinedParams = new ArrayList();
if (wrappedRequestParams != null) {
combinedParams.addAll(Arrays.asList(wrappedRequestParams));
}
if (savedRequestParams != null) {
combinedParams.addAll(Arrays.asList(savedRequestParams));
}
return (String[]) combinedParams.toArray(new String[combinedParams.size()]);
if (savedRequest == null) {
return super.getParameterValues(name);
} else {
return savedRequest.getParameterValues(name);
}
}
}
@@ -1,3 +1,3 @@
http\://www.springframework.org/schema/security/spring-security-2.0.xsd=org/springframework/security/config/spring-security-2.0.xsd
http\://www.springframework.org/schema/security/spring-security-2.0.1.xsd=org/springframework/security/config/spring-security-2.0.1.xsd
http\://www.springframework.org/schema/security/spring-security-2.0.2.xsd=org/springframework/security/config/spring-security-2.0.2.xsd
@@ -7,7 +7,7 @@ start = http | ldap-server | authentication-provider | ldap-authentication-provi
hash =
## Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm.
attribute hash {"plaintext" | "sha" | "sha-256" | "md5" | "md4" | "{sha}" | "{ssha}"}
attribute hash {"plaintext" | "sha" | "md5" | "md4" | "{sha}" | "{ssha}"}
base64 =
## Whether a string should be base64 encoded
attribute base64 {"true" | "false"}
@@ -34,10 +34,6 @@ cache-ref =
user-service-ref =
## A reference to a user-service (or UserDetailsService bean) Id
attribute user-service-ref {xsd:string}
data-source-ref =
## A reference to a DataSource bean
attribute data-source-ref {xsd:string}
password-encoder =
## element which defines a password encoding strategy. Used by an authentication provider to convert submitted passwords to hashed versions, for example.
@@ -57,7 +53,7 @@ system-wide =
boolean = "true" | "false"
role-prefix =
## A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). Use the value "none" for no prefix in cases where the default is non-empty.
## A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_").
attribute role-prefix {xsd:string}
@@ -255,7 +251,7 @@ intercept-url.attlist &=
attribute method {"GET" | "DELETE" | "HEAD" | "OPTIONS" | "POST" | "PUT" | "TRACE"}?
intercept-url.attlist &=
## The filter list for the path. Currently can be set to "none" to remove a path from having any filters applied. The full filter stack (consisting of all filters created by the namespace configuration, and any added using 'custom-filter'), will be applied to any other paths.
## The filter list for the path. Currently can be set to "none" to remove a path from having any filters applied. The full filter stack (consisting of all defined filters, will be applied to any other paths).
attribute filters {"none"}?
intercept-url.attlist &=
## Used to specify that a URL must be accessed over http or https
@@ -335,44 +331,20 @@ concurrent-session-control =
concurrent-sessions.attlist &=
attribute max-sessions {xsd:positiveInteger}?
concurrent-sessions.attlist &=
## The URL a user will be redirected to if they attempt to use a session which has been "expired" by the concurrent session controller.
attribute expired-url {xsd:string}?
concurrent-sessions.attlist &=
## Specifies that an exception should be raised when a user attempts to login twice. The default behaviour is to expire the original session.
attribute exception-if-maximum-exceeded {boolean}?
concurrent-sessions.attlist &=
## Allows you to define an alias for the SessionRegistry bean in order to access it in your own configuration
attribute session-registry-alias {xsd:string}?
concurrent-sessions.attlist &=
## A reference to an external SessionRegistry implementation which will be used in place of the standard one.
attribute session-registry-ref {xsd:string}?
remember-me =
## Sets up remember-me authentication. If used with the "key" attribute (or no attributes) the cookie-only implementation will be used. Specifying "token-repository-ref" or "remember-me-data-source-ref" will use the more secure, persisten token approach.
element remember-me {remember-me.attlist}
remember-me.attlist &=
## The "key" used to identify cookies from a specific token-based remember-me application. You should set this to a unique value for your application.
attribute key {xsd:string}?
remember-me.attlist &=
(token-repository-ref | remember-me-data-source-ref | remember-me-services-ref)
(attribute key {xsd:string} | (attribute token-repository-ref {xsd:string} | attribute data-source-ref {xsd:string}))
remember-me.attlist &=
user-service-ref?
remember-me.attlist &=
## The period (in seconds) for which the remember-me cookie should be valid.
attribute token-validity-seconds {xsd:positiveInteger}?
token-repository-ref =
## Reference to a PersistentTokenRepository bean for use with the persistent token remember-me implementation.
attribute token-repository-ref {xsd:string}
remember-me-services-ref =
## Allows a custom implementation of RememberMeServices to be used. Note that this implementation should return RememberMeAuthenticationToken instances with the same "key" value as specified in the remember-me element. Alternatively it should register its own AuthenticationProvider.
attribute services-ref {xsd:string}?
remember-me-data-source-ref =
## DataSource bean for the database that contains the token
data-source-ref
anonymous =
## Adds support for automatically granting all anonymous web requests a particular principal identity and a corresponding granted authority.
@@ -412,15 +384,11 @@ x509.attlist &=
user-service-ref?
authentication-manager =
## If you are using namespace configuration with Spring Security, an AuthenticationManager will automatically be registered. This element allows you to define an alias to allow you to reference the authentication-manager in your own beans.
## If you are using namespace configuration with Spring Security, an AuthenticationManager will automatically be registered. This element simple allows you to define an alias to allow you to reference the authentication-manager in your own beans.
element authentication-manager {authman.attlist}
authman.attlist &=
## The alias you wish to use for the AuthenticationManager bean
attribute alias {xsd:ID}
authman.attlist &=
## Allows the session controller to be set on the internal AuthenticationManager. This should not be used with the <concurrent-session-control /> element
attribute session-controller-ref {xsd:string}?
attribute alias {xsd:ID}
authentication-provider =
## Indicates that the contained user-service should be used as an authentication source.
@@ -10,7 +10,7 @@
<xsl:output method="xml" indent="yes"/>
<xsl:variable name="elts-to-inline">
<xsl:text>,anonymous,concurrent-session-control,filter-chain,form-login,http-basic,intercept-url,logout,password-encoder,port-mappings,port-mapper,password-compare,protect,protect-pointcut,remember-me,salt-source,x509,</xsl:text>
<xsl:text>,intercept-url,form-login,x509,password-encoder,http-basic,logout,concurrent-session-control,remember-me,anonymous,port-mappings,password-compare,salt-source,filter-chain,protect-pointcut,</xsl:text>
</xsl:variable>
<xsl:template match="xs:element">
@@ -65,7 +65,7 @@ public class SimpleRoles2GrantedAuthoritiesMapperTests extends TestCase {
String[] expectedGas = { "ROLE_Role1", "ROLE_Role2", "ROLE_ROLE_Role3" };
SimpleAttributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
mapper.setAddPrefixIfAlreadyExisting(true);
mapper.setAttributePrefix("ROLE_");
mapper.seAttributePrefix("ROLE_");
testGetGrantedAuthorities(mapper, roles, expectedGas);
}
@@ -74,7 +74,7 @@ public class SimpleRoles2GrantedAuthoritiesMapperTests extends TestCase {
String[] expectedGas = { "ROLE_Role1", "ROLE_Role2", "ROLE_Role3" };
SimpleAttributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
mapper.setAddPrefixIfAlreadyExisting(false);
mapper.setAttributePrefix("ROLE_");
mapper.seAttributePrefix("ROLE_");
testGetGrantedAuthorities(mapper, roles, expectedGas);
}
@@ -83,7 +83,7 @@ public class SimpleRoles2GrantedAuthoritiesMapperTests extends TestCase {
String[] expectedGas = { "ROLE_Role1", "ROLE_Role2", "ROLE_role_Role3" };
SimpleAttributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
mapper.setAddPrefixIfAlreadyExisting(false);
mapper.setAttributePrefix("ROLE_");
mapper.seAttributePrefix("ROLE_");
testGetGrantedAuthorities(mapper, roles, expectedGas);
}
@@ -93,7 +93,7 @@ public class SimpleRoles2GrantedAuthoritiesMapperTests extends TestCase {
SimpleAttributes2GrantedAuthoritiesMapper mapper = getDefaultMapper();
mapper.setAddPrefixIfAlreadyExisting(false);
mapper.setConvertAttributeToUpperCase(true);
mapper.setAttributePrefix("ROLE_");
mapper.seAttributePrefix("ROLE_");
testGetGrantedAuthorities(mapper, roles, expectedGas);
}
@@ -111,7 +111,7 @@ public class SimpleRoles2GrantedAuthoritiesMapperTests extends TestCase {
private SimpleAttributes2GrantedAuthoritiesMapper getDefaultMapper() {
SimpleAttributes2GrantedAuthoritiesMapper mapper = new SimpleAttributes2GrantedAuthoritiesMapper();
mapper.setAttributePrefix("");
mapper.seAttributePrefix("");
mapper.setConvertAttributeToLowerCase(false);
mapper.setConvertAttributeToUpperCase(false);
mapper.setAddPrefixIfAlreadyExisting(false);
@@ -1,12 +1,8 @@
package org.springframework.security.config;
import static org.junit.Assert.*;
import org.springframework.security.providers.ProviderManager;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.providers.AuthenticationProvider;
import org.springframework.security.providers.encoding.ShaPasswordEncoder;
import org.springframework.security.util.FieldUtils;
import org.springframework.security.util.InMemoryXmlApplicationContext;
import org.springframework.context.support.AbstractXmlApplicationContext;
@@ -75,19 +71,6 @@ public class AuthenticationProviderBeanDefinitionParserTests {
getProvider().authenticate(bob);
}
@Test
public void providerWithSha256PasswordEncoderIsSupported() throws Exception {
setContext(" <authentication-provider>" +
" <password-encoder hash='sha-256'/>" +
" <user-service>" +
" <user name='bob' password='notused' authorities='ROLE_A' />" +
" </user-service>" +
" </authentication-provider>");
ShaPasswordEncoder encoder = (ShaPasswordEncoder) FieldUtils.getFieldValue(getProvider(), "passwordEncoder");
assertEquals("SHA-256", encoder.getAlgorithm());
}
@Test
public void passwordIsBase64EncodedWhenBase64IsEnabled() throws Exception {
setContext(" <authentication-provider>" +
@@ -98,7 +81,7 @@ public class AuthenticationProviderBeanDefinitionParserTests {
" </authentication-provider>");
getProvider().authenticate(bob);
}
}
@Test
public void externalUserServiceAndPasswordEncoderWork() throws Exception {
@@ -21,7 +21,7 @@ public class CustomAfterInvocationProviderBeanDefinitionDecoratorTests {
}
@Test
public void customAfterInvocationProviderIsAddedToInterceptor() {
public void customAuthenticationProviderIsAddedToInterceptor() {
setContext(
"<global-method-security />" +
"<b:bean id='aip' class='org.springframework.security.config.MockAfterInvocationProvider'>" +
@@ -1,44 +1,21 @@
package org.springframework.security.config;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.security.providers.ProviderManager;
import org.springframework.security.util.InMemoryXmlApplicationContext;
public class CustomAuthenticationProviderBeanDefinitionDecoratorTests {
@Test
public void decoratedProviderParsesSuccessfully() {
public void decoratorParsesSuccessfully() {
InMemoryXmlApplicationContext ctx = new InMemoryXmlApplicationContext(
"<b:bean class='org.springframework.security.providers.dao.DaoAuthenticationProvider'>" +
" <custom-authentication-provider />" +
" <b:property name='userDetailsService' ref='us'/>" +
"</b:bean>" +
"<user-service id='us'>" +
" <user name='bob' password='bobspassword' authorities='ROLE_A,ROLE_B' />" +
"</user-service>"
"<b:bean id='someBean' class='org.springframework.security.config.TestBusinessBeanImpl'>" +
" <intercept-methods>" +
" <protect method='org.springframework.security.config.TestBusinessBean.*' access='ROLE_A' />" +
" </intercept-methods>" +
"</b:bean>" + HttpSecurityBeanDefinitionParserTests.AUTH_PROVIDER_XML
);
ProviderManager authMgr = (ProviderManager) ctx.getBean(BeanIds.AUTHENTICATION_MANAGER);
assertEquals(1, authMgr.getProviders().size());
}
@Test
public void decoratedBeanAndRegisteredProviderAreTheSameObject() {
InMemoryXmlApplicationContext ctx = new InMemoryXmlApplicationContext(
"<b:bean id='myProvider' class='org.springframework.security.providers.dao.DaoAuthenticationProvider'>" +
" <custom-authentication-provider />" +
" <b:property name='userDetailsService' ref='us'/>" +
"</b:bean>" +
"<user-service id='us'>" +
" <user name='bob' password='bobspassword' authorities='ROLE_A,ROLE_B' />" +
"</user-service>"
);
ProviderManager authMgr = (ProviderManager) ctx.getBean(BeanIds.AUTHENTICATION_MANAGER);
assertEquals(1, authMgr.getProviders().size());
assertSame(ctx.getBean("myProvider"), authMgr.getProviders().get(0));
ctx.getBean("someBean");
}
}
@@ -9,7 +9,6 @@ import java.util.List;
import org.junit.After;
import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.context.support.AbstractXmlApplicationContext;
import org.springframework.mock.web.MockHttpServletRequest;
@@ -57,7 +56,7 @@ public class HttpSecurityBeanDefinitionParserTests {
private AbstractXmlApplicationContext appContext;
static final String AUTH_PROVIDER_XML =
" <authentication-provider>" +
" <user-service id='us'>" +
" <user-service>" +
" <user name='bob' password='bobspassword' authorities='ROLE_A,ROLE_B' />" +
" <user name='bill' password='billspassword' authorities='ROLE_A,ROLE_B,AUTH_OTHER' />" +
" </user-service>" +
@@ -83,7 +82,6 @@ public class HttpSecurityBeanDefinitionParserTests {
List filterList = getFilters("/anyurl");
checkAutoConfigFilters(filterList);
assertEquals(true, FieldUtils.getFieldValue(filterList.get(10), "objectDefinitionSource.stripQueryStringFromUrls"));
}
@Test(expected=BeanDefinitionParsingException.class)
@@ -96,7 +94,8 @@ public class HttpSecurityBeanDefinitionParserTests {
Iterator filters = filterList.iterator();
assertTrue(filters.next() instanceof HttpSessionContextIntegrationFilter);
assertTrue(filters.next() instanceof HttpSessionContextIntegrationFilter);
assertTrue(filters.next() instanceof SessionFixationProtectionFilter);
assertTrue(filters.next() instanceof LogoutFilter);
Object authProcFilter = filters.next();
assertTrue(authProcFilter instanceof AuthenticationProcessingFilter);
@@ -111,7 +110,6 @@ public class HttpSecurityBeanDefinitionParserTests {
assertTrue(filters.next() instanceof RememberMeProcessingFilter);
assertTrue(filters.next() instanceof AnonymousProcessingFilter);
assertTrue(filters.next() instanceof ExceptionTranslationFilter);
assertTrue(filters.next() instanceof SessionFixationProtectionFilter);
Object fsiObj = filters.next();
assertTrue(fsiObj instanceof FilterSecurityInterceptor);
FilterSecurityInterceptor fsi = (FilterSecurityInterceptor) fsiObj;
@@ -138,9 +136,7 @@ public class HttpSecurityBeanDefinitionParserTests {
" </http>" + AUTH_PROVIDER_XML);
assertEquals(0, getFilters("/imlowercase").size());
// This will be matched by the default pattern ".*"
List allFilters = getFilters("/ImCaughtByTheUniversalMatchPattern");
checkAutoConfigFilters(allFilters);
assertEquals(false, FieldUtils.getFieldValue(allFilters.get(10), "objectDefinitionSource.stripQueryStringFromUrls"));
checkAutoConfigFilters(getFilters("/ImCaughtByTheUniversalMatchPattern"));
}
@Test
@@ -173,12 +169,12 @@ public class HttpSecurityBeanDefinitionParserTests {
" <form-login default-target-url='/default' always-use-default-target='true' />" +
"</http>" + AUTH_PROVIDER_XML);
// These will be matched by the default pattern "/**"
AuthenticationProcessingFilter filter = (AuthenticationProcessingFilter) getFilters("/anything").get(1);
AuthenticationProcessingFilter filter = (AuthenticationProcessingFilter) getFilters("/anything").get(2);
assertEquals("/default", filter.getDefaultTargetUrl());
assertEquals(Boolean.TRUE, FieldUtils.getFieldValue(filter, "alwaysUseDefaultTargetUrl"));
}
@Test(expected=BeanCreationException.class)
@Test(expected=BeanDefinitionParsingException.class)
public void invalidLoginPageIsDetected() throws Exception {
setContext(
"<http>" +
@@ -186,7 +182,7 @@ public class HttpSecurityBeanDefinitionParserTests {
"</http>" + AUTH_PROVIDER_XML);
}
@Test(expected=BeanCreationException.class)
@Test(expected=BeanDefinitionParsingException.class)
public void invalidDefaultTargetUrlIsDetected() throws Exception {
setContext(
"<http>" +
@@ -194,7 +190,7 @@ public class HttpSecurityBeanDefinitionParserTests {
"</http>" + AUTH_PROVIDER_XML);
}
@Test(expected=BeanCreationException.class)
@Test(expected=BeanDefinitionParsingException.class)
public void invalidLogoutUrlIsDetected() throws Exception {
setContext(
"<http>" +
@@ -203,7 +199,7 @@ public class HttpSecurityBeanDefinitionParserTests {
"</http>" + AUTH_PROVIDER_XML);
}
@Test(expected=BeanCreationException.class)
@Test(expected=BeanDefinitionParsingException.class)
public void invalidLogoutSuccessUrlIsDetected() throws Exception {
setContext(
"<http>" +
@@ -264,12 +260,12 @@ public class HttpSecurityBeanDefinitionParserTests {
setContext("<http access-denied-page='/access-denied'><http-basic /></http>" + AUTH_PROVIDER_XML);
List filters = getFilters("/someurl");
ExceptionTranslationFilter etf = (ExceptionTranslationFilter) filters.get(filters.size() - 3);
ExceptionTranslationFilter etf = (ExceptionTranslationFilter) filters.get(filters.size() - 2);
assertEquals("/access-denied", FieldUtils.getFieldValue(etf, "accessDeniedHandler.errorPage"));
}
@Test(expected=BeanDefinitionStoreException.class)
@Test(expected=BeanDefinitionParsingException.class)
public void invalidAccessDeniedUrlIsDetected() throws Exception {
setContext("<http auto-config='true' access-denied-page='noLeadingSlash'/>" + AUTH_PROVIDER_XML);
}
@@ -324,7 +320,7 @@ public class HttpSecurityBeanDefinitionParserTests {
assertEquals(14, filters.size());
assertTrue(filters.get(0) instanceof MockFilter);
assertTrue(filters.get(1) instanceof SecurityContextHolderAwareRequestFilter);
assertTrue(filters.get(4) instanceof SecurityContextHolderAwareRequestFilter);
assertTrue(filters.get(5) instanceof SecurityContextHolderAwareRequestFilter);
}
@Test(expected=BeanCreationException.class)
@@ -340,50 +336,23 @@ public class HttpSecurityBeanDefinitionParserTests {
public void rememberMeServiceWorksWithTokenRepoRef() {
setContext(
"<http auto-config='true'>" +
" <remember-me token-repository-ref='tokenRepo'/>" +
" <remember-me key='doesntmatter' token-repository-ref='tokenRepo'/>" +
"</http>" +
"<b:bean id='tokenRepo' " +
"class='org.springframework.security.ui.rememberme.InMemoryTokenRepositoryImpl'/> " + AUTH_PROVIDER_XML);
Object rememberMeServices = appContext.getBean(BeanIds.REMEMBER_ME_SERVICES);
assertTrue(rememberMeServices instanceof PersistentTokenBasedRememberMeServices);
}
@Test
public void rememberMeServiceWorksWithExternalServicesImpl() throws Exception {
setContext(
"<http auto-config='true'>" +
" <remember-me key='ourkey' services-ref='rms'/>" +
"</http>" +
"<b:bean id='rms' class='org.springframework.security.ui.rememberme.TokenBasedRememberMeServices'> " +
" <b:property name='userDetailsService' ref='us'/>" +
" <b:property name='key' value='ourkey'/>" +
" <b:property name='tokenValiditySeconds' value='5000'/>" +
"</b:bean>" +
AUTH_PROVIDER_XML);
assertEquals(5000, FieldUtils.getFieldValue(appContext.getBean(BeanIds.REMEMBER_ME_SERVICES),
"tokenValiditySeconds"));
}
@Test
public void rememberMeTokenValidityIsParsedCorrectly() throws Exception {
setContext(
"<http auto-config='true'>" +
" <remember-me key='ourkey' token-validity-seconds='10000' />" +
"</http>" + AUTH_PROVIDER_XML);
assertEquals(10000, FieldUtils.getFieldValue(appContext.getBean(BeanIds.REMEMBER_ME_SERVICES),
"tokenValiditySeconds"));
}
@Test
public void rememberMeServiceConfigurationParsesWithCustomUserService() {
setContext(
"<http auto-config='true'>" +
" <remember-me key='somekey' user-service-ref='userService'/>" +
" <remember-me key='doesntmatter' user-service-ref='userService'/>" +
"</http>" +
"<b:bean id='userService' class='org.springframework.security.userdetails.MockUserDetailsService'/> " +
AUTH_PROVIDER_XML);
"<b:bean id='userService' " +
"class='org.springframework.security.userdetails.MockUserDetailsService'/> " + AUTH_PROVIDER_XML);
// AbstractRememberMeServices rememberMeServices = (AbstractRememberMeServices) appContext.getBean(BeanIds.REMEMBER_ME_SERVICES);
}
@@ -395,7 +364,7 @@ public class HttpSecurityBeanDefinitionParserTests {
"</http>" + AUTH_PROVIDER_XML);
List filters = getFilters("/someurl");
assertTrue(filters.get(2) instanceof X509PreAuthenticatedProcessingFilter);
assertTrue(filters.get(3) instanceof X509PreAuthenticatedProcessingFilter);
}
@Test
@@ -403,7 +372,7 @@ public class HttpSecurityBeanDefinitionParserTests {
setContext(
"<http auto-config='true'>" +
" <concurrent-session-control session-registry-alias='seshRegistry' expired-url='/expired'/>" +
"</http>" + AUTH_PROVIDER_XML);
"</http>" + AUTH_PROVIDER_XML);
List filters = getFilters("/someurl");
assertTrue(filters.get(0) instanceof ConcurrentSessionFilter);
@@ -411,55 +380,6 @@ public class HttpSecurityBeanDefinitionParserTests {
assertNotNull(appContext.getBean(BeanIds.CONCURRENT_SESSION_CONTROLLER));
}
@Test
public void externalSessionRegistryBeanIsConfiguredCorrectly() throws Exception {
setContext(
"<http auto-config='true'>" +
" <concurrent-session-control session-registry-ref='seshRegistry' />" +
"</http>" +
"<b:bean id='seshRegistry' class='org.springframework.security.concurrent.SessionRegistryImpl'/>" +
AUTH_PROVIDER_XML);
Object sessionRegistry = appContext.getBean("seshRegistry");
Object sessionRegistryFromFilter = FieldUtils.getFieldValue(
appContext.getBean(BeanIds.CONCURRENT_SESSION_FILTER),"sessionRegistry");
Object sessionRegistryFromController = FieldUtils.getFieldValue(
appContext.getBean(BeanIds.CONCURRENT_SESSION_CONTROLLER),"sessionRegistry");
Object sessionRegistryFromFixationFilter = FieldUtils.getFieldValue(
appContext.getBean(BeanIds.SESSION_FIXATION_PROTECTION_FILTER),"sessionRegistry");
assertSame(sessionRegistry, sessionRegistryFromFilter);
assertSame(sessionRegistry, sessionRegistryFromController);
assertSame(sessionRegistry, sessionRegistryFromFixationFilter);
}
@Test(expected=BeanDefinitionParsingException.class)
public void concurrentSessionSupportCantBeUsedWithIndependentControllerBean() throws Exception {
setContext(
"<authentication-manager alias='authManager' session-controller-ref='sc'/>" +
"<http auto-config='true'>" +
" <concurrent-session-control session-registry-alias='seshRegistry' expired-url='/expired'/>" +
"</http>" +
"<b:bean id='sc' class='org.springframework.security.concurrent.ConcurrentSessionControllerImpl'>" +
" <b:property name='sessionRegistry'>" +
" <b:bean class='org.springframework.security.concurrent.SessionRegistryImpl'/>" +
" </b:property>" +
"</b:bean>" + AUTH_PROVIDER_XML);
}
@Test(expected=BeanDefinitionParsingException.class)
public void concurrentSessionSupportCantBeUsedWithIndependentControllerBean2() throws Exception {
setContext(
"<http auto-config='true'>" +
" <concurrent-session-control session-registry-alias='seshRegistry' expired-url='/expired'/>" +
"</http>" +
"<b:bean id='sc' class='org.springframework.security.concurrent.ConcurrentSessionControllerImpl'>" +
" <b:property name='sessionRegistry'>" +
" <b:bean class='org.springframework.security.concurrent.SessionRegistryImpl'/>" +
" </b:property>" +
"</b:bean>" +
"<authentication-manager alias='authManager' session-controller-ref='sc'/>" + AUTH_PROVIDER_XML);
}
@Test(expected=ConcurrentLoginException.class)
public void concurrentSessionMaxSessionsIsCorrectlyConfigured() throws Exception {
setContext(
@@ -498,7 +418,7 @@ public class HttpSecurityBeanDefinitionParserTests {
"<b:bean id='entryPoint' class='org.springframework.security.MockAuthenticationEntryPoint'>" +
" <b:constructor-arg value='/customlogin'/>" +
"</b:bean>" + AUTH_PROVIDER_XML);
ExceptionTranslationFilter etf = (ExceptionTranslationFilter) getFilters("/someurl").get(8);
ExceptionTranslationFilter etf = (ExceptionTranslationFilter) getFilters("/someurl").get(9);
assertTrue("ExceptionTranslationFilter should be configured with custom entry point",
etf.getAuthenticationEntryPoint() instanceof MockAuthenticationEntryPoint);
}
@@ -585,7 +505,8 @@ public class HttpSecurityBeanDefinitionParserTests {
" <form-login login-page='/login.jsp' default-target-url='/messageList.html'/>" +
" </http>" + AUTH_PROVIDER_XML);
}
private void setContext(String context) {
appContext = new InMemoryXmlApplicationContext(context);
}
@@ -38,8 +38,8 @@ public class LdapProviderBeanDefinitionParserTests {
Authentication auth = provider.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword"));
LdapUserDetailsImpl ben = (LdapUserDetailsImpl) auth.getPrincipal();
assertEquals(3, ben.getAuthorities().length);
}
assertEquals(2, ben.getAuthorities().length);
}
@Test(expected = SecurityConfigurationException.class)
public void missingServerEltCausesConfigException() {
@@ -42,7 +42,7 @@ public class LdapUserServiceBeanDefinitionParserTests {
UserDetails ben = uds.loadUserByUsername("ben");
Set authorities = AuthorityUtils.authorityArrayToSet(ben.getAuthorities());
assertEquals(3, authorities.size());
assertEquals(2, authorities.size());
assertTrue(authorities.contains("ROLE_DEVELOPERS"));
}
@@ -88,7 +88,7 @@ public class LdapUserServiceBeanDefinitionParserTests {
UserDetails ben = uds.loadUserByUsername("ben");
Set authorities = AuthorityUtils.authorityArrayToSet(ben.getAuthorities());
assertEquals(3, authorities.size());
assertEquals(2, authorities.size());
assertTrue(authorities.contains(new GrantedAuthorityImpl("ROLE_DEVELOPER")));
}
@@ -17,19 +17,13 @@ package org.springframework.security.ldap;
import org.springframework.ldap.UncategorizedLdapException;
import org.springframework.ldap.core.ContextExecutor;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapEncoder;
import org.junit.Test;
import static org.junit.Assert.*;
import java.util.Set;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.naming.ldap.LdapName;
/**
* @author Luke Taylor
@@ -49,22 +43,22 @@ public class SpringSecurityLdapTemplateTests extends AbstractLdapIntegrationTest
}
@Test
public void compareOfCorrectValueSucceeds() {
public void testCompareOfCorrectValueSucceeds() {
assertTrue(template.compare("uid=bob,ou=people", "uid", "bob"));
}
@Test
public void compareOfCorrectByteValueSucceeds() {
public void testCompareOfCorrectByteValueSucceeds() {
assertTrue(template.compare("uid=bob,ou=people", "userPassword", LdapUtils.getUtf8Bytes("bobspassword")));
}
@Test
public void compareOfWrongByteValueFails() {
public void testCompareOfWrongByteValueFails() {
assertFalse(template.compare("uid=bob,ou=people", "userPassword", LdapUtils.getUtf8Bytes("wrongvalue")));
}
@Test
public void compareOfWrongValueFails() {
public void testCompareOfWrongValueFails() {
assertFalse(template.compare("uid=bob,ou=people", "uid", "wrongvalue"));
}
@@ -79,7 +73,7 @@ public class SpringSecurityLdapTemplateTests extends AbstractLdapIntegrationTest
// }
@Test
public void namingExceptionIsTranslatedCorrectly() {
public void testNamingExceptionIsTranslatedCorrectly() {
try {
template.executeReadOnly(new ContextExecutor() {
public Object executeWithContext(DirContext dirContext) throws NamingException {
@@ -91,7 +85,7 @@ public class SpringSecurityLdapTemplateTests extends AbstractLdapIntegrationTest
}
@Test
public void roleSearchReturnsCorrectNumberOfRoles() {
public void testRoleSearchReturnsCorrectNumberOfRoles() {
String param = "uid=ben,ou=people,dc=springframework,dc=org";
Set values = template.searchForSingleAttributeValues("ou=groups", "(member={0})", new String[] {param}, "ou");
@@ -110,44 +104,4 @@ public class SpringSecurityLdapTemplateTests extends AbstractLdapIntegrationTest
assertEquals(0, values.size());
}
@Test
public void roleSearchWithEscapedCharacterSucceeds() throws Exception {
String param = "cn=mouse\\, jerry,ou=people,dc=springframework,dc=org";
Set values = template.searchForSingleAttributeValues("ou=groups", "(member={0})", new String[] {param}, "cn");
assertEquals(1, values.size());
}
@Test
public void nonSpringLdapSearchCodeTestMethod() throws Exception {
java.util.Hashtable env = new java.util.Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:53389");
env.put(Context.SECURITY_PRINCIPAL, "");
env.put(Context.SECURITY_CREDENTIALS, "");
DirContext ctx = new javax.naming.directory.InitialDirContext(env);
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
controls.setReturningObjFlag(true);
controls.setReturningAttributes(null);
String param = "cn=mouse\\, jerry,ou=people,dc=springframework,dc=org";
javax.naming.NamingEnumeration results =
ctx.search("ou=groups,dc=springframework,dc=org",
"(member={0})", new String[] {param},
controls);
assertTrue("Expected a result", results.hasMore());
}
@Test
public void searchForSingleEntryWithEscapedCharsInDnSucceeds() {
String param = "mouse, jerry";
DirContextOperations jerry = template.searchForSingleEntry("ou=people", "(cn={0})", new String[] {param});
}
}
@@ -131,18 +131,4 @@ public class DefaultLdapAuthoritiesPopulatorTests extends AbstractLdapIntegratio
assertTrue(roles.contains("ROLE_SUBMANAGER"));
}
@Test
public void testUserDnWithEscapedCharacterParameterReturnsExpectedRoles() {
populator.setGroupRoleAttribute("ou");
populator.setConvertToUpperCase(true);
populator.setGroupSearchFilter("(member={0})");
DirContextAdapter ctx = new DirContextAdapter(new DistinguishedName("cn=mouse\\, jerry,ou=people,dc=springframework,dc=org"));
GrantedAuthority[] authorities = populator.getGrantedAuthorities(ctx, "notused");
assertEquals("Should have 1 role", 1, authorities.length);
assertEquals("ROLE_MANAGER", authorities[0].getAuthority());
}
}
@@ -60,7 +60,7 @@ public class FilterBasedLdapUserSearchTests extends AbstractLdapIntegrationTests
@Test
public void extraFilterPartToExcludeBob() throws Exception {
FilterBasedLdapUserSearch locator = new FilterBasedLdapUserSearch("ou=people",
"(&(cn=*)(!(|(uid={0})(uid=rod)(uid=jerry))))", dirCtxFactory);
"(&(cn=*)(!(|(uid={0})(uid=rod))))", dirCtxFactory);
// Search for bob, get back ben...
DirContextOperations ben = locator.searchForUser("bob");
@@ -2,14 +2,19 @@ package org.springframework.security.ui;
import static org.junit.Assert.*;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.junit.After;
import org.junit.Test;
import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.context.HttpSessionContextIntegrationFilter;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.TestingAuthenticationToken;
@@ -29,7 +34,6 @@ public class SessionFixationProtectionFilterTests {
public void newSessionShouldNotBeCreatedIfNoSessionExists() throws Exception {
SessionFixationProtectionFilter filter = new SessionFixationProtectionFilter();
HttpServletRequest request = new MockHttpServletRequest();
authenticateUser();
filter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain());
@@ -37,15 +41,14 @@ public class SessionFixationProtectionFilterTests {
}
@Test
public void newSessionBeCreatedIfAuthenticatedOccurredDuringRequest() throws Exception {
public void newSessionShouldNotBeCreatedIfUserIsAuthenticated() throws Exception {
SessionFixationProtectionFilter filter = new SessionFixationProtectionFilter();
HttpServletRequest request = new MockHttpServletRequest();
String sessionId = request.getSession().getId();
authenticateUser();
filter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain());
assertFalse(sessionId.equals(request.getSession().getId()));
assertEquals(sessionId, request.getSession().getId());
}
@Test
@@ -65,15 +68,91 @@ public class SessionFixationProtectionFilterTests {
HttpServletRequest request = new MockHttpServletRequest();
String sessionId = request.getSession().getId();
authenticateUser();
request.getSession().setAttribute(HttpSessionContextIntegrationFilter.SPRING_SECURITY_CONTEXT_KEY,
SecurityContextHolder.getContext());
filter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain());
assertEquals(sessionId, request.getSession().getId());
}
@Test
public void newSessionShouldBeCreatedIfAuthenticationOccursDuringRequest() throws Exception {
SessionFixationProtectionFilter filter = new SessionFixationProtectionFilter();
HttpServletRequest request = new MockHttpServletRequest();
String sessionId = request.getSession().getId();
filter.doFilter(request, new MockHttpServletResponse(), new UserAuthenticatingFilterChain());
assertFalse(sessionId.equals(request.getSession().getId()));
}
@Test
public void newSessionShouldBeCreatedIfAuthenticationAndRedirectOccursDuringRequest() throws Exception {
SessionFixationProtectionFilter filter = new SessionFixationProtectionFilter();
HttpServletRequest request = new MockHttpServletRequest();
String sessionId = request.getSession().getId();
AuthenticateAndRedirectFilterChain chain = new AuthenticateAndRedirectFilterChain();
filter.doFilter(request, new MockHttpServletResponse(), chain);
assertTrue(chain.getResponse() instanceof
SessionFixationProtectionFilter.SessionFixationProtectionResponseWrapper);
assertTrue("New session should have been created by session wrapper",
((SessionFixationProtectionFilter.SessionFixationProtectionResponseWrapper)chain.getResponse()).isNewSessionStarted());
assertFalse(sessionId.equals(request.getSession().getId()));
}
@Test
public void wrapperSendErrorCreatesNewSession() throws Exception {
authenticateUser();
SessionFixationProtectionFilter filter = new SessionFixationProtectionFilter();
HttpServletRequest request = new MockHttpServletRequest();
String sessionId = request.getSession().getId();
SessionFixationProtectionFilter.SessionFixationProtectionResponseWrapper wrapper =
filter.new SessionFixationProtectionResponseWrapper(new MockHttpServletResponse(), request);
wrapper.sendError(HttpServletResponse.SC_FORBIDDEN);
assertFalse(sessionId.equals(request.getSession().getId()));
// Message version
request = new MockHttpServletRequest();
sessionId = request.getSession().getId();
wrapper = filter.new SessionFixationProtectionResponseWrapper(new MockHttpServletResponse(), request);
wrapper.sendError(HttpServletResponse.SC_FORBIDDEN, "Hi. I'm your friendly forbidden message.");
assertFalse(sessionId.equals(request.getSession().getId()));
}
@Test
public void wrapperRedirectCreatesNewSession() throws Exception {
authenticateUser();
SessionFixationProtectionFilter filter = new SessionFixationProtectionFilter();
HttpServletRequest request = new MockHttpServletRequest();
String sessionId = request.getSession().getId();
SessionFixationProtectionFilter.SessionFixationProtectionResponseWrapper wrapper =
filter.new SessionFixationProtectionResponseWrapper(new MockHttpServletResponse(), request);
wrapper.sendRedirect("/somelocation");
assertFalse(sessionId.equals(request.getSession().getId()));
}
private void authenticateUser() {
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "pass", null));
}
private class UserAuthenticatingFilterChain implements FilterChain {
public void doFilter(ServletRequest request, ServletResponse response) throws IOException {
authenticateUser();
}
}
private class AuthenticateAndRedirectFilterChain extends UserAuthenticatingFilterChain{
HttpServletResponse response;
public void doFilter(ServletRequest request, ServletResponse response) throws IOException {
super.doFilter(request, response);
this.response = (HttpServletResponse)response;
this.response.sendRedirect("/someUrl");
}
public HttpServletResponse getResponse() {
return response;
}
}
}
@@ -130,7 +130,7 @@ public class J2eeBasedPreAuthenticatedWebAuthenticationDetailsSourceTests extend
result.setAddPrefixIfAlreadyExisting(false);
result.setConvertAttributeToLowerCase(false);
result.setConvertAttributeToUpperCase(false);
result.setAttributePrefix("");
result.seAttributePrefix("");
return result;
}
@@ -342,8 +342,6 @@ public class TokenBasedRememberMeServicesTests extends TestCase {
public void testLoginSuccessNormalWithNonUserDetailsBasedPrincipal() {
TokenBasedRememberMeServices services = new TokenBasedRememberMeServices();
// SEC-822
services.setTokenValiditySeconds(5000000);
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("d");
request.addParameter(TokenBasedRememberMeServices.DEFAULT_PARAMETER, "true");
@@ -1,14 +0,0 @@
package org.springframework.security.util;
import static org.junit.Assert.*;
import org.junit.Test;
public class TextUtilsTests {
@Test
public void charactersAreEscapedCorrectly() {
assertEquals("a&lt;script&gt;&#034;&#039;", TextUtils.escapeEntities("a<script>\"'"));
}
}
@@ -1,66 +0,0 @@
package org.springframework.security.wrapper;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.security.ui.AbstractProcessingFilter;
import org.springframework.security.ui.savedrequest.SavedRequest;
import org.springframework.security.util.PortResolverImpl;
public class SavedRequestAwareWrapperTests {
@Test
/* SEC-830 */
public void wrappedRequestParameterTakesPrecedenceOverSavedRequest() {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setParameter("action", "foo");
SavedRequest savedRequest = new SavedRequest(request, new PortResolverImpl());
MockHttpServletRequest request2 = new MockHttpServletRequest();
request2.getSession().setAttribute(AbstractProcessingFilter.SPRING_SECURITY_SAVED_REQUEST_KEY, savedRequest);
SavedRequestAwareWrapper wrapper = new SavedRequestAwareWrapper(request2, new PortResolverImpl(), "ROLE_");
assertEquals("foo", wrapper.getParameter("action"));
request2.setParameter("action", "bar");
assertEquals("bar", wrapper.getParameter("action"));
}
@Test
public void savedRequestHeadersTakePrecedence() {
MockHttpServletRequest request = new MockHttpServletRequest();
request.addHeader("Authorization","foo");
SavedRequest savedRequest = new SavedRequest(request, new PortResolverImpl());
MockHttpServletRequest request2 = new MockHttpServletRequest();
request2.addHeader("Authorization","bar");
request2.getSession().setAttribute(AbstractProcessingFilter.SPRING_SECURITY_SAVED_REQUEST_KEY, savedRequest);
SavedRequestAwareWrapper wrapper = new SavedRequestAwareWrapper(request2, new PortResolverImpl(), "ROLE_");
assertEquals("foo", wrapper.getHeader("Authorization"));
}
@Test
public void getParameterValuesReturnsNullIfParameterIsntSet() {
MockHttpServletRequest request = new MockHttpServletRequest();
SavedRequestAwareWrapper wrapper = new SavedRequestAwareWrapper(request, new PortResolverImpl(), "ROLE_");
assertNull(wrapper.getParameterValues("action"));
assertNull(wrapper.getParameterMap().get("action"));
}
@Test
public void getParameterValuesReturnsCombinedValues() {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setParameter("action", "foo");
SavedRequest savedRequest = new SavedRequest(request, new PortResolverImpl());
MockHttpServletRequest request2 = new MockHttpServletRequest();
request2.getSession().setAttribute(AbstractProcessingFilter.SPRING_SECURITY_SAVED_REQUEST_KEY, savedRequest);
SavedRequestAwareWrapper wrapper = new SavedRequestAwareWrapper(request2, new PortResolverImpl(), "ROLE_");
assertArrayEquals(new Object[] {"foo"}, wrapper.getParameterValues("action"));
request2.setParameter("action", "bar");
assertArrayEquals(new Object[] {"bar","foo"}, wrapper.getParameterValues("action"));
// Check map is consistent
String[] valuesFromMap = (String[]) wrapper.getParameterMap().get("action");
assertEquals(2, valuesFromMap.length);
assertEquals("bar", valuesFromMap[0]);
}
}
@@ -9,6 +9,7 @@ http://www.springframework.org/schema/security http://www.springframework.org/sc
<b:bean id="target" class="org.springframework.security.config.TestBusinessBeanImpl">
<!-- This will add a security interceptor to the bean -->
<intercept-methods>
<!-- TODO: It would be better if we didn't need the package/interface names here -->
<protect method="org.springframework.security.config.TestBusinessBean.set*" access="ROLE_ADMIN" />
<protect method="get*" access="ROLE_ADMIN,ROLE_USER" />
<protect method="doSomething" access="ROLE_USER" />
-11
View File
@@ -48,16 +48,6 @@ sn: Smeth
uid: joe
userPassword: joespassword
dn: cn=mouse\, jerry,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Mouse, Jerry
sn: Mouse
uid: jerry
userPassword: jerryspassword
dn: cn=developers,ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: groupOfNames
@@ -72,7 +62,6 @@ objectclass: groupOfNames
cn: managers
ou: manager
member: uid=ben,ou=people,dc=springframework,dc=org
member: cn=mouse\, jerry,ou=people,dc=springframework,dc=org
dn: cn=submanagers,ou=subgroups,ou=groups,dc=springframework,dc=org
objectclass: top
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-parent</artifactId>
<version>2.0.2</version>
<version>2.0.1</version>
</parent>
<packaging>jar</packaging>
<artifactId>spring-security-ntlm</artifactId>
+4 -4
View File
@@ -3,12 +3,12 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-parent</artifactId>
<version>2.0.2</version>
<version>2.0.1</version>
</parent>
<artifactId>spring-security-openid</artifactId>
<name>Spring Security - OpenID support</name>
<description>Spring Security - Support for OpenID</description>
<version>2.0.2</version>
<version>2.0.1</version>
<packaging>bundle</packaging>
<dependencies>
@@ -41,14 +41,14 @@
<properties>
<spring.osgi.export>
org.springframework.security.*;version=${pom.version.osgi}
org.springframework.security.*;version=${pom.version}
</spring.osgi.export>
<spring.osgi.import>
javax.servlet.*;version="[2.4.0, 3.0.0)",
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
org.openid4java.*;version="[0.9.3, 1.0.0)",
org.springframework.security.*;version="[${pom.version.osgi},${pom.version.osgi}]",
org.springframework.security.*;version="[${pom.version},${pom.version}]",
org.springframework.beans.*;version="${spring.version.osgi}",
org.springframework.util.*;version="${spring.version.osgi}"
</spring.osgi.import>
@@ -78,8 +78,6 @@ public class OpenIDAuthenticationProcessingFilter extends AbstractProcessingFilt
throw new AuthenticationServiceException("Consumer error", oice);
}
token.setDetails(authenticationDetailsSource.buildDetails(req));
// delegate to the auth provider
Authentication authentication = this.getAuthenticationManager().authenticate(token);
+5 -6
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-parent</artifactId>
<version>2.0.2</version>
<version>2.0.1</version>
<name>Spring Security</name>
<packaging>pom</packaging>
@@ -38,9 +38,9 @@
<!-- Note when doing releases: tagBase is set in release plugin configuration below -->
<scm>
<connection>scm:svn:https://acegisecurity.svn.sourceforge.net/svnroot/acegisecurity/spring-security/tags/spring-security-parent-2.0.2</connection>
<developerConnection>scm:svn:https://acegisecurity.svn.sourceforge.net/svnroot/acegisecurity/spring-security/tags/spring-security-parent-2.0.2</developerConnection>
<url>http://acegisecurity.svn.sourceforge.net/viewcvs.cgi/acegisecurity/spring-security/tags/spring-security-parent-2.0.2</url>
<connection>scm:svn:https://acegisecurity.svn.sourceforge.net/svnroot/acegisecurity/spring-security/tags/spring-security-parent-2.0.1</connection>
<developerConnection>scm:svn:https://acegisecurity.svn.sourceforge.net/svnroot/acegisecurity/spring-security/tags/spring-security-parent-2.0.1</developerConnection>
<url>http://acegisecurity.svn.sourceforge.net/viewcvs.cgi/acegisecurity/spring-security/tags/spring-security-parent-2.0.1</url>
</scm>
<issueManagement>
@@ -731,8 +731,7 @@
</dependency>
</dependencies>
</dependencyManagement>
<properties>
<pom.version.osgi>2.0.2.SNAPSHOT</pom.version.osgi>
<properties>
<spring.version>2.0.8</spring.version>
<spring.version.osgi>[2.0.8, 3.0.0)</spring.version.osgi>
<jstl.version>1.1.2</jstl.version>
+3 -3
View File
@@ -3,18 +3,18 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-parent</artifactId>
<version>2.0.2</version>
<version>2.0.1</version>
</parent>
<artifactId>spring-security-portlet</artifactId>
<name>Spring Security - Portlet support</name>
<description>Spring Security - Support for JSR 168 Portlets</description>
<version>2.0.2</version>
<version>2.0.1</version>
<dependencies>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>2.0.2</version>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-samples-cas</artifactId>
<version>2.0.2</version>
<version>2.0.1</version>
</parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-samples-cas-client</artifactId>
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-samples</artifactId>
<version>2.0.2</version>
<version>2.0.1</version>
</parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-samples-cas</artifactId>
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-samples-cas</artifactId>
<version>2.0.2</version>
<version>2.0.1</version>
</parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-samples-cas-server</artifactId>
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-samples</artifactId>
<version>2.0.2</version>
<version>2.0.1</version>
</parent>
<artifactId>spring-security-samples-contacts</artifactId>
<name>Spring Security - Contacts sample</name>
@@ -4,7 +4,7 @@
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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.1.xsd">
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
<!--
- Application context containing authentication beans.
@@ -30,6 +30,7 @@
<property name="staticField" value="org.springframework.security.acls.domain.BasePermission.DELETE"/>
</bean>
<!-- An access decision voter that reads ROLE_* configuration settings -->
<bean id="roleVoter" class="org.springframework.security.vote.RoleVoter"/>
@@ -27,17 +27,17 @@
</bean>
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionManager"><ref local="transactionManager"/></property>
<property name="transactionAttributeSource">
<value>
sample.contact.ContactManager.create=PROPAGATION_REQUIRED
sample.contact.ContactManager.getAllRecipients=PROPAGATION_REQUIRED,readOnly
sample.contact.ContactManager.getAll=PROPAGATION_REQUIRED,readOnly
sample.contact.ContactManager.getById=PROPAGATION_REQUIRED,readOnly
sample.contact.ContactManager.delete=PROPAGATION_REQUIRED
sample.contact.ContactManager.deletePermission=PROPAGATION_REQUIRED
sample.contact.ContactManager.addPermission=PROPAGATION_REQUIRED
</value>
<value>
sample.contact.ContactManager.create=PROPAGATION_REQUIRED
sample.contact.ContactManager.getAllRecipients=PROPAGATION_REQUIRED,readOnly
sample.contact.ContactManager.getAll=PROPAGATION_REQUIRED,readOnly
sample.contact.ContactManager.getById=PROPAGATION_REQUIRED,readOnly
sample.contact.ContactManager.delete=PROPAGATION_REQUIRED
sample.contact.ContactManager.deletePermission=PROPAGATION_REQUIRED
sample.contact.ContactManager.addPermission=PROPAGATION_REQUIRED
</value>
</property>
</bean>
@@ -24,7 +24,7 @@
<intercept-url pattern="/j_spring_security_switch_user" access="ROLE_SUPERVISOR"/>
<intercept-url pattern="/**" access="ROLE_USER"/>
<form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error=1"/>
<form-login login-page="/login.jsp" authentication-failure-url="/acegilogin.jsp?login_error=1"/>
<logout logout-success-url="/index.jsp"/>
</http>
@@ -27,23 +27,28 @@
<!-- HTTP invoker exporter for the ContactManager -->
<!-- Spring's HTTP invoker uses Java serialization via HTTP -->
<bean name="/ContactManager-httpinvoker" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
<property name="service" ref="contactManager"/>
<property name="serviceInterface" value="sample.contact.ContactManager"/>
<property name="service"><ref bean="contactManager"/></property>
<property name="serviceInterface">
<value>sample.contact.ContactManager</value>
</property>
</bean>
<!-- Hessian exporter for the ContactManager -->
<!-- Hessian is a slim binary HTTP remoting protocol -->
<bean name="/ContactManager-hessian" class="org.springframework.remoting.caucho.HessianServiceExporter">
<property name="service" ref="contactManager"/>
<property name="serviceInterface" value="sample.contact.ContactManager"/>
<property name="service"><ref bean="contactManager"/></property>
<property name="serviceInterface">
<value>sample.contact.ContactManager</value>
</property>
</bean>
<!-- Burlap exporter for the ContactManager -->
<!-- Burlap is a slim XML-based HTTP remoting protocol -->
<bean name="/ContactManager-burlap" class="org.springframework.remoting.caucho.BurlapServiceExporter">
<property name="service" ref="contactManager"/>
<property name="serviceInterface" value="sample.contact.ContactManager"/>
<property name="service"><ref bean="contactManager"/></property>
<property name="serviceInterface">
<value>sample.contact.ContactManager</value>
</property>
</bean>
</beans>
+3 -3
View File
@@ -27,14 +27,14 @@
--%>
<c:if test="${not empty param.login_error}">
<font color="red">
Your login attempt was not successful, try again.<br/><br/>
Reason: <c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message}"/>.
Your login attempt was not successful, try again.<BR><BR>
Reason: <%= ((AuthenticationException) session.getAttribute(AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY)).getMessage() %>
</font>
</c:if>
<form name="f" action="<c:url value='j_spring_security_check'/>" method="POST">
<table>
<tr><td>User:</td><td><input type='text' name='j_username' value='<c:if test="${not empty param.login_error}"><c:out value="${SPRING_SECURITY_LAST_USERNAME}"/></c:if>'/></td></tr>
<tr><td>User:</td><td><input type='text' name='j_username' <c:if test="${not empty param.login_error}">value='<%= session.getAttribute(AuthenticationProcessingFilter.SPRING_SECURITY_LAST_USERNAME_KEY) %>'</c:if>></td></tr>
<tr><td>Password:</td><td><input type='password' name='j_password'></td></tr>
<tr><td><input type="checkbox" name="_spring_security_remember_me"></td><td>Don't ask for my password for two weeks</td></tr>
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-samples</artifactId>
<version>2.0.2</version>
<version>2.0.1</version>
</parent>
<artifactId>spring-security-samples-dms</artifactId>
<name>Spring Security - DMS sample</name>
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-samples</artifactId>
<version>2.0.2</version>
<version>2.0.1</version>
</parent>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-samples-ldap</artifactId>
@@ -1,63 +1,32 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:s="http://www.springframework.org/schema/security"
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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.1.xsd">
<s:http>
<s:intercept-url pattern="/secure/extreme/**" access="ROLE_SUPERVISOR"/>
<s:intercept-url pattern="/secure/**" access="IS_AUTHENTICATED_REMEMBERED" />
<s:intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<http>
<intercept-url pattern="/secure/extreme/**" access="ROLE_SUPERVISOR"/>
<intercept-url pattern="/secure/**" access="IS_AUTHENTICATED_REMEMBERED" />
<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<s:form-login />
<s:anonymous />
<s:logout />
</s:http>
<form-login />
<anonymous />
<logout />
</http>
<!--
Usernames/Passwords are
rod/koala
dianne/emu
scott/wombat
-->
<ldap-server ldif="classpath:users.ldif" />
<!-- Simple namespace-based configuration -->
<ldap-authentication-provider
group-search-filter="member={0}"
group-search-base="ou=groups"
user-search-base="ou=people"
user-search-filter="uid={0}"
/>
<s:ldap-server ldif="classpath:users.ldif" port="33389"/>
<s:ldap-authentication-provider
group-search-filter="member={0}"
group-search-base="ou=groups"
user-search-base="ou=people"
user-search-filter="uid={0}"
/>
<!-- Traditional Bean version of the same configuration -->
<!-- This bean points at the embedded directory server created by the ldap-server element above -->
<bean id="contextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg value="ldap://localhost:33389/dc=springframework,dc=org"/>
</bean>
<bean id="secondLdapProvider" class="org.springframework.security.providers.ldap.LdapAuthenticationProvider">
<s:custom-authentication-provider />
<constructor-arg>
<bean class="org.springframework.security.providers.ldap.authenticator.BindAuthenticator">
<constructor-arg ref="contextSource" />
<property name="userSearch">
<bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg index="0" value="ou=people"/>
<constructor-arg index="1" value="(uid={0})"/>
<constructor-arg index="2" ref="contextSource" />
</bean>
</property>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator">
<constructor-arg ref="contextSource" />
<constructor-arg value="ou=groups" />
<property name="groupSearchFilter" value="member={0}"/>
<property name="groupRoleAttribute" value="ou" />
<property name="rolePrefix" value="ROLE_"/>
<property name="searchSubtree" value="true"/>
<property name="convertToUpperCase" value="true"/>
</bean>
</constructor-arg>
</bean>
</beans>
</beans:beans>

Some files were not shown because too many files have changed in this diff Show More