1
0
mirror of synced 2026-08-05 17:57:15 +00:00

SEC-1126: separated out spring-security-config module containing namespace configuration classes and resources

This commit is contained in:
Luke Taylor
2009-03-23 04:23:48 +00:00
parent a45ba138f7
commit 2c985a1c36
92 changed files with 322 additions and 79 deletions
@@ -1,52 +0,0 @@
package org.springframework.security.config.ldap;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.Ordered;
import org.springframework.ldap.core.support.BaseLdapPathContextSource;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.Elements;
import org.springframework.security.config.SecurityConfigurationException;
/**
* Checks for the presence of a ContextSource instance. Also supplies the standard reference to any
* unconfigured <ldap-authentication-provider> or <ldap-user-service> beans. This is
* necessary in cases where the user has given the server a specific Id, but hasn't used
* the server-ref attribute to link this to the other ldap definitions. See SEC-799.
*
* @author Luke Taylor
* @version $Id$
* @since 2.5
*/
public class ContextSourceSettingPostProcessor implements BeanFactoryPostProcessor, Ordered {
/** If set to true, a bean parser has indicated that the default context source name needs to be set */
private boolean defaultNameRequired;
public void postProcessBeanFactory(ConfigurableListableBeanFactory bf) throws BeansException {
String[] sources = bf.getBeanNamesForType(BaseLdapPathContextSource.class);
if (sources.length == 0) {
throw new SecurityConfigurationException("No BaseLdapPathContextSource instances found. Have you " +
"added an <" + Elements.LDAP_SERVER + " /> element to your application context?");
}
if (!bf.containsBean(BeanIds.CONTEXT_SOURCE) && defaultNameRequired) {
if (sources.length > 1) {
throw new SecurityConfigurationException("More than one BaseLdapPathContextSource instance found. " +
"Please specify a specific server id using the 'server-ref' attribute when configuring your <" +
Elements.LDAP_PROVIDER + "> " + "or <" + Elements.LDAP_USER_SERVICE + ">.");
}
bf.registerAlias(sources[0], BeanIds.CONTEXT_SOURCE);
}
}
public void setDefaultNameRequired(boolean defaultNameRequired) {
this.defaultNameRequired = defaultNameRequired;
}
public int getOrder() {
return LOWEST_PRECEDENCE;
}
}
@@ -1,4 +1,4 @@
package org.springframework.security.config.ldap;
package org.springframework.security.ldap.server;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.DisposableBean;
@@ -7,8 +7,8 @@ import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.Lifecycle;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.ldap.core.ContextSource;
import org.springframework.security.config.LdapServerBeanDefinitionParser;
import org.springframework.util.Assert;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -39,12 +39,14 @@ import java.io.IOException;
* repeatedly loading an application context during testing), it's important that the
* application context is closed to allow the bean to be disposed of and the server shutdown
* prior to attempting to start it again.
* </p>
* <p>
* This class is intended for testing and internal security namespace use and is not considered part of
* framework public API.
*
* @author Luke Taylor
* @version $Id$
*/
class ApacheDSContainer implements InitializingBean, DisposableBean, Lifecycle, ApplicationContextAware {
public class ApacheDSContainer implements InitializingBean, DisposableBean, Lifecycle, ApplicationContextAware {
private Log logger = LogFactory.getLog(getClass());
private MutableServerStartupConfiguration configuration;
@@ -152,7 +154,14 @@ class ApacheDSContainer implements InitializingBean, DisposableBean, Lifecycle,
private void importLdifs() throws IOException, NamingException {
// Import any ldif files
Resource[] ldifs = ctxt.getResources(ldifResources);
Resource[] ldifs;
if (ctxt == null) {
// Not running within an app context
ldifs = new PathMatchingResourcePatternResolver().getResources(ldifResources);
} else {
ldifs = ctxt.getResources(ldifResources);
}
// Note that we can't just import using the ServerContext returned
// from starting Apace DS, apparently because of the long-running issue DIRSERVER-169.
@@ -1,112 +0,0 @@
package org.springframework.security;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.After;
import org.junit.Test;
import org.springframework.security.Authentication;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.SecurityConfigurationException;
import org.springframework.security.providers.ProviderManager;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.providers.ldap.LdapAuthenticationProvider;
import org.springframework.security.userdetails.ldap.InetOrgPersonContextMapper;
import org.springframework.security.userdetails.ldap.LdapUserDetailsImpl;
import org.springframework.security.util.FieldUtils;
import org.springframework.security.util.InMemoryXmlApplicationContext;
/**
* @author Luke Taylor
* @version $Id$
*/
public class LdapProviderBeanDefinitionParserTests {
InMemoryXmlApplicationContext appCtx;
@After
public void closeAppContext() {
if (appCtx != null) {
appCtx.close();
appCtx = null;
}
}
@Test
public void simpleProviderAuthenticatesCorrectly() {
setContext("<ldap-server /> <ldap-authentication-provider group-search-filter='member={0}' />");
LdapAuthenticationProvider provider = getProvider();
Authentication auth = provider.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword"));
LdapUserDetailsImpl ben = (LdapUserDetailsImpl) auth.getPrincipal();
assertEquals(3, ben.getAuthorities().size());
}
@Test(expected = SecurityConfigurationException.class)
public void missingServerEltCausesConfigException() {
setContext("<ldap-authentication-provider />");
}
@Test
public void supportsPasswordComparisonAuthentication() {
setContext("<ldap-server /> " +
"<ldap-authentication-provider user-dn-pattern='uid={0},ou=people'>" +
" <password-compare />" +
"</ldap-authentication-provider>");
LdapAuthenticationProvider provider = getProvider();
provider.authenticate(new UsernamePasswordAuthenticationToken("ben", "benspassword"));
}
@Test
public void supportsPasswordComparisonAuthenticationWithHashAttribute() {
setContext("<ldap-server /> " +
"<ldap-authentication-provider user-dn-pattern='uid={0},ou=people'>" +
" <password-compare password-attribute='uid' hash='plaintext'/>" +
"</ldap-authentication-provider>");
LdapAuthenticationProvider provider = getProvider();
provider.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben"));
}
@Test
public void supportsPasswordComparisonAuthenticationWithPasswordEncoder() {
setContext("<ldap-server /> " +
"<ldap-authentication-provider user-dn-pattern='uid={0},ou=people'>" +
" <password-compare password-attribute='uid'>" +
" <password-encoder hash='plaintext'/>" +
" </password-compare>" +
"</ldap-authentication-provider>");
LdapAuthenticationProvider provider = getProvider();
provider.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben"));
}
@Test
public void detectsNonStandardServerId() {
setContext("<ldap-server id='myServer'/> " +
"<ldap-authentication-provider />");
}
@Test
public void inetOrgContextMapperIsSupported() throws Exception {
setContext(
"<ldap-server id='someServer' url='ldap://127.0.0.1:343/dc=springframework,dc=org'/>" +
"<ldap-authentication-provider user-details-class='inetOrgPerson'/>");
LdapAuthenticationProvider provider = getProvider();
assertTrue(FieldUtils.getFieldValue(provider, "userDetailsContextMapper") instanceof InetOrgPersonContextMapper);
}
private void setContext(String context) {
appCtx = new InMemoryXmlApplicationContext(context);
}
private LdapAuthenticationProvider getProvider() {
ProviderManager authManager = (ProviderManager) appCtx.getBean(BeanIds.AUTHENTICATION_MANAGER);
assertEquals(1, authManager.getProviders().size());
LdapAuthenticationProvider provider = (LdapAuthenticationProvider) authManager.getProviders().get(0);
return provider;
}
}
@@ -1,64 +0,0 @@
package org.springframework.security;
import org.junit.After;
import org.junit.Test;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.security.config.BeanIds;
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
import org.springframework.security.util.InMemoryXmlApplicationContext;
/**
* @author Luke Taylor
* @version $Id$
*/
public class LdapServerBeanDefinitionParserTests {
InMemoryXmlApplicationContext appCtx;
@After
public void closeAppContext() {
if (appCtx != null) {
appCtx.close();
appCtx = null;
}
}
@Test
public void embeddedServerCreationContainsExpectedContextSourceAndData() {
appCtx = new InMemoryXmlApplicationContext("<ldap-server />");
DefaultSpringSecurityContextSource contextSource = (DefaultSpringSecurityContextSource) appCtx.getBean(BeanIds.CONTEXT_SOURCE);
// Check data is loaded
LdapTemplate template = new LdapTemplate(contextSource);
template.lookup("uid=ben,ou=people");
}
@Test
public void useOfUrlAttributeCreatesCorrectContextSource() {
// Create second "server" with a url pointing at embedded one
appCtx = new InMemoryXmlApplicationContext("<ldap-server port='33388'/>" +
"<ldap-server id='blah' url='ldap://127.0.0.1:33388/dc=springframework,dc=org' />");
// Check the default context source is still there.
appCtx.getBean(BeanIds.CONTEXT_SOURCE);
DefaultSpringSecurityContextSource contextSource = (DefaultSpringSecurityContextSource) appCtx.getBean("blah");
// Check data is loaded as before
LdapTemplate template = new LdapTemplate(contextSource);
template.lookup("uid=ben,ou=people");
}
@Test
public void loadingSpecificLdifFileIsSuccessful() {
appCtx = new InMemoryXmlApplicationContext(
"<ldap-server ldif='classpath*:test-server2.xldif' root='dc=monkeymachine,dc=co,dc=uk' />");
DefaultSpringSecurityContextSource contextSource = (DefaultSpringSecurityContextSource) appCtx.getBean(BeanIds.CONTEXT_SOURCE);
LdapTemplate template = new LdapTemplate(contextSource);
template.lookup("uid=pg,ou=gorillas");
}
}
@@ -1,129 +0,0 @@
package org.springframework.security;
import java.util.Set;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.util.AuthorityUtils;
import org.springframework.security.util.InMemoryXmlApplicationContext;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.ldap.InetOrgPerson;
import org.springframework.security.userdetails.ldap.Person;
import org.junit.Test;
import org.junit.After;
import static org.junit.Assert.*;
/**
* @author Luke Taylor
* @version $Id$
*/
public class LdapUserServiceBeanDefinitionParserTests {
private InMemoryXmlApplicationContext appCtx;
@After
public void closeAppContext() {
if (appCtx != null) {
appCtx.close();
appCtx = null;
}
}
@Test
public void minimalConfigurationIsParsedOk() throws Exception {
setContext("<ldap-user-service user-search-filter='(uid={0})' /><ldap-server url='ldap://127.0.0.1:343/dc=springframework,dc=org' />");
}
@Test
public void userServiceReturnsExpectedData() throws Exception {
setContext("<ldap-user-service id='ldapUDS' user-search-filter='(uid={0})' group-search-filter='member={0}' /><ldap-server />");
UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
UserDetails ben = uds.loadUserByUsername("ben");
Set<String> authorities = AuthorityUtils.authorityListToSet(ben.getAuthorities());
assertEquals(3, authorities.size());
assertTrue(authorities.contains("ROLE_DEVELOPERS"));
}
@Test
public void differentUserSearchBaseWorksAsExpected() throws Exception {
setContext("<ldap-user-service id='ldapUDS' " +
" user-search-base='ou=otherpeople' " +
" user-search-filter='(cn={0})' " +
" group-search-filter='member={0}' /><ldap-server />");
UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
UserDetails joe = uds.loadUserByUsername("Joe Smeth");
assertEquals("Joe Smeth", joe.getUsername());
}
@Test
public void rolePrefixIsSupported() throws Exception {
setContext(
"<ldap-user-service id='ldapUDS' " +
" user-search-filter='(uid={0})' " +
" group-search-filter='member={0}' role-prefix='PREFIX_'/>" +
"<ldap-user-service id='ldapUDSNoPrefix' " +
" user-search-filter='(uid={0})' " +
" group-search-filter='member={0}' role-prefix='none'/><ldap-server />");
UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
UserDetails ben = uds.loadUserByUsername("ben");
assertTrue(AuthorityUtils.authorityListToSet(ben.getAuthorities()).contains("PREFIX_DEVELOPERS"));
uds = (UserDetailsService) appCtx.getBean("ldapUDSNoPrefix");
ben = uds.loadUserByUsername("ben");
assertTrue(AuthorityUtils.authorityListToSet(ben.getAuthorities()).contains("DEVELOPERS"));
}
@Test
public void differentGroupRoleAttributeWorksAsExpected() throws Exception {
setContext("<ldap-user-service id='ldapUDS' user-search-filter='(uid={0})' group-role-attribute='ou' group-search-filter='member={0}' /><ldap-server />");
UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
UserDetails ben = uds.loadUserByUsername("ben");
Set<String> authorities = AuthorityUtils.authorityListToSet(ben.getAuthorities());
assertEquals(3, authorities.size());
assertTrue(authorities.contains(new GrantedAuthorityImpl("ROLE_DEVELOPER")));
}
@Test
public void isSupportedByAuthenticationProviderElement() {
setContext(
"<ldap-server url='ldap://127.0.0.1:343/dc=springframework,dc=org'/>" +
"<authentication-provider>" +
" <ldap-user-service user-search-filter='(uid={0})' />" +
"</authentication-provider>");
}
@Test
public void personContextMapperIsSupported() {
setContext(
"<ldap-server />" +
"<ldap-user-service id='ldapUDS' user-search-filter='(uid={0})' user-details-class='person'/>");
UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
UserDetails ben = uds.loadUserByUsername("ben");
assertTrue(ben instanceof Person);
}
@Test
public void inetOrgContextMapperIsSupported() {
setContext(
"<ldap-server id='someServer'/>" +
"<ldap-user-service id='ldapUDS' user-search-filter='(uid={0})' user-details-class='inetOrgPerson'/>");
UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
UserDetails ben = uds.loadUserByUsername("ben");
assertTrue(ben instanceof InetOrgPerson);
}
private void setContext(String context) {
appCtx = new InMemoryXmlApplicationContext(context);
}
}
@@ -14,15 +14,24 @@
*/
package org.springframework.security.ldap;
import java.util.HashSet;
import java.util.Set;
import javax.naming.Binding;
import javax.naming.ContextNotEmptyException;
import javax.naming.Name;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import org.apache.directory.server.configuration.MutableServerStartupConfiguration;
import org.apache.directory.server.core.DirectoryService;
import org.apache.directory.server.core.partition.impl.btree.MutableBTreePartitionConfiguration;
import org.apache.directory.server.protocol.shared.store.LdifFileLoader;
import org.junit.After;
import org.junit.AfterClass;
@@ -31,8 +40,7 @@ import org.junit.BeforeClass;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.support.BaseLdapPathContextSource;
import org.springframework.security.config.BeanIds;
import org.springframework.security.util.InMemoryXmlApplicationContext;
import org.springframework.security.ldap.server.ApacheDSContainer;
/**
* Based on class borrowed from Spring Ldap project.
@@ -41,22 +49,48 @@ import org.springframework.security.util.InMemoryXmlApplicationContext;
* @version $Id$
*/
public abstract class AbstractLdapIntegrationTests {
private static InMemoryXmlApplicationContext appContext;
// private static InMemoryXmlApplicationContext appContext;
private static ApacheDSContainer server;
private static BaseLdapPathContextSource contextSource;
protected AbstractLdapIntegrationTests() {
}
@BeforeClass
public static void loadContext() throws NamingException {
public static void startServer() throws Exception {
shutdownRunningServers();
appContext = new InMemoryXmlApplicationContext("<ldap-server port='53389' ldif='classpath:test-server.ldif'/>");
MutableBTreePartitionConfiguration partition = new MutableBTreePartitionConfiguration();
partition.setName("springsecurity");
Attributes rootAttributes = new BasicAttributes("dc", "springsecurity");
Attribute a = new BasicAttribute("objectClass");
a.add("top");
a.add("domain");
a.add("extensibleObject");
rootAttributes.put(a);
partition.setContextEntry(rootAttributes);
partition.setSuffix("dc=springframework,dc=org");
Set partitions = new HashSet();
partitions.add(partition);
MutableServerStartupConfiguration cfg = new MutableServerStartupConfiguration();
cfg.setLdapPort(53389);
cfg.setShutdownHookEnabled(false);
cfg.setExitVmOnShutdown(false);
cfg.setContextPartitionConfigurations(partitions);
contextSource = new DefaultSpringSecurityContextSource("ldap://127.0.0.1:53389/dc=springframework,dc=org");
((DefaultSpringSecurityContextSource)contextSource).afterPropertiesSet();
server = new ApacheDSContainer(cfg, contextSource, "classpath:test-server.ldif");
server.afterPropertiesSet();
}
@AfterClass
public static void closeContext() throws Exception {
if(appContext != null) {
appContext.close();
public static void stopServer() throws Exception {
if (server != null) {
server.stop();
}
shutdownRunningServers();
}
@@ -100,7 +134,7 @@ public abstract class AbstractLdapIntegrationTests {
}
public BaseLdapPathContextSource getContextSource() {
return (BaseLdapPathContextSource)appContext.getBean(BeanIds.CONTEXT_SOURCE);
return contextSource;
}
@@ -1,16 +0,0 @@
dn: ou=gorillas,dc=monkeymachine,dc=co,dc=uk
objectclass: top
objectclass: organizationalUnit
ou: gorillas
dn: uid=pg,ou=gorillas,dc=monkeymachine,dc=co,dc=uk
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Pierre
sn: Gorille
uid: pg
userPassword: password