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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -257,10 +257,11 @@ public class ManagementWebSecurityAutoConfiguration { ...@@ -257,10 +257,11 @@ public class ManagementWebSecurityAutoConfiguration {
private void configurePermittedRequests( private void configurePermittedRequests(
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry requests) { ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry requests) {
requests.requestMatchers(new LazyEndpointPathRequestMatcher(
this.contextResolver, EndpointPaths.SENSITIVE)).authenticated();
// Permit access to the non-sensitive endpoints // Permit access to the non-sensitive endpoints
requests.requestMatchers(new LazyEndpointPathRequestMatcher( requests.requestMatchers(new LazyEndpointPathRequestMatcher(
this.contextResolver, EndpointPaths.NON_SENSITIVE)).permitAll(); this.contextResolver, EndpointPaths.NON_SENSITIVE)).permitAll();
requests.anyRequest().authenticated();
} }
} }
...@@ -276,6 +277,15 @@ public class ManagementWebSecurityAutoConfiguration { ...@@ -276,6 +277,15 @@ public class ManagementWebSecurityAutoConfiguration {
return !endpoint.isSensitive(); return !endpoint.isSensitive();
} }
},
SENSITIVE {
@Override
protected boolean isIncluded(MvcEndpoint endpoint) {
return endpoint.isSensitive();
}
}; };
public String[] getPaths(EndpointHandlerMapping endpointHandlerMapping) { public String[] getPaths(EndpointHandlerMapping endpointHandlerMapping) {
...@@ -289,12 +299,9 @@ public class ManagementWebSecurityAutoConfiguration { ...@@ -289,12 +299,9 @@ public class ManagementWebSecurityAutoConfiguration {
String path = endpointHandlerMapping.getPath(endpoint.getPath()); String path = endpointHandlerMapping.getPath(endpoint.getPath());
paths.add(path); paths.add(path);
if (!path.equals("")) { if (!path.equals("")) {
if (endpoint.isSensitive()) { paths.add(path + "/**");
// Ensure that nested paths are secured // Add Spring MVC-generated additional paths
paths.add(path + "/**"); paths.add(path + ".*");
// Add Spring MVC-generated additional paths
paths.add(path + ".*");
}
} }
paths.add(path + "/"); paths.add(path + "/");
} }
......
...@@ -234,6 +234,11 @@ ...@@ -234,6 +234,11 @@
<artifactId>sendgrid-java</artifactId> <artifactId>sendgrid-java</artifactId>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency>
<groupId>com.unboundid</groupId>
<artifactId>unboundid-ldapsdk</artifactId>
<optional>true</optional>
</dependency>
<dependency> <dependency>
<groupId>com.zaxxer</groupId> <groupId>com.zaxxer</groupId>
<artifactId>HikariCP-java6</artifactId> <artifactId>HikariCP-java6</artifactId>
...@@ -382,6 +387,11 @@ ...@@ -382,6 +387,11 @@
<artifactId>spring-data-cassandra</artifactId> <artifactId>spring-data-cassandra</artifactId>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-ldap</artifactId>
<optional>true</optional>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.data</groupId> <groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId> <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 ...@@ -29,6 +29,8 @@ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfi
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\ 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.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
...@@ -63,6 +65,8 @@ org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfigu ...@@ -63,6 +65,8 @@ org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfigu
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\ org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\ org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\ 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.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\ org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\ 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 @@ ...@@ -181,6 +181,7 @@
<thymeleaf-extras-java8time.version>2.1.0.RELEASE</thymeleaf-extras-java8time.version> <thymeleaf-extras-java8time.version>2.1.0.RELEASE</thymeleaf-extras-java8time.version>
<tomcat.version>8.5.6</tomcat.version> <tomcat.version>8.5.6</tomcat.version>
<undertow.version>1.4.8.Final</undertow.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-hal-browser.version>9f96c74</webjars-hal-browser.version>
<webjars-locator.version>0.32</webjars-locator.version> <webjars-locator.version>0.32</webjars-locator.version>
<wsdl4j.version>1.6.3</wsdl4j.version> <wsdl4j.version>1.6.3</wsdl4j.version>
...@@ -335,6 +336,11 @@ ...@@ -335,6 +336,11 @@
<artifactId>spring-boot-starter-data-jpa</artifactId> <artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version> <version>2.0.0.BUILD-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-ldap</artifactId>
<version>1.5.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId> <artifactId>spring-boot-starter-data-mongodb</artifactId>
...@@ -784,6 +790,11 @@ ...@@ -784,6 +790,11 @@
<artifactId>java-statsd-client</artifactId> <artifactId>java-statsd-client</artifactId>
<version>${statsd-client.version}</version> <version>${statsd-client.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.unboundid</groupId>
<artifactId>unboundid-ldapsdk</artifactId>
<version>${unboundid-ldapsdk.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.zaxxer</groupId> <groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId> <artifactId>HikariCP</artifactId>
......
...@@ -314,6 +314,20 @@ content into your application; rather pick only the properties that you need. ...@@ -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.servlet.load-on-startup=-1 # Load on startup priority of the Jersey servlet.
spring.jersey.type=servlet # Jersey integration type. 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 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.enable-fallback=false # Enable support for fallback resolution.
spring.mobile.devicedelegatingviewresolver.enabled=false # Enable device view resolver. spring.mobile.devicedelegatingviewresolver.enabled=false # Enable device view resolver.
......
...@@ -3203,11 +3203,12 @@ https://github.com/spring-projects/spring-data-elasticsearch/[Elasticsearch], ...@@ -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-solr/[Solr],
http://projects.spring.io/spring-data-redis/[Redis], http://projects.spring.io/spring-data-redis/[Redis],
http://projects.spring.io/spring-data-gemfire/[Gemfire], 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-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 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 Cassandra, Couchbase and LDAP; you can make use of the other projects, but you will need
them yourself. Refer to the appropriate reference documentation at to configure them yourself. Refer to the appropriate reference documentation at
http://projects.spring.io/spring-data[projects.spring.io/spring-data]. 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 ...@@ -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]. http://docs.spring.io/spring-data/cassandra/docs/[reference documentation].
[[boot-features-couchbase]] [[boot-features-couchbase]]
=== Couchbase === Couchbase
http://www.couchbase.com/[Couchbase] is an open-source, distributed multi-model NoSQL http://www.couchbase.com/[Couchbase] is an open-source, distributed multi-model NoSQL
...@@ -3853,6 +3855,89 @@ implementation. ...@@ -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]] [[boot-features-caching]]
== Caching == Caching
The Spring Framework provides support for transparently adding caching to an application. The Spring Framework provides support for transparently adding caching to an application.
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
<module>spring-boot-sample-data-couchbase</module> <module>spring-boot-sample-data-couchbase</module>
<module>spring-boot-sample-data-elasticsearch</module> <module>spring-boot-sample-data-elasticsearch</module>
<module>spring-boot-sample-data-jpa</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-mongodb</module>
<module>spring-boot-sample-data-neo4j</module> <module>spring-boot-sample-data-neo4j</module>
<module>spring-boot-sample-data-redis</module> <module>spring-boot-sample-data-redis</module>
...@@ -112,6 +113,7 @@ ...@@ -112,6 +113,7 @@
<module>spring-boot-sample-websocket-undertow</module> <module>spring-boot-sample-websocket-undertow</module>
<module>spring-boot-sample-webservices</module> <module>spring-boot-sample-webservices</module>
<module>spring-boot-sample-xml</module> <module>spring-boot-sample-xml</module>
<module>spring-boot-sample-hypermedia-ui-secure</module>
</modules> </modules>
<!-- No dependencies - otherwise the samples won't work if you change the <!-- No dependencies - otherwise the samples won't work if you change the
parent --> 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 { ...@@ -60,4 +60,11 @@ public class SampleDevToolsApplicationIntegrationTests {
assertThat(entity.getBody()).contains("public file"); 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 @@ ...@@ -32,6 +32,7 @@
<module>spring-boot-starter-data-couchbase</module> <module>spring-boot-starter-data-couchbase</module>
<module>spring-boot-starter-data-elasticsearch</module> <module>spring-boot-starter-data-elasticsearch</module>
<module>spring-boot-starter-data-jpa</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-mongodb</module>
<module>spring-boot-starter-data-neo4j</module> <module>spring-boot-starter-data-neo4j</module>
<module>spring-boot-starter-data-redis</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