Browse Source

Add unbounid support in xml

Add unbounid support in xml

Fixes gh-6011
Rob Winch 6 năm trước cách đây
mục cha
commit
abc90280e0
30 tập tin đã thay đổi với 770 bổ sung18 xóa
  1. 2 0
      config/src/main/java/org/springframework/security/config/BeanIds.java
  2. 2 2
      config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java
  3. 53 10
      config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java
  4. 2 2
      config/src/main/resources/META-INF/spring.schemas
  5. 3 0
      config/src/main/resources/org/springframework/security/config/spring-security-5.2.rnc
  6. 13 0
      config/src/main/resources/org/springframework/security/config/spring-security-5.2.xsd
  7. 4 3
      config/src/test/java/org/springframework/security/config/util/InMemoryXmlApplicationContext.java
  8. 2 0
      docs/manual/src/docs/asciidoc/_includes/servlet/additional-topics/ldap.adoc
  9. 3 0
      docs/manual/src/docs/asciidoc/_includes/servlet/appendix/namespace.adoc
  10. 1 1
      docs/manual/src/docs/asciidoc/index.adoc
  11. 13 0
      itest/ldap/embedded-ldap-apacheds-default/spring-security-itest-ldap-embedded-apacheds-default.gradle
  12. 56 0
      itest/ldap/embedded-ldap-apacheds-default/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java
  13. 9 0
      itest/ldap/embedded-ldap-apacheds-default/src/integration-test/resources/applicationContext-security.xml
  14. 60 0
      itest/ldap/embedded-ldap-apacheds-default/src/integration-test/resources/users.ldif
  15. 13 0
      itest/ldap/embedded-ldap-mode-apacheds/spring-security-itest-ldap-embedded-mode-apacheds.gradle
  16. 56 0
      itest/ldap/embedded-ldap-mode-apacheds/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java
  17. 9 0
      itest/ldap/embedded-ldap-mode-apacheds/src/integration-test/resources/applicationContext-security.xml
  18. 60 0
      itest/ldap/embedded-ldap-mode-apacheds/src/integration-test/resources/users.ldif
  19. 13 0
      itest/ldap/embedded-ldap-mode-unboundid/spring-security-itest-ldap-embedded-mode-unboundid.gradle
  20. 56 0
      itest/ldap/embedded-ldap-mode-unboundid/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java
  21. 9 0
      itest/ldap/embedded-ldap-mode-unboundid/src/integration-test/resources/applicationContext-security.xml
  22. 60 0
      itest/ldap/embedded-ldap-mode-unboundid/src/integration-test/resources/users.ldif
  23. 11 0
      itest/ldap/embedded-ldap-none/spring-security-itest-ldap-embedded-none.gradle
  24. 53 0
      itest/ldap/embedded-ldap-none/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java
  25. 9 0
      itest/ldap/embedded-ldap-none/src/integration-test/resources/applicationContext-security.xml
  26. 60 0
      itest/ldap/embedded-ldap-none/src/integration-test/resources/users.ldif
  27. 13 0
      itest/ldap/embedded-ldap-unboundid-default/spring-security-itest-ldap-embedded-unboundid-default.gradle
  28. 56 0
      itest/ldap/embedded-ldap-unboundid-default/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java
  29. 9 0
      itest/ldap/embedded-ldap-unboundid-default/src/integration-test/resources/applicationContext-security.xml
  30. 60 0
      itest/ldap/embedded-ldap-unboundid-default/src/integration-test/resources/users.ldif

+ 2 - 0
config/src/main/java/org/springframework/security/config/BeanIds.java

@@ -53,6 +53,8 @@ public abstract class BeanIds {
 			+ "methodSecurityMetadataSourceAdvisor";
 	public static final String EMBEDDED_APACHE_DS = PREFIX
 			+ "apacheDirectoryServerContainer";
+	public static final String EMBEDDED_UNBOUNDID = PREFIX
+			+ "unboundidServerContainer";
 	public static final String CONTEXT_SOURCE = PREFIX + "securityContextSource";
 
 	public static final String DEBUG_FILTER = PREFIX + "debugFilter";

+ 2 - 2
config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java

@@ -86,7 +86,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
 		if (!namespaceMatchesVersion(element)) {
 			pc.getReaderContext()
 					.fatal("You cannot use a spring-security-2.0.xsd or spring-security-3.0.xsd or spring-security-3.1.xsd schema or spring-security-3.2.xsd schema or spring-security-4.0.xsd schema "
-							+ "with Spring Security 4.2. Please update your schema declarations to the 4.2 schema.",
+							+ "with Spring Security 5.2. Please update your schema declarations to the 5.2 schema.",
 							element);
 		}
 		String name = pc.getDelegate().getLocalName(element);
@@ -221,7 +221,7 @@ public final class SecurityNamespaceHandler implements NamespaceHandler {
 	private boolean matchesVersionInternal(Element element) {
 		String schemaLocation = element.getAttributeNS(
 				"http://www.w3.org/2001/XMLSchema-instance", "schemaLocation");
-		return schemaLocation.matches("(?m).*spring-security-4\\.2.*.xsd.*")
+		return schemaLocation.matches("(?m).*spring-security-5\\.2.*.xsd.*")
 				|| schemaLocation.matches("(?m).*spring-security.xsd.*")
 				|| !schemaLocation.matches("(?m).*spring-security.*");
 	}

+ 53 - 10
config/src/main/java/org/springframework/security/config/ldap/LdapServerBeanDefinitionParser.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2019 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ import java.net.ServerSocket;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+
 import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
 import org.springframework.beans.factory.support.RootBeanDefinition;
@@ -28,11 +29,14 @@ import org.springframework.beans.factory.xml.BeanDefinitionParser;
 import org.springframework.beans.factory.xml.ParserContext;
 import org.springframework.security.config.BeanIds;
 import org.springframework.security.ldap.server.ApacheDSContainer;
+import org.springframework.security.ldap.server.UnboundIdContainer;
+import org.springframework.util.ClassUtils;
 import org.springframework.util.StringUtils;
 import org.w3c.dom.Element;
 
 /**
  * @author Luke Taylor
+ * @author Eddú Meléndez
  */
 public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
 	private static final String CONTEXT_SOURCE_CLASS = "org.springframework.security.ldap.DefaultSpringSecurityContextSource";
@@ -65,6 +69,12 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
 	private static final int DEFAULT_PORT = 33389;
 	public static final String OPT_DEFAULT_PORT = String.valueOf(DEFAULT_PORT);
 
+	private static final String APACHEDS_CLASSNAME = "org.apache.directory.server.core.DefaultDirectoryService";
+	private static final String UNBOUNID_CLASSNAME = "com.unboundid.ldap.listener.InMemoryDirectoryServer";
+
+	private static final String APACHEDS_CONTAINER_CLASSNAME = "org.springframework.security.ldap.server.ApacheDSContainer";
+	private static final String UNBOUNDID_CONTAINER_CLASSNAME = "org.springframework.security.ldap.server.UnboundIdContainer";
+
 	public BeanDefinition parse(Element elt, ParserContext parserContext) {
 		String url = elt.getAttribute(ATT_URL);
 
@@ -114,6 +124,7 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
 	 * @return the BeanDefinition for the ContextSource for the embedded server.
 	 *
 	 * @see ApacheDSContainer
+	 * @see UnboundIdContainer
 	 */
 	private RootBeanDefinition createEmbeddedServer(Element element,
 			ParserContext parserContext) {
@@ -142,34 +153,65 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
 		contextSource.addPropertyValue("userDn", "uid=admin,ou=system");
 		contextSource.addPropertyValue("password", "secret");
 
-		RootBeanDefinition apacheContainer = new RootBeanDefinition(
-				"org.springframework.security.ldap.server.ApacheDSContainer", null, null);
-		apacheContainer.setSource(source);
-		apacheContainer.getConstructorArgumentValues().addGenericArgumentValue(suffix);
+		String mode = element.getAttribute("mode");
+		RootBeanDefinition ldapContainer = getRootBeanDefinition(mode);
+		ldapContainer.setSource(source);
+		ldapContainer.getConstructorArgumentValues().addGenericArgumentValue(suffix);
 
 		String ldifs = element.getAttribute(ATT_LDIF_FILE);
 		if (!StringUtils.hasText(ldifs)) {
 			ldifs = OPT_DEFAULT_LDIF_FILE;
 		}
 
-		apacheContainer.getConstructorArgumentValues().addGenericArgumentValue(ldifs);
-		apacheContainer.getPropertyValues().addPropertyValue("port", port);
+		ldapContainer.getConstructorArgumentValues().addGenericArgumentValue(ldifs);
+		ldapContainer.getPropertyValues().addPropertyValue("port", port);
 
 		logger.info("Embedded LDAP server bean definition created for URL: " + url);
 
 		if (parserContext.getRegistry()
-				.containsBeanDefinition(BeanIds.EMBEDDED_APACHE_DS)) {
+				.containsBeanDefinition(BeanIds.EMBEDDED_APACHE_DS) ||
+				parserContext.getRegistry().containsBeanDefinition(BeanIds.EMBEDDED_UNBOUNDID)) {
 			parserContext.getReaderContext().error(
 					"Only one embedded server bean is allowed per application context",
 					element);
 		}
 
-		parserContext.getRegistry().registerBeanDefinition(BeanIds.EMBEDDED_APACHE_DS,
-				apacheContainer);
+		String beanId = resolveBeanId(mode);
+		if (beanId != null) {
+			parserContext.getRegistry().registerBeanDefinition(beanId, ldapContainer);
+		}
 
 		return (RootBeanDefinition) contextSource.getBeanDefinition();
 	}
 
+	private RootBeanDefinition getRootBeanDefinition(String mode) {
+		if (isApacheDsEnabled(mode)) {
+			return new RootBeanDefinition(APACHEDS_CONTAINER_CLASSNAME, null, null);
+		}
+		else if (isUnboundidEnabled(mode)) {
+			return new RootBeanDefinition(UNBOUNDID_CONTAINER_CLASSNAME, null, null);
+		}
+		throw new IllegalStateException("Embedded LDAP server is not provided");
+	}
+
+	private String resolveBeanId(String mode) {
+		if (isApacheDsEnabled(mode)) {
+			return BeanIds.EMBEDDED_APACHE_DS;
+		}
+		else if (isUnboundidEnabled(mode)) {
+			return BeanIds.EMBEDDED_UNBOUNDID;
+		}
+		return null;
+	}
+
+	private boolean isApacheDsEnabled(String mode) {
+		return "apacheds".equals(mode) || ClassUtils.isPresent(APACHEDS_CLASSNAME, getClass().getClassLoader());
+	}
+
+	private boolean isUnboundidEnabled(String mode) {
+		return "unboundid".equals(mode) || ClassUtils.isPresent(UNBOUNID_CLASSNAME, getClass().getClassLoader());
+	}
+
 	private String getDefaultPort() {
 		ServerSocket serverSocket = null;
 		try {
@@ -196,4 +238,5 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser {
 			}
 		}
 	}
+
 }

+ 2 - 2
config/src/main/resources/META-INF/spring.schemas

@@ -1,5 +1,5 @@
-http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-5.2.xsd
-http\://www.springframework.org/schema/security/spring-security-5.2.xsd=org/springframework/security/config/spring-security-5.2.xsd
+https\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-5.2.xsd
+https\://www.springframework.org/schema/security/spring-security-5.2.xsd=org/springframework/security/config/spring-security-5.2.xsd
 http\://www.springframework.org/schema/security/spring-security-5.1.xsd=org/springframework/security/config/spring-security-5.1.xsd
 http\://www.springframework.org/schema/security/spring-security-5.0.xsd=org/springframework/security/config/spring-security-5.0.xsd
 http\://www.springframework.org/schema/security/spring-security-4.2.xsd=org/springframework/security/config/spring-security-4.2.xsd

+ 3 - 0
config/src/main/resources/org/springframework/security/config/spring-security-5.2.rnc

@@ -83,6 +83,9 @@ ldap-server.attlist &=
 ldap-server.attlist &=
 	## Optional root suffix for the embedded LDAP server. Default is "dc=springframework,dc=org"
 	attribute root { xsd:string }?
+ldap-server.attlist &=
+	## Explicitly specifies which embedded ldap server should use. Values are 'apacheds' and 'unboundid'. By default, it will depends if the library is available in the classpath.
+	attribute mode { "apacheds" | "unboundid" }?
 
 ldap-server-ref-attribute =
 	## The optional server to use. If omitted, and a default LDAP server is registered (using <ldap-server> with no Id), that server will be used.

+ 13 - 0
config/src/main/resources/org/springframework/security/config/spring-security-5.2.xsd

@@ -222,6 +222,19 @@
                 </xs:documentation>
          </xs:annotation>
       </xs:attribute>
+      <xs:attribute name="mode">
+         <xs:annotation>
+            <xs:documentation>Explicitly specifies which embedded ldap server should use. Values are 'apacheds' and
+                'unboundid'. By default, it will depends if the library is available in the classpath.
+                </xs:documentation>
+         </xs:annotation>
+         <xs:simpleType>
+            <xs:restriction base="xs:token">
+               <xs:enumeration value="apacheds"/>
+               <xs:enumeration value="unboundid"/>
+            </xs:restriction>
+         </xs:simpleType>
+      </xs:attribute>
   </xs:attributeGroup>
   <xs:attributeGroup name="ldap-server-ref-attribute">
       <xs:attribute name="server-ref" use="required" type="xs:token">

+ 4 - 3
config/src/test/java/org/springframework/security/config/util/InMemoryXmlApplicationContext.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2009-2013 the original author or authors.
+ * Copyright 2009-2019 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@ import org.springframework.security.util.InMemoryResource;
 
 /**
  * @author Luke Taylor
+ * @author Eddú Meléndez
  */
 public class InMemoryXmlApplicationContext extends AbstractXmlApplicationContext {
 	static final String BEANS_OPENING = "<b:beans xmlns='http://www.springframework.org/schema/security'\n"
@@ -37,10 +38,10 @@ public class InMemoryXmlApplicationContext extends AbstractXmlApplicationContext
 			+ "http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd\n"
 			+ "http://www.springframework.org/schema/websocket https://www.springframework.org/schema/websocket/spring-websocket.xsd\n"
 			+ "http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context-2.5.xsd\n"
-			+ "http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-";
+			+ "http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security-";
 	static final String BEANS_CLOSE = "</b:beans>\n";
 
-	static final String SPRING_SECURITY_VERSION = "4.2";
+	static final String SPRING_SECURITY_VERSION = "5.2";
 
 	Resource inMemoryXml;
 

+ 2 - 0
docs/manual/src/docs/asciidoc/_includes/servlet/additional-topics/ldap.adoc

@@ -47,6 +47,8 @@ This can be configured to point at an external LDAP server, using the `url` attr
 <ldap-server url="ldap://springframework.org:389/dc=springframework,dc=org" />
 ----
 
+NOTE: `spring-security` provides integration with `apacheds` and `unboundid` as a embedded ldap servers. You can choose between them using the attribute `mode` in `ldap-server`.
+
 ==== Using an Embedded Test Server
 The `<ldap-server>` element can also be used to create an embedded server, which can be very useful for testing and demonstrations.
 In this case you use it without the `url` attribute:

+ 3 - 0
docs/manual/src/docs/asciidoc/_includes/servlet/appendix/namespace.adoc

@@ -2360,6 +2360,9 @@ This is actually the bean `id` of the `ContextSource` instance, if you want to u
 [[nsa-ldap-server-attributes]]
 ===== <ldap-server> Attributes
 
+[[nsa-ldap-server-mode]]
+* **mode**
+Explicitly specifies which embedded ldap server should use. Values are `apacheds` and `unboundid`. By default, it will depends if the library is available in the classpath.
 
 [[nsa-ldap-server-id]]
 * **id**

+ 1 - 1
docs/manual/src/docs/asciidoc/index.adoc

@@ -1,5 +1,5 @@
 = Spring Security Reference
-Ben Alex; Luke Taylor; Rob Winch; Gunnar Hillert; Joe Grandja; Jay Bryant
+Ben Alex; Luke Taylor; Rob Winch; Gunnar Hillert; Joe Grandja; Jay Bryant; Eddú Meléndez
 :include-dir: _includes
 :security-api-url: https://docs.spring.io/spring-security/site/docs/current/api/
 :source-indent: 0

+ 13 - 0
itest/ldap/embedded-ldap-apacheds-default/spring-security-itest-ldap-embedded-apacheds-default.gradle

@@ -0,0 +1,13 @@
+apply plugin: 'io.spring.convention.spring-test'
+
+dependencies {
+    compile project(':spring-security-core')
+    compile 'org.springframework:spring-beans'
+    compile 'org.springframework:spring-context'
+    compile 'org.springframework:spring-core'
+    compile 'org.springframework:spring-tx'
+    compile project(':spring-security-config')
+    compile project(':spring-security-ldap')
+
+    runtime apachedsDependencies
+}

+ 56 - 0
itest/ldap/embedded-ldap-apacheds-default/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java

@@ -0,0 +1,56 @@
+/*
+ * Copyright 2002-2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.security;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.security.config.BeanIds;
+import org.springframework.security.ldap.server.ApacheDSContainer;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author Eddú Meléndez
+ */
+public class LdapServerBeanDefinitionParserTests {
+
+	private ClassPathXmlApplicationContext context;
+
+	@Before
+	public void setup() {
+		this.context = new ClassPathXmlApplicationContext("applicationContext-security.xml");
+	}
+
+	@After
+	public void closeAppContext() {
+		if (this.context != null) {
+			this.context.close();
+			this.context = null;
+		}
+	}
+
+	@Test
+	public void apacheDirectoryServerIsStartedByDefault() {
+		String[] beanNames = this.context.getBeanNamesForType(ApacheDSContainer.class);
+		assertThat(beanNames).hasSize(1);
+		assertThat(beanNames[0]).isEqualTo(BeanIds.EMBEDDED_APACHE_DS);
+	}
+
+}

+ 9 - 0
itest/ldap/embedded-ldap-apacheds-default/src/integration-test/resources/applicationContext-security.xml

@@ -0,0 +1,9 @@
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:s="http://www.springframework.org/schema/security"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
+	http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd">
+
+	<s:ldap-server ldif="classpath:users.ldif"/>
+
+</beans>

+ 60 - 0
itest/ldap/embedded-ldap-apacheds-default/src/integration-test/resources/users.ldif

@@ -0,0 +1,60 @@
+dn: ou=groups,dc=springframework,dc=org
+objectclass: top
+objectclass: organizationalUnit
+ou: groups
+
+dn: ou=people,dc=springframework,dc=org
+objectclass: top
+objectclass: organizationalUnit
+ou: people
+
+dn: uid=rod,ou=people,dc=springframework,dc=org
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+cn: Rod Johnson
+sn: Johnson
+uid: rod
+userPassword: koala
+
+dn: uid=dianne,ou=people,dc=springframework,dc=org
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+cn: Dianne Emu
+sn: Emu
+uid: dianne
+userPassword: emu
+
+dn: uid=scott,ou=people,dc=springframework,dc=org
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+cn: Scott
+sn: Wombat
+uid: scott
+userPassword: wombat
+
+dn: cn=user,ou=groups,dc=springframework,dc=org
+objectclass: top
+objectclass: groupOfNames
+cn: user
+member: uid=rod,ou=people,dc=springframework,dc=org
+member: uid=dianne,ou=people,dc=springframework,dc=org
+member: uid=scott,ou=people,dc=springframework,dc=org
+
+dn: cn=teller,ou=groups,dc=springframework,dc=org
+objectclass: top
+objectclass: groupOfNames
+cn: teller
+member: uid=rod,ou=people,dc=springframework,dc=org
+member: uid=dianne,ou=people,dc=springframework,dc=org
+
+dn: cn=supervisor,ou=groups,dc=springframework,dc=org
+objectclass: top
+objectclass: groupOfNames
+cn: supervisor
+member: uid=rod,ou=people,dc=springframework,dc=org

+ 13 - 0
itest/ldap/embedded-ldap-mode-apacheds/spring-security-itest-ldap-embedded-mode-apacheds.gradle

@@ -0,0 +1,13 @@
+apply plugin: 'io.spring.convention.spring-test'
+
+dependencies {
+    compile project(':spring-security-core')
+    compile 'org.springframework:spring-beans'
+    compile 'org.springframework:spring-context'
+    compile 'org.springframework:spring-core'
+    compile 'org.springframework:spring-tx'
+    compile project(':spring-security-config')
+    compile project(':spring-security-ldap')
+
+    runtime apachedsDependencies
+}

+ 56 - 0
itest/ldap/embedded-ldap-mode-apacheds/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java

@@ -0,0 +1,56 @@
+/*
+ * Copyright 2002-2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.security;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.security.config.BeanIds;
+import org.springframework.security.ldap.server.ApacheDSContainer;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author Eddú Meléndez
+ */
+public class LdapServerBeanDefinitionParserTests {
+
+	private ClassPathXmlApplicationContext context;
+
+	@Before
+	public void setup() {
+		this.context = new ClassPathXmlApplicationContext("applicationContext-security.xml");
+	}
+
+	@After
+	public void closeAppContext() {
+		if (this.context != null) {
+			this.context.close();
+			this.context = null;
+		}
+	}
+
+	@Test
+	public void apacheDirectoryServerIsStartedByDefault() {
+		String[] beanNames = this.context.getBeanNamesForType(ApacheDSContainer.class);
+		assertThat(beanNames).hasSize(1);
+		assertThat(beanNames[0]).isEqualTo(BeanIds.EMBEDDED_APACHE_DS);
+	}
+
+}

+ 9 - 0
itest/ldap/embedded-ldap-mode-apacheds/src/integration-test/resources/applicationContext-security.xml

@@ -0,0 +1,9 @@
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:s="http://www.springframework.org/schema/security"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
+	http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd">
+
+	<s:ldap-server mode="apacheds" ldif="classpath:users.ldif"/>
+
+</beans>

+ 60 - 0
itest/ldap/embedded-ldap-mode-apacheds/src/integration-test/resources/users.ldif

@@ -0,0 +1,60 @@
+dn: ou=groups,dc=springframework,dc=org
+objectclass: top
+objectclass: organizationalUnit
+ou: groups
+
+dn: ou=people,dc=springframework,dc=org
+objectclass: top
+objectclass: organizationalUnit
+ou: people
+
+dn: uid=rod,ou=people,dc=springframework,dc=org
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+cn: Rod Johnson
+sn: Johnson
+uid: rod
+userPassword: koala
+
+dn: uid=dianne,ou=people,dc=springframework,dc=org
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+cn: Dianne Emu
+sn: Emu
+uid: dianne
+userPassword: emu
+
+dn: uid=scott,ou=people,dc=springframework,dc=org
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+cn: Scott
+sn: Wombat
+uid: scott
+userPassword: wombat
+
+dn: cn=user,ou=groups,dc=springframework,dc=org
+objectclass: top
+objectclass: groupOfNames
+cn: user
+member: uid=rod,ou=people,dc=springframework,dc=org
+member: uid=dianne,ou=people,dc=springframework,dc=org
+member: uid=scott,ou=people,dc=springframework,dc=org
+
+dn: cn=teller,ou=groups,dc=springframework,dc=org
+objectclass: top
+objectclass: groupOfNames
+cn: teller
+member: uid=rod,ou=people,dc=springframework,dc=org
+member: uid=dianne,ou=people,dc=springframework,dc=org
+
+dn: cn=supervisor,ou=groups,dc=springframework,dc=org
+objectclass: top
+objectclass: groupOfNames
+cn: supervisor
+member: uid=rod,ou=people,dc=springframework,dc=org

+ 13 - 0
itest/ldap/embedded-ldap-mode-unboundid/spring-security-itest-ldap-embedded-mode-unboundid.gradle

@@ -0,0 +1,13 @@
+apply plugin: 'io.spring.convention.spring-test'
+
+dependencies {
+    compile project(':spring-security-core')
+    compile 'org.springframework:spring-beans'
+    compile 'org.springframework:spring-context'
+    compile 'org.springframework:spring-core'
+    compile 'org.springframework:spring-tx'
+    compile project(':spring-security-config')
+    compile project(':spring-security-ldap')
+
+    testCompile "com.unboundid:unboundid-ldapsdk"
+}

+ 56 - 0
itest/ldap/embedded-ldap-mode-unboundid/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java

@@ -0,0 +1,56 @@
+/*
+ * Copyright 2002-2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.security;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.security.config.BeanIds;
+import org.springframework.security.ldap.server.UnboundIdContainer;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author Eddú Meléndez
+ */
+public class LdapServerBeanDefinitionParserTests {
+
+	private ClassPathXmlApplicationContext context;
+
+	@Before
+	public void setup() {
+		this.context = new ClassPathXmlApplicationContext("applicationContext-security.xml");
+	}
+
+	@After
+	public void closeAppContext() {
+		if (this.context != null) {
+			this.context.close();
+			this.context = null;
+		}
+	}
+
+	@Test
+	public void apacheDirectoryServerIsStartedByDefault() {
+		String[] beanNames = this.context.getBeanNamesForType(UnboundIdContainer.class);
+		assertThat(beanNames).hasSize(1);
+		assertThat(beanNames[0]).isEqualTo(BeanIds.EMBEDDED_UNBOUNDID);
+	}
+
+}

+ 9 - 0
itest/ldap/embedded-ldap-mode-unboundid/src/integration-test/resources/applicationContext-security.xml

@@ -0,0 +1,9 @@
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:s="http://www.springframework.org/schema/security"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
+	http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd">
+
+	<s:ldap-server mode="unboundid" ldif="classpath:users.ldif"/>
+
+</beans>

+ 60 - 0
itest/ldap/embedded-ldap-mode-unboundid/src/integration-test/resources/users.ldif

@@ -0,0 +1,60 @@
+dn: ou=groups,dc=springframework,dc=org
+objectclass: top
+objectclass: organizationalUnit
+ou: groups
+
+dn: ou=people,dc=springframework,dc=org
+objectclass: top
+objectclass: organizationalUnit
+ou: people
+
+dn: uid=rod,ou=people,dc=springframework,dc=org
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+cn: Rod Johnson
+sn: Johnson
+uid: rod
+userPassword: koala
+
+dn: uid=dianne,ou=people,dc=springframework,dc=org
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+cn: Dianne Emu
+sn: Emu
+uid: dianne
+userPassword: emu
+
+dn: uid=scott,ou=people,dc=springframework,dc=org
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+cn: Scott
+sn: Wombat
+uid: scott
+userPassword: wombat
+
+dn: cn=user,ou=groups,dc=springframework,dc=org
+objectclass: top
+objectclass: groupOfNames
+cn: user
+member: uid=rod,ou=people,dc=springframework,dc=org
+member: uid=dianne,ou=people,dc=springframework,dc=org
+member: uid=scott,ou=people,dc=springframework,dc=org
+
+dn: cn=teller,ou=groups,dc=springframework,dc=org
+objectclass: top
+objectclass: groupOfNames
+cn: teller
+member: uid=rod,ou=people,dc=springframework,dc=org
+member: uid=dianne,ou=people,dc=springframework,dc=org
+
+dn: cn=supervisor,ou=groups,dc=springframework,dc=org
+objectclass: top
+objectclass: groupOfNames
+cn: supervisor
+member: uid=rod,ou=people,dc=springframework,dc=org

+ 11 - 0
itest/ldap/embedded-ldap-none/spring-security-itest-ldap-embedded-none.gradle

@@ -0,0 +1,11 @@
+apply plugin: 'io.spring.convention.spring-test'
+
+dependencies {
+    compile project(':spring-security-core')
+    compile 'org.springframework:spring-beans'
+    compile 'org.springframework:spring-context'
+    compile 'org.springframework:spring-core'
+    compile 'org.springframework:spring-tx'
+    compile project(':spring-security-config')
+    compile project(':spring-security-ldap')
+}

+ 53 - 0
itest/ldap/embedded-ldap-none/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java

@@ -0,0 +1,53 @@
+/*
+ * Copyright 2002-2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.security;
+
+import org.junit.After;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import org.springframework.beans.factory.BeanDefinitionStoreException;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * @author Eddú Meléndez
+ */
+public class LdapServerBeanDefinitionParserTests {
+
+	@Rule
+	public ExpectedException thrown = ExpectedException.none();
+
+	private ClassPathXmlApplicationContext context;
+
+	@After
+	public void closeAppContext() {
+		if (this.context != null) {
+			this.context.close();
+			this.context = null;
+		}
+	}
+
+	@Test
+	public void apacheDirectoryServerIsStartedByDefault() {
+		this.thrown.expect(BeanDefinitionStoreException.class);
+		this.thrown.expectMessage("Embedded LDAP server is not provided");
+
+		this.context = new ClassPathXmlApplicationContext("applicationContext-security.xml");
+	}
+
+}

+ 9 - 0
itest/ldap/embedded-ldap-none/src/integration-test/resources/applicationContext-security.xml

@@ -0,0 +1,9 @@
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:s="http://www.springframework.org/schema/security"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
+	http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd">
+
+	<s:ldap-server ldif="classpath:users.ldif"/>
+
+</beans>

+ 60 - 0
itest/ldap/embedded-ldap-none/src/integration-test/resources/users.ldif

@@ -0,0 +1,60 @@
+dn: ou=groups,dc=springframework,dc=org
+objectclass: top
+objectclass: organizationalUnit
+ou: groups
+
+dn: ou=people,dc=springframework,dc=org
+objectclass: top
+objectclass: organizationalUnit
+ou: people
+
+dn: uid=rod,ou=people,dc=springframework,dc=org
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+cn: Rod Johnson
+sn: Johnson
+uid: rod
+userPassword: koala
+
+dn: uid=dianne,ou=people,dc=springframework,dc=org
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+cn: Dianne Emu
+sn: Emu
+uid: dianne
+userPassword: emu
+
+dn: uid=scott,ou=people,dc=springframework,dc=org
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+cn: Scott
+sn: Wombat
+uid: scott
+userPassword: wombat
+
+dn: cn=user,ou=groups,dc=springframework,dc=org
+objectclass: top
+objectclass: groupOfNames
+cn: user
+member: uid=rod,ou=people,dc=springframework,dc=org
+member: uid=dianne,ou=people,dc=springframework,dc=org
+member: uid=scott,ou=people,dc=springframework,dc=org
+
+dn: cn=teller,ou=groups,dc=springframework,dc=org
+objectclass: top
+objectclass: groupOfNames
+cn: teller
+member: uid=rod,ou=people,dc=springframework,dc=org
+member: uid=dianne,ou=people,dc=springframework,dc=org
+
+dn: cn=supervisor,ou=groups,dc=springframework,dc=org
+objectclass: top
+objectclass: groupOfNames
+cn: supervisor
+member: uid=rod,ou=people,dc=springframework,dc=org

+ 13 - 0
itest/ldap/embedded-ldap-unboundid-default/spring-security-itest-ldap-embedded-unboundid-default.gradle

@@ -0,0 +1,13 @@
+apply plugin: 'io.spring.convention.spring-test'
+
+dependencies {
+    compile project(':spring-security-core')
+    compile 'org.springframework:spring-beans'
+    compile 'org.springframework:spring-context'
+    compile 'org.springframework:spring-core'
+    compile 'org.springframework:spring-tx'
+    compile project(':spring-security-config')
+    compile project(':spring-security-ldap')
+
+    testCompile "com.unboundid:unboundid-ldapsdk"
+}

+ 56 - 0
itest/ldap/embedded-ldap-unboundid-default/src/integration-test/java/org/springframework/security/LdapServerBeanDefinitionParserTests.java

@@ -0,0 +1,56 @@
+/*
+ * Copyright 2002-2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.security;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.security.config.BeanIds;
+import org.springframework.security.ldap.server.UnboundIdContainer;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author Eddú Meléndez
+ */
+public class LdapServerBeanDefinitionParserTests {
+
+	private ClassPathXmlApplicationContext context;
+
+	@Before
+	public void setup() {
+		this.context = new ClassPathXmlApplicationContext("applicationContext-security.xml");
+	}
+
+	@After
+	public void closeAppContext() {
+		if (this.context != null) {
+			this.context.close();
+			this.context = null;
+		}
+	}
+
+	@Test
+	public void apacheDirectoryServerIsStartedByDefault() {
+		String[] beanNames = this.context.getBeanNamesForType(UnboundIdContainer.class);
+		assertThat(beanNames).hasSize(1);
+		assertThat(beanNames[0]).isEqualTo(BeanIds.EMBEDDED_UNBOUNDID);
+	}
+
+}

+ 9 - 0
itest/ldap/embedded-ldap-unboundid-default/src/integration-test/resources/applicationContext-security.xml

@@ -0,0 +1,9 @@
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:s="http://www.springframework.org/schema/security"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
+	http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd">
+
+	<s:ldap-server ldif="classpath:users.ldif"/>
+
+</beans>

+ 60 - 0
itest/ldap/embedded-ldap-unboundid-default/src/integration-test/resources/users.ldif

@@ -0,0 +1,60 @@
+dn: ou=groups,dc=springframework,dc=org
+objectclass: top
+objectclass: organizationalUnit
+ou: groups
+
+dn: ou=people,dc=springframework,dc=org
+objectclass: top
+objectclass: organizationalUnit
+ou: people
+
+dn: uid=rod,ou=people,dc=springframework,dc=org
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+cn: Rod Johnson
+sn: Johnson
+uid: rod
+userPassword: koala
+
+dn: uid=dianne,ou=people,dc=springframework,dc=org
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+cn: Dianne Emu
+sn: Emu
+uid: dianne
+userPassword: emu
+
+dn: uid=scott,ou=people,dc=springframework,dc=org
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+cn: Scott
+sn: Wombat
+uid: scott
+userPassword: wombat
+
+dn: cn=user,ou=groups,dc=springframework,dc=org
+objectclass: top
+objectclass: groupOfNames
+cn: user
+member: uid=rod,ou=people,dc=springframework,dc=org
+member: uid=dianne,ou=people,dc=springframework,dc=org
+member: uid=scott,ou=people,dc=springframework,dc=org
+
+dn: cn=teller,ou=groups,dc=springframework,dc=org
+objectclass: top
+objectclass: groupOfNames
+cn: teller
+member: uid=rod,ou=people,dc=springframework,dc=org
+member: uid=dianne,ou=people,dc=springframework,dc=org
+
+dn: cn=supervisor,ou=groups,dc=springframework,dc=org
+objectclass: top
+objectclass: groupOfNames
+cn: supervisor
+member: uid=rod,ou=people,dc=springframework,dc=org