Reputation: 1657
I am implementing ldap authentication using Spring Security. It works when I hardcode all the ldap server information in following configuration class.
//WebSecurityConfig.java
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin();
}
@Configuration
protected static class AuthenticationConfiguration extends
GlobalAuthenticationConfigurerAdapter {
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource("ldap://ldap.mdanderson.edu:389/dc=mdanderson,dc=edu");
contextSource.setUserDn("cn=ris_flow,ou=service accounts,ou=institution,ou=service accounts,dc=mdanderson,dc=edu");
contextSource.setPassword("xxxyyyzzz");
contextSource.setReferral("follow");
contextSource.afterPropertiesSet();
LdapAuthenticationProviderConfigurer<AuthenticationManagerBuilder> ldapAuthenticationProviderConfigurer = auth.ldapAuthentication();
ldapAuthenticationProviderConfigurer
.userDnPatterns("cn={0},ou=institution,ou=people")
.userSearchBase("")
.contextSource(contextSource);
}
}
}
I decided to put these server information in application.properties and set the variables using @Value in my config class, so I add the following right before AuthenticationConfiguration
.
@Value("${ldap.contextSource.url")
private static String url;
@Value("${ldap.contextSource.managerDn")
private static String userDn;
@Value("${ldap.contextSource.managerPass")
private static String userPass;
And replaced the lines of contextSource to:
DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(url);
contextSource.setUserDn(userDn);
contextSource.setPassword(userPass);
However when I ran it again, the application failed to start with errors below:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource.......
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate....
Caused by: java.lang.IllegalArgumentException: An LDAP connection URL must be supplied.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource....
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate....
Caused by: org.springframework.security.config.annotation.AlreadyBuiltException: This object has already been built
What did I do wrong?
Upvotes: 0
Views: 925
Reputation: 1176
Check this piece of code
@Value("${ldap.contextSource.url")
private static String url;
@Value("${ldap.contextSource.managerDn")
private static String userDn;
@Value("${ldap.contextSource.managerPass")
private static String userPass;
You need to close the brackets properly this way
@Value("${ldap.contextSource.url}") private static String url;
@Value("${ldap.contextSource.managerDn}") private static String userDn;
@Value("${ldap.contextSource.managerPass}") private static String userPass;
From Spring In Action Fourth Edition book:
When relying on component-scanning and autowiring to create and initialize your
application components, there’s no configuration file or class where you can specify the placeholders. Instead, you can use the @Value annotation in much the same way as you might use the @Autowired annotation.
In order to use placeholder values, you must configure either a PropertyPlaceholderConfigurer
bean or a PropertySourcesPlaceholderConfigurer
bean. Starting with Spring 3.1, PropertySourcesPlaceholderConfigurer
is preferred because it resolves placeholders against the Spring Environment and its set of property sources.
The following @Bean method configures PropertySourcesPlaceholderConfigurer
in Java configuration:
@Bean
public
static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
EDIT: Complete example accesing properties using SPRING 4.2.5 RELEASE
Configuration Class:
@Configuration
@ComponentScan
@PropertySource("classpath:/your/package/example.properties")
// In my case, this package is stored in src/main/resources folder, which is in the classpath of the application
public class SpringPropertiesConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
Component (Bean) accessing the properties:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class ComponentAccessingProperties {
@Value("${first.property}")
private String propertyOne;
@Value("${second.property}")
private String propertyTwo;
public String getPropertyOne() {
return propertyOne;
}
public String getPropertyTwo() {
return propertyTwo;
}
}
Example properties file (/your/package/example.properties):
first.property=ONE
second.property=SECOND
Test Class:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import your.package.ComponentAccessingProperties;
import your.package.SpringPropertiesConfig;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringPropertiesConfig.class)
public class TestAccessingProperties {
@Autowired
private ComponentAccessingProperties componentAccesingProperties;
@Test
public void shouldNotBeNull() {
assertNotNull(componentAccesingProperties);
}
@Test
public void checkProperties() {
assertEquals("ONE", componentAccesingProperties.getPropertyOne());
assertEquals("SECOND", componentAccesingProperties.getPropertyTwo());
}
}
Upvotes: 1