Commit c35454e5 authored by Phillip Webb's avatar Phillip Webb

Merge branch '1.5.x'

parents da4f8514 e9acc7f1
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
......@@ -257,10 +257,11 @@ public class ManagementWebSecurityAutoConfiguration {
private void configurePermittedRequests(
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry requests) {
requests.requestMatchers(new LazyEndpointPathRequestMatcher(
this.contextResolver, EndpointPaths.SENSITIVE)).authenticated();
// Permit access to the non-sensitive endpoints
requests.requestMatchers(new LazyEndpointPathRequestMatcher(
this.contextResolver, EndpointPaths.NON_SENSITIVE)).permitAll();
requests.anyRequest().authenticated();
}
}
......@@ -276,6 +277,15 @@ public class ManagementWebSecurityAutoConfiguration {
return !endpoint.isSensitive();
}
},
SENSITIVE {
@Override
protected boolean isIncluded(MvcEndpoint endpoint) {
return endpoint.isSensitive();
}
};
public String[] getPaths(EndpointHandlerMapping endpointHandlerMapping) {
......@@ -289,12 +299,9 @@ public class ManagementWebSecurityAutoConfiguration {
String path = endpointHandlerMapping.getPath(endpoint.getPath());
paths.add(path);
if (!path.equals("")) {
if (endpoint.isSensitive()) {
// Ensure that nested paths are secured
paths.add(path + "/**");
// Add Spring MVC-generated additional paths
paths.add(path + ".*");
}
paths.add(path + "/**");
// Add Spring MVC-generated additional paths
paths.add(path + ".*");
}
paths.add(path + "/");
}
......
......@@ -234,6 +234,11 @@
<artifactId>sendgrid-java</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.unboundid</groupId>
<artifactId>unboundid-ldapsdk</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP-java6</artifactId>
......@@ -382,6 +387,11 @@
<artifactId>spring-data-cassandra</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-ldap</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
......
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.data.ldap;
import javax.naming.ldap.LdapContext;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.ldap.repository.LdapRepository;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.ldap.core.LdapTemplate;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's LDAP support.
*
* @author Eddú Meléndez
* @since 1.5.0
*/
@Configuration
@ConditionalOnClass({ LdapContext.class, LdapRepository.class })
@AutoConfigureAfter(LdapAutoConfiguration.class)
public class LdapDataAutoConfiguration {
@Bean
@ConditionalOnMissingBean(LdapOperations.class)
public LdapTemplate ldapTemplate(ContextSource contextSource) {
return new LdapTemplate(contextSource);
}
}
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.data.ldap;
import javax.naming.ldap.LdapContext;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.ldap.repository.LdapRepository;
import org.springframework.data.ldap.repository.support.LdapRepositoryFactoryBean;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Couchbase
* Repositories.
*
* @author Eddú Meléndez
* @since 1.5.0
*/
@Configuration
@ConditionalOnClass({ LdapContext.class, LdapRepository.class })
@ConditionalOnProperty(prefix = "spring.data.ldap.repositories", name = "enabled", havingValue = "true", matchIfMissing = true)
@ConditionalOnMissingBean(LdapRepositoryFactoryBean.class)
@Import(LdapRepositoriesRegistrar.class)
public class LdapRepositoriesAutoConfiguration {
}
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.data.ldap;
import java.lang.annotation.Annotation;
import org.springframework.boot.autoconfigure.data.AbstractRepositoryConfigurationSourceSupport;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.data.ldap.repository.config.EnableLdapRepositories;
import org.springframework.data.ldap.repository.config.LdapRepositoryConfigurationExtension;
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
/**
* {@link ImportBeanDefinitionRegistrar} used to auto-configure Spring Data LDAP
* Repositories.
*
* @author Eddú Meléndez
* @since 1.5.0
*/
class LdapRepositoriesRegistrar extends AbstractRepositoryConfigurationSourceSupport {
@Override
protected Class<? extends Annotation> getAnnotation() {
return EnableLdapRepositories.class;
}
@Override
protected Class<?> getConfiguration() {
return EnableLdapRepositoriesConfiguration.class;
}
@Override
protected RepositoryConfigurationExtension getRepositoryConfigurationExtension() {
return new LdapRepositoryConfigurationExtension();
}
@EnableLdapRepositories
private static class EnableLdapRepositoriesConfiguration {
}
}
/*
* Copyright 2012-2017 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
*
* http://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.
*/
/**
* Auto-configuration for Spring Data LDAP.
*/
package org.springframework.boot.autoconfigure.data.ldap;
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.ldap;
import java.util.Collections;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.core.support.LdapContextSource;
/**
* {@link EnableAutoConfiguration Auto-configuration} for LDAP.
*
* @author Eddú Meléndez
* @since 1.5.0
*/
@Configuration
@ConditionalOnClass(ContextSource.class)
@EnableConfigurationProperties(LdapProperties.class)
public class LdapAutoConfiguration {
private final LdapProperties properties;
private final Environment environment;
public LdapAutoConfiguration(LdapProperties properties, Environment environment) {
this.properties = properties;
this.environment = environment;
}
@Bean
@ConditionalOnMissingBean
public ContextSource ldapContextSource() {
LdapContextSource source = new LdapContextSource();
source.setUserDn(this.properties.getUsername());
source.setPassword(this.properties.getPassword());
source.setBase(this.properties.getBase());
source.setUrls(this.properties.determineUrls(this.environment));
source.setBaseEnvironmentProperties(Collections
.<String, Object>unmodifiableMap(this.properties.getBaseEnvironment()));
return source;
}
}
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.ldap;
import java.util.HashMap;
import java.util.Map;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.env.Environment;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* Configuration properties to configure {@link LdapTemplate}.
*
* @author Eddú Meléndez
* @since 1.5.0
*/
@ConfigurationProperties(prefix = "spring.ldap")
public class LdapProperties {
private static final int DEFAULT_PORT = 389;
/**
* LDAP urls.
*/
private String[] urls;
/**
* Base suffix from which all operations should originate.
*/
private String base;
/**
* Login user of the LDAP.
*/
private String username;
/**
* Login password of the LDAP.
*/
private String password;
/**
* LDAP custom environment properties.
*/
private Map<String, String> baseEnvironment = new HashMap<String, String>();
public String[] getUrls() {
return this.urls;
}
public void setUrls(String[] urls) {
this.urls = urls;
}
public String getBase() {
return this.base;
}
public void setBase(String base) {
this.base = base;
}
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
public Map<String, String> getBaseEnvironment() {
return this.baseEnvironment;
}
public void setBaseEnvironment(Map<String, String> baseEnvironment) {
this.baseEnvironment = baseEnvironment;
}
public String[] determineUrls(Environment environment) {
if (ObjectUtils.isEmpty(this.urls)) {
return new String[] { "ldap://localhost:" + determinePort(environment) };
}
return this.urls;
}
private int determinePort(Environment environment) {
Assert.state(environment != null, "No local LDAP port configured");
String localPort = environment.getProperty("local.ldap.port");
if (localPort != null) {
return Integer.valueOf(localPort);
}
return DEFAULT_PORT;
}
}
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.ldap.embedded;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.PreDestroy;
import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldif.LDIFReader;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration;
import org.springframework.boot.autoconfigure.ldap.LdapProperties;
import org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapProperties.Credential;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.Resource;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.core.support.LdapContextSource;
import org.springframework.util.StringUtils;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Embedded LDAP.
*
* @author Eddú Meléndez
* @since 1.5.0
*/
@Configuration
@EnableConfigurationProperties({ LdapProperties.class, EmbeddedLdapProperties.class })
@AutoConfigureBefore(LdapAutoConfiguration.class)
@ConditionalOnClass(InMemoryDirectoryServer.class)
@ConditionalOnProperty(prefix = "spring.ldap.embedded", name = "base-dn")
public class EmbeddedLdapAutoConfiguration {
private static final String PROPERTY_SOURCE_NAME = "ldap.ports";
private final EmbeddedLdapProperties embeddedProperties;
private final LdapProperties properties;
private final ConfigurableApplicationContext applicationContext;
private final Environment environment;
private InMemoryDirectoryServer server;
public EmbeddedLdapAutoConfiguration(EmbeddedLdapProperties embeddedProperties,
LdapProperties properties, ConfigurableApplicationContext applicationContext,
Environment environment) {
this.embeddedProperties = embeddedProperties;
this.properties = properties;
this.applicationContext = applicationContext;
this.environment = environment;
}
@Bean
@DependsOn("directoryServer")
@ConditionalOnMissingBean
public ContextSource ldapContextSource() {
LdapContextSource source = new LdapContextSource();
if (hasCredentials(this.embeddedProperties.getCredential())) {
source.setUserDn(this.embeddedProperties.getCredential().getUsername());
source.setPassword(this.embeddedProperties.getCredential().getPassword());
}
source.setUrls(this.properties.determineUrls(this.environment));
return source;
}
@Bean
public InMemoryDirectoryServer directoryServer() throws LDAPException {
InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(
this.embeddedProperties.getBaseDn());
if (hasCredentials(this.embeddedProperties.getCredential())) {
config.addAdditionalBindCredentials(
this.embeddedProperties.getCredential().getUsername(),
this.embeddedProperties.getCredential().getPassword());
}
InMemoryListenerConfig listenerConfig = InMemoryListenerConfig
.createLDAPConfig("LDAP", this.embeddedProperties.getPort());
config.setListenerConfigs(listenerConfig);
this.server = new InMemoryDirectoryServer(config);
importLdif();
this.server.startListening();
setPortProperty(this.applicationContext, this.server.getListenPort());
return this.server;
}
private boolean hasCredentials(Credential credential) {
return StringUtils.hasText(credential.getUsername())
&& StringUtils.hasText(credential.getPassword());
}
private void importLdif() throws LDAPException {
String location = this.embeddedProperties.getLdif();
if (StringUtils.hasText(location)) {
try {
Resource resource = this.applicationContext.getResource(location);
if (resource.exists()) {
InputStream inputStream = resource.getInputStream();
try {
this.server.importFromLDIF(true, new LDIFReader(inputStream));
}
finally {
inputStream.close();
}
}
}
catch (Exception ex) {
throw new IllegalStateException("Unable to load LDIF " + location, ex);
}
}
}
private void setPortProperty(ApplicationContext context, int port) {
if (context instanceof ConfigurableApplicationContext) {
MutablePropertySources sources = ((ConfigurableApplicationContext) context)
.getEnvironment().getPropertySources();
getLdapPorts(sources).put("local.ldap.port", port);
}
if (context.getParent() != null) {
setPortProperty(context.getParent(), port);
}
}
@SuppressWarnings("unchecked")
private Map<String, Object> getLdapPorts(MutablePropertySources sources) {
PropertySource<?> propertySource = sources.get(PROPERTY_SOURCE_NAME);
if (propertySource == null) {
propertySource = new MapPropertySource(PROPERTY_SOURCE_NAME,
new HashMap<String, Object>());
sources.addFirst(propertySource);
}
return (Map<String, Object>) propertySource.getSource();
}
@PreDestroy
public void close() {
if (this.server != null) {
this.server.shutDown(true);
}
}
}
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.ldap.embedded;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Configuration properties for Embedded LDAP.
*
* @author Eddú Meléndez
* @since 1.5.0
*/
@ConfigurationProperties(prefix = "spring.ldap.embedded")
public class EmbeddedLdapProperties {
/**
* Embedded LDAP port.
*/
private int port = 0;
/**
* Embedded LDAP credentials.
*/
private Credential credential = new Credential();
/**
* Base DNs.
*/
private String baseDn;
/**
* Schema (LDIF) script resource reference.
*/
private String ldif = "classpath:schema.ldif";
public int getPort() {
return this.port;
}
public void setPort(int port) {
this.port = port;
}
public Credential getCredential() {
return this.credential;
}
public void setCredential(Credential credential) {
this.credential = credential;
}
public String getBaseDn() {
return this.baseDn;
}
public void setBaseDn(String baseDn) {
this.baseDn = baseDn;
}
public String getLdif() {
return this.ldif;
}
public void setLdif(String ldif) {
this.ldif = ldif;
}
static class Credential {
/**
* Embedded LDAP username.
*/
private String username;
/**
* Embedded LDAP password.
*/
private String password;
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
}
}
/*
* Copyright 2012-2017 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
*
* http://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.
*/
/**
* Auto-configuration for LDAP.
*/
package org.springframework.boot.autoconfigure.ldap;
......@@ -29,6 +29,8 @@ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfi
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
......@@ -63,6 +65,8 @@ org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfigu
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
......
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.data.alt.ldap;
import javax.naming.Name;
import org.springframework.boot.autoconfigure.data.ldap.person.Person;
import org.springframework.data.repository.Repository;
public interface PersonLdapRepository extends Repository<Person, Name> {
}
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.data.ldap;
import org.junit.After;
import org.junit.Test;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.ldap.core.LdapTemplate;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link LdapDataAutoConfiguration}
*
* @author Eddú Meléndez
*/
public class LdapDataAutoConfigurationTests {
private AnnotationConfigApplicationContext context;
@After
public void close() {
this.context.close();
}
@Test
public void templateExists() {
this.context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(this.context,
"spring.ldap.urls:ldap://localhost:389");
this.context.register(PropertyPlaceholderAutoConfiguration.class,
LdapAutoConfiguration.class, LdapDataAutoConfiguration.class);
this.context.refresh();
assertThat(this.context.getBeanNamesForType(LdapTemplate.class)).hasSize(1);
}
}
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.data.ldap;
import org.junit.After;
import org.junit.Test;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
import org.springframework.boot.autoconfigure.data.alt.ldap.PersonLdapRepository;
import org.springframework.boot.autoconfigure.data.empty.EmptyDataPackage;
import org.springframework.boot.autoconfigure.data.ldap.person.Person;
import org.springframework.boot.autoconfigure.data.ldap.person.PersonRepository;
import org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.ldap.repository.config.EnableLdapRepositories;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link LdapRepositoriesAutoConfiguration}
*
* @author Eddú Meléndez
*/
public class LdapRepositoriesAutoConfigurationTests {
private AnnotationConfigApplicationContext context;
@After
public void close() {
if (this.context != null) {
this.context.close();
}
}
@Test
public void testDefaultRepositoryConfiguration() throws Exception {
load(TestConfiguration.class);
assertThat(this.context.getBean(PersonRepository.class)).isNotNull();
}
@Test
public void testNoRepositoryConfiguration() throws Exception {
load(EmptyConfiguration.class);
assertThat(this.context.getBeanNamesForType(PersonRepository.class)).isEmpty();
}
@Test
public void doesNotTriggerDefaultRepositoryDetectionIfCustomized() {
load(CustomizedConfiguration.class);
assertThat(this.context.getBean(PersonLdapRepository.class)).isNotNull();
}
private void load(Class<?>... configurationClasses) {
this.context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(this.context,
"spring.ldap.urls:ldap://localhost:389");
this.context.register(configurationClasses);
this.context.register(LdapAutoConfiguration.class,
LdapDataAutoConfiguration.class, LdapRepositoriesAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
}
@Configuration
@TestAutoConfigurationPackage(Person.class)
protected static class TestConfiguration {
}
@Configuration
@TestAutoConfigurationPackage(EmptyDataPackage.class)
protected static class EmptyConfiguration {
}
@Configuration
@TestAutoConfigurationPackage(LdapRepositoriesAutoConfigurationTests.class)
@EnableLdapRepositories(basePackageClasses = PersonLdapRepository.class)
protected static class CustomizedConfiguration {
}
}
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.data.ldap.person;
import javax.naming.Name;
import org.springframework.ldap.odm.annotations.Attribute;
import org.springframework.ldap.odm.annotations.DnAttribute;
import org.springframework.ldap.odm.annotations.Entry;
import org.springframework.ldap.odm.annotations.Id;
@Entry(objectClasses = { "person", "top" }, base = "ou=someOu")
public class Person {
@Id
private Name dn;
@Attribute(name = "cn")
@DnAttribute(value = "cn", index = 1)
private String fullName;
}
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.data.ldap.person;
import javax.naming.Name;
import org.springframework.data.repository.Repository;
public interface PersonRepository extends Repository<Person, Name> {
}
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.ldap;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.ldap.core.ContextSource;
import org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link LdapAutoConfiguration}.
*
* @author Eddú Meléndez
*/
public class LdapAutoConfigurationTests {
private AnnotationConfigApplicationContext context;
@Before
public void setup() {
this.context = new AnnotationConfigApplicationContext();
}
@After
public void close() {
if (this.context != null) {
this.context.close();
}
}
@Test
public void testDefaultUrl() {
load();
ContextSource contextSource = this.context.getBean(ContextSource.class);
String[] urls = (String[]) ReflectionTestUtils.getField(contextSource, "urls");
assertThat(urls).containsExactly("ldap://localhost:389");
}
@Test
public void testContextSourceSetOneUrl() {
load("spring.ldap.urls:ldap://localhost:123");
ContextSource contextSource = this.context.getBean(ContextSource.class);
String[] urls = (String[]) ReflectionTestUtils.getField(contextSource, "urls");
assertThat(urls).containsExactly("ldap://localhost:123");
}
@Test
public void testContextSourceSetTwoUrls() {
load("spring.ldap.urls:ldap://localhost:123,ldap://mycompany:123");
ContextSource contextSource = this.context.getBean(ContextSource.class);
LdapProperties ldapProperties = this.context.getBean(LdapProperties.class);
String[] urls = (String[]) ReflectionTestUtils.getField(contextSource, "urls");
assertThat(urls).containsExactly("ldap://localhost:123", "ldap://mycompany:123");
assertThat(ldapProperties.getUrls()).hasSize(2);
}
@Test
public void testContextSourceWithMoreProperties() {
load("spring.ldap.urls:ldap://localhost:123", "spring.ldap.username:root",
"spring.ldap.password:root", "spring.ldap.base:cn=SpringDevelopers",
"spring.ldap.baseEnvironment.java.naming.security"
+ ".authentication:DIGEST-MD5");
LdapProperties ldapProperties = this.context.getBean(LdapProperties.class);
assertThat(ldapProperties.getBaseEnvironment())
.containsEntry("java.naming.security.authentication", "DIGEST-MD5");
}
private void load(String... properties) {
EnvironmentTestUtils.addEnvironment(this.context, properties);
this.context.register(LdapAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
}
}
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.ldap.embedded;
import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.sdk.BindResult;
import com.unboundid.ldap.sdk.DN;
import com.unboundid.ldap.sdk.LDAPConnection;
import com.unboundid.ldap.sdk.LDAPException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration;
import org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ldap.core.LdapTemplate;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link EmbeddedLdapAutoConfiguration}
*
* @author Eddú Meléndez
*/
public class EmbeddedLdapAutoConfigurationTests {
private AnnotationConfigApplicationContext context;
@Before
public void setup() {
this.context = new AnnotationConfigApplicationContext();
}
@After
public void close() {
if (this.context != null) {
this.context.close();
}
}
@Test
public void testSetDefaultPort() throws LDAPException {
load("spring.ldap.embedded.port:1234",
"spring.ldap.embedded.base-dn:dc=spring,dc=org");
InMemoryDirectoryServer server = this.context
.getBean(InMemoryDirectoryServer.class);
assertThat(server.getListenPort()).isEqualTo(1234);
}
@Test
public void testRandomPortWithEnvironment() throws LDAPException {
load("spring.ldap.embedded.base-dn:dc=spring,dc=org");
InMemoryDirectoryServer server = this.context
.getBean(InMemoryDirectoryServer.class);
assertThat(server.getListenPort()).isEqualTo(this.context.getEnvironment()
.getProperty("local.ldap.port", Integer.class));
}
@Test
public void testRandomPortWithValueAnnotation() throws LDAPException {
EnvironmentTestUtils.addEnvironment(this.context,
"spring.ldap.embedded.base-dn:dc=spring,dc=org");
this.context.register(EmbeddedLdapAutoConfiguration.class,
LdapClientConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
LDAPConnection connection = this.context.getBean(LDAPConnection.class);
assertThat(connection.getConnectedPort()).isEqualTo(this.context.getEnvironment()
.getProperty("local.ldap.port", Integer.class));
}
@Test
public void testSetCredentials() throws LDAPException {
load("spring.ldap.embedded.base-dn:dc=spring,dc=org",
"spring.ldap.embedded.credential.username:uid=root",
"spring.ldap.embedded.credential.password:boot");
InMemoryDirectoryServer server = this.context
.getBean(InMemoryDirectoryServer.class);
BindResult result = server.bind("uid=root", "boot");
assertThat(result).isNotNull();
}
@Test
public void testSetPartitionSuffix() throws LDAPException {
load("spring.ldap.embedded.base-dn:dc=spring,dc=org");
InMemoryDirectoryServer server = this.context
.getBean(InMemoryDirectoryServer.class);
assertThat(server.getBaseDNs()).containsExactly(new DN("dc=spring,dc=org"));
}
@Test
public void testSetLdifFile() throws LDAPException {
load("spring.ldap.embedded.base-dn:dc=spring,dc=org");
InMemoryDirectoryServer server = this.context
.getBean(InMemoryDirectoryServer.class);
assertThat(server.countEntriesBelow("ou=company1,c=Sweden,dc=spring,dc=org"))
.isEqualTo(5);
}
@Test
public void testQueryEmbeddedLdap() throws LDAPException {
EnvironmentTestUtils.addEnvironment(this.context,
"spring.ldap.embedded.base-dn:dc=spring,dc=org");
this.context.register(EmbeddedLdapAutoConfiguration.class,
LdapAutoConfiguration.class, LdapDataAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
assertThat(this.context.getBeanNamesForType(LdapTemplate.class).length)
.isEqualTo(1);
LdapTemplate ldapTemplate = this.context.getBean(LdapTemplate.class);
assertThat(ldapTemplate.list("ou=company1,c=Sweden,dc=spring,dc=org")).hasSize(4);
}
private void load(String... properties) {
EnvironmentTestUtils.addEnvironment(this.context, properties);
this.context.register(EmbeddedLdapAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
}
@Configuration
static class LdapClientConfiguration {
@Bean
public LDAPConnection ldapConnection(@Value("${local.ldap.port}") int port)
throws LDAPException {
LDAPConnection con = new LDAPConnection();
con.connect("localhost", port);
return con;
}
}
}
dn: dc=spring,dc=org
objectclass: top
objectclass: domain
objectclass: extensibleObject
dc: spring
dn: ou=groups,dc=spring,dc=org
objectclass: top
objectclass: organizationalUnit
ou: groups
dn: cn=ROLE_USER,ou=groups,dc=spring,dc=org
objectclass: top
objectclass: groupOfUniqueNames
cn: ROLE_USER
uniqueMember: cn=Some Person,ou=company1,c=Sweden,dc=spring,dc=org
uniqueMember: cn=Some Person2,ou=company1,c=Sweden,dc=spring,dc=org
uniqueMember: cn=Some Person,ou=company1,c=Sweden,dc=spring,dc=org
uniqueMember: cn=Some Person3,ou=company1,c=Sweden,dc=spring,dc=org
dn: cn=ROLE_ADMIN,ou=groups,dc=spring,dc=org
objectclass: top
objectclass: groupOfUniqueNames
cn: ROLE_ADMIN
uniqueMember: cn=Some Person2,ou=company1,c=Sweden,dc=spring,dc=org
dn: c=Sweden,dc=spring,dc=org
objectclass: top
objectclass: country
c: Sweden
description: The country of Sweden
dn: ou=company1,c=Sweden,dc=spring,dc=org
objectclass: top
objectclass: organizationalUnit
ou: company1
description: First company in Sweden
dn: cn=Some Person,ou=company1,c=Sweden,dc=spring,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: some.person
userPassword: password
cn: Some Person
sn: Person
description: Sweden, Company1, Some Person
telephoneNumber: +46 555-123456
dn: cn=Some Person2,ou=company1,c=Sweden,dc=spring,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: some.person2
userPassword: password
cn: Some Person2
sn: Person2
description: Sweden, Company1, Some Person2
telephoneNumber: +46 555-654321
dn: cn=Some Person3,ou=company1,c=Sweden,dc=spring,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: some.person3
userPassword: password
cn: Some Person3
sn: Person3
description: Sweden, Company1, Some Person3
telephoneNumber: +46 555-123654
dn: cn=Some Person4,ou=company1,c=Sweden,dc=spring,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: some.person4
userPassword: password
cn: Some Person
sn: Person
description: Sweden, Company1, Some Person
telephoneNumber: +46 555-456321
......@@ -181,6 +181,7 @@
<thymeleaf-extras-java8time.version>2.1.0.RELEASE</thymeleaf-extras-java8time.version>
<tomcat.version>8.5.6</tomcat.version>
<undertow.version>1.4.8.Final</undertow.version>
<unboundid-ldapsdk.version>3.2.0</unboundid-ldapsdk.version>
<webjars-hal-browser.version>9f96c74</webjars-hal-browser.version>
<webjars-locator.version>0.32</webjars-locator.version>
<wsdl4j.version>1.6.3</wsdl4j.version>
......@@ -335,6 +336,11 @@
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-ldap</artifactId>
<version>1.5.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
......@@ -784,6 +790,11 @@
<artifactId>java-statsd-client</artifactId>
<version>${statsd-client.version}</version>
</dependency>
<dependency>
<groupId>com.unboundid</groupId>
<artifactId>unboundid-ldapsdk</artifactId>
<version>${unboundid-ldapsdk.version}</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
......
......@@ -314,6 +314,20 @@ content into your application; rather pick only the properties that you need.
spring.jersey.servlet.load-on-startup=-1 # Load on startup priority of the Jersey servlet.
spring.jersey.type=servlet # Jersey integration type.
# SPRING LDAP ({sc-spring-boot-autoconfigure}/ldap/LdapProperties.{sc-ext}[LdapProperties])
spring.ldap.urls= # LDAP url of the server.
spring.ldap.base= # Base suffix from which all operations should originate.
spring.ldap.username= # Login user of the server.
spring.ldap.password= # Login password of the server.
spring.ldap.base-environment.*= # Ldap specification settings.
# EMBEDDED LDAP ({sc-spring-boot-autoconfigure}/ldap/embedded/EmbeddedLdapProperties.{sc-ext}[EmbeddedLdapProperties])
spring.ldap.embedded.port= # Embedded LDAP port.
spring.ldap.embedded.credential.username= # Embedded LDAP username.
spring.ldap.embedded.credential.password= # Embedded LDAP password.
spring.ldap.embedded.base-dn= # The base DN
spring.ldap.embedded.ldif= # Schema (LDIF) script resource reference.
# SPRING MOBILE DEVICE VIEWS ({sc-spring-boot-autoconfigure}/mobile/DeviceDelegatingViewResolverAutoConfiguration.{sc-ext}[DeviceDelegatingViewResolverAutoConfiguration])
spring.mobile.devicedelegatingviewresolver.enable-fallback=false # Enable support for fallback resolution.
spring.mobile.devicedelegatingviewresolver.enabled=false # Enable device view resolver.
......
......@@ -3203,11 +3203,12 @@ https://github.com/spring-projects/spring-data-elasticsearch/[Elasticsearch],
http://projects.spring.io/spring-data-solr/[Solr],
http://projects.spring.io/spring-data-redis/[Redis],
http://projects.spring.io/spring-data-gemfire/[Gemfire],
http://projects.spring.io/spring-data-cassandra/[Cassandra],
http://projects.spring.io/spring-data-couchbase/[Couchbase] and
http://projects.spring.io/spring-data-cassandra/[Cassandra].
http://projects.spring.io/spring-data-ldap/[LDAP].
Spring Boot provides auto-configuration for Redis, MongoDB, Neo4j, Elasticsearch, Solr
and Cassandra; you can make use of the other projects, but you will need to configure
them yourself. Refer to the appropriate reference documentation at
Cassandra, Couchbase and LDAP; you can make use of the other projects, but you will need
to configure them yourself. Refer to the appropriate reference documentation at
http://projects.spring.io/spring-data[projects.spring.io/spring-data].
......@@ -3746,6 +3747,7 @@ TIP: For complete details of Spring Data Cassandra, refer to their
http://docs.spring.io/spring-data/cassandra/docs/[reference documentation].
[[boot-features-couchbase]]
=== Couchbase
http://www.couchbase.com/[Couchbase] is an open-source, distributed multi-model NoSQL
......@@ -3853,6 +3855,89 @@ implementation.
[[boot-features-ldap]]
=== LDAP
https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol[LDAP] (Lightweight
Directory Access Protocol) is an is an open, vendor-neutral, industry standard application
protocol for accessing and maintaining distributed directory information services over an
IP network. Spring Boot offers auto-configuration for any compliant LDAP server as well
as support for the embedded in-memory LDAP server from
https://www.ldap.com/unboundid-ldap-sdk-for-java[Unbounded].
LDAP abstractions are provided by
https://github.com/spring-projects/spring-data-ldap[Spring Data LDAP].
There is a `spring-boot-starter-data-ldap` '`Starter`' for collecting the dependencies in
a convenient way.
[[boot-features-ldap-connecting]]
==== Connecting to an LDAP server
To connect to an LDAP server make sure you declare a dependency on the
`spring-boot-starter-data-ldap` '`Starter`' or `spring-ldap-core` then declare the
URLs of your server in your application.properties:
[source,properties,indent=0]
----
spring.ldap.urls=ldap://myserver:1235
spring.ldap.username=admin
spring.ldap.password=secret
----
If you need to customize connection settings you can use the `spring.ldap.base` and
`spring.ldap.base-environment` properties.
[[boot-features-ldap-spring-data-repositories]]
==== Spring Data LDAP repositories
Spring Data includes repository support for LDAP. For complete details of Spring
Data LDAP, refer to their
http://docs.spring.io/spring-data/ldap/docs/1.0.x/reference/html/[reference documentation].
You can also inject an auto-configured `LdapTemplate` instance as you would with any
other Spring Bean.
[source,java,indent=0]
----
@Component
public class MyBean {
private final LdapTemplate template;
@Autowired
public MyBean(LdapTemplate template) {
this.template = template;
}
// ...
}
----
[[boot-features-ldap-embedded]]
==== Embedded in-memory LDAP server
For testing purposes Spring Boot supports auto-configuration of an in-memory LDAP server
from https://www.ldap.com/unboundid-ldap-sdk-for-java[Unbounded]. To configure the server
add a dependency to `com.unboundid:unboundid-ldapsdk` and declare a `base-dn` property:
[source,properties,indent=0]
----
spring.ldap.embedded.base-dn=dc=spring,dc=io
----
By default the server will start on a random port and the trigger the regular LDAP support
(there is not need to specify a `spring.ldap.urls` property).
If there is a `schema.ldif` file on your classpath it will be used to initialize the
server. You can also use the `spring.ldap.embedded.ldif` property if you want to load
the initialization script from a different resource.
[[boot-features-caching]]
== Caching
The Spring Framework provides support for transparently adding caching to an application.
......
......@@ -37,6 +37,7 @@
<module>spring-boot-sample-data-couchbase</module>
<module>spring-boot-sample-data-elasticsearch</module>
<module>spring-boot-sample-data-jpa</module>
<module>spring-boot-sample-data-ldap</module>
<module>spring-boot-sample-data-mongodb</module>
<module>spring-boot-sample-data-neo4j</module>
<module>spring-boot-sample-data-redis</module>
......@@ -112,6 +113,7 @@
<module>spring-boot-sample-websocket-undertow</module>
<module>spring-boot-sample-webservices</module>
<module>spring-boot-sample-xml</module>
<module>spring-boot-sample-hypermedia-ui-secure</module>
</modules>
<!-- No dependencies - otherwise the samples won't work if you change the
parent -->
......
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<!-- Your own application should inherit from spring-boot-starter-parent -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-samples</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
</parent>
<artifactId>spring-boot-sample-data-ldap</artifactId>
<name>Spring Boot Data LDAP Sample</name>
<description>Spring Boot Data LDAP Sample</description>
<url>http://projects.spring.io/spring-boot/</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>http://www.spring.io</url>
</organization>
<properties>
<main.basedir>${basedir}/../..</main.basedir>
</properties>
<dependencies>
<!-- Compile -->
<dependency>
<groupId>com.unboundid</groupId>
<artifactId>unboundid-ldapsdk</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-ldap</artifactId>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
/*
* Copyright 2012-2017 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
*
* http://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 sample.data.ldap;
import javax.naming.Name;
import org.springframework.ldap.odm.annotations.Attribute;
import org.springframework.ldap.odm.annotations.Entry;
import org.springframework.ldap.odm.annotations.Id;
@Entry(objectClasses = { "person", "top" })
public class Person {
@Id
private Name dn;
@Attribute(name = "telephoneNumber")
private String phone;
@Override
public String toString() {
return String.format("Customer[dn=%s, phone='%s']", this.dn, this.phone);
}
}
/*
* Copyright 2012-2017 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
*
* http://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 sample.data.ldap;
import org.springframework.data.ldap.repository.LdapRepository;
public interface PersonRepository extends LdapRepository<Person> {
Person findByPhone(String phone);
}
/*
* Copyright 2012-2017 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
*
* http://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 sample.data.ldap;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SampleLdapApplication implements CommandLineRunner {
private final PersonRepository repository;
public SampleLdapApplication(PersonRepository repository) {
this.repository = repository;
}
@Override
public void run(String... args) throws Exception {
// fetch all people
System.out.println("People found with findAll():");
System.out.println("-------------------------------");
for (Person person : this.repository.findAll()) {
System.out.println(person);
}
System.out.println();
// fetch an individual person
System.out.println("Person found with findByPhone('+46 555-123456'):");
System.out.println("--------------------------------");
System.out.println(this.repository.findByPhone("+46 555-123456"));
//
// System.out.println("Customers found with findByLastName('Smith'):");
// System.out.println("--------------------------------");
// for (Customer customer : this.repository.findByLastName("Smith")) {
// System.out.println(customer);
// }
}
public static void main(String[] args) throws Exception {
SpringApplication.run(SampleLdapApplication.class, args).close();
}
}
dn: dc=spring,dc=org
objectclass: top
objectclass: domain
objectclass: extensibleObject
dc: spring
dn: ou=groups,dc=spring,dc=org
objectclass: top
objectclass: organizationalUnit
ou: groups
dn: cn=ROLE_USER,ou=groups,dc=spring,dc=org
objectclass: top
objectclass: groupOfUniqueNames
cn: ROLE_USER
uniqueMember: cn=Some Person,ou=company1,c=Sweden,dc=spring,dc=org
uniqueMember: cn=Some Person2,ou=company1,c=Sweden,dc=spring,dc=org
uniqueMember: cn=Some Person,ou=company1,c=Sweden,dc=spring,dc=org
uniqueMember: cn=Some Person3,ou=company1,c=Sweden,dc=spring,dc=org
dn: cn=ROLE_ADMIN,ou=groups,dc=spring,dc=org
objectclass: top
objectclass: groupOfUniqueNames
cn: ROLE_ADMIN
uniqueMember: cn=Some Person2,ou=company1,c=Sweden,dc=spring,dc=org
dn: c=Sweden,dc=spring,dc=org
objectclass: top
objectclass: country
c: Sweden
description: The country of Sweden
dn: ou=company1,c=Sweden,dc=spring,dc=org
objectclass: top
objectclass: organizationalUnit
ou: company1
description: First company in Sweden
dn: cn=Alice Smith,ou=company1,c=Sweden,dc=spring,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: alice.smith
userPassword: password
cn: Alice Smith
sn: Alice Smith
description: Sweden, Company1, Alice Smith
telephoneNumber: +46 555-123456
dn: cn=Bob Smith,ou=company1,c=Sweden,dc=spring,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: bob.smith
userPassword: password
cn: Bob Smith
sn: Bob Smith
description: Sweden, Company1, Some Person2
telephoneNumber: +46 555-654321
/*
* Copyright 2012-2017 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
*
* http://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 sample.data.ldap;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.rule.OutputCapture;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link SampleLdapApplication}.
*
* @author Phillip Webb
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class SampleLdapApplicationTests {
@ClassRule
public static OutputCapture outputCapture = new OutputCapture();
@Test
public void testDefaultSettings() throws Exception {
String output = outputCapture.toString();
assertThat(output).contains("cn=Alice Smith");
}
}
......@@ -60,4 +60,11 @@ public class SampleDevToolsApplicationIntegrationTests {
assertThat(entity.getBody()).contains("public file");
}
@Test
public void testClassResource() throws Exception {
ResponseEntity<String> entity = this.restTemplate
.getForEntity("/application.properties", String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-boot-samples</artifactId>
<groupId>org.springframework.boot</groupId>
<version>1.5.0.BUILD-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-boot-sample-hypermedia-ui-secure</artifactId>
<name>Spring Boot Hypermedia UI Secure Sample</name>
<description>Spring Boot Hypermedia UI Secure Sample</description>
<properties>
<main.basedir>${basedir}/../..</main.basedir>
</properties>
<dependencies>
<!-- Compile -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-docs</artifactId>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
/*
* Copyright 2012-2017 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
*
* http://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 sample.hypermedia.ui.secure;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SampleHypermediaUiSecureApplication {
public static void main(String[] args) {
SpringApplication.run(SampleHypermediaUiSecureApplication.class, args);
}
}
<html>
<body>
<h1>Hello World!</h1>
</body>
</html>
\ No newline at end of file
/*
* Copyright 2012-2017 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
*
* http://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 sample.hypermedia.ui.secure;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {
"endpoints.env.sensitive=false" })
public class SampleHypermediaUiSecureApplicationTests {
@Autowired
private TestRestTemplate restTemplate;
@Test
public void links() {
String response = this.restTemplate.getForObject("/actuator", String.class);
assertThat(response).contains("\"_links\":");
}
@Test
public void testInSecureNestedPath() throws Exception {
ResponseEntity<String> entity = this.restTemplate.getForEntity("/env",
String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
ResponseEntity<String> user = this.restTemplate.getForEntity("/env/user",
String.class);
assertThat(user.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(user.getBody()).contains("{\"user\":");
}
@Test
public void testSecurePath() throws Exception {
ResponseEntity<String> entity = this.restTemplate.getForEntity("/metrics",
String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
}
}
/*
* Copyright 2012-2017 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
*
* http://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 sample.hypermedia.ui.secure;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {
"management.context-path=/admin" })
public class SampleHypermediaUiSecureApplicationWithContextPathTests {
@Autowired
private TestRestTemplate restTemplate;
@Test
public void links() {
String response = this.restTemplate.getForObject("/admin", String.class);
assertThat(response).contains("\"_links\":");
}
@Test
public void testSecurePath() throws Exception {
ResponseEntity<String> entity = this.restTemplate.getForEntity("/admin/metrics",
String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
}
}
......@@ -32,6 +32,7 @@
<module>spring-boot-starter-data-couchbase</module>
<module>spring-boot-starter-data-elasticsearch</module>
<module>spring-boot-starter-data-jpa</module>
<module>spring-boot-starter-data-ldap</module>
<module>spring-boot-starter-data-mongodb</module>
<module>spring-boot-starter-data-neo4j</module>
<module>spring-boot-starter-data-redis</module>
......
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>spring-boot-starters</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.0.0.BUILD-SNAPSHOT</version>
</parent>
<artifactId>spring-boot-starter-data-ldap</artifactId>
<name>Spring Boot Data LDAP Starter</name>
<description>Starter for using Spring Data LDAP</description>
<url>http://projects.spring.io/spring-boot/</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>http://www.spring.io</url>
</organization>
<properties>
<main.basedir>${basedir}/../..</main.basedir>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-ldap</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.basepom.maven</groupId>
<artifactId>duplicate-finder-maven-plugin</artifactId>
<executions>
<execution>
<id>duplicate-dependencies</id>
<phase>validate</phase>
<goals>
<goal>check</goal>
</goals>
<configuration>
<ignoredResourcePatterns>
<ignoredResourcePattern>changelog.txt</ignoredResourcePattern>
</ignoredResourcePatterns>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment