0

我正在使用Spring Security实施ldap身份验证。当我在以下配置类中对所有ldap服务器信息进行硬编码时,它工作正常。Spring访问配置 - 使用@Value设置变量时发生AlreadyBuiltException

//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); 
     } 
    } 
} 

我决定把在application.properties这些服务器的信息,并在我的配置类使用@Value设置的变量,所以我添加下面的权利之前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; 

和更换好的ContextSource到行:

DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(url); 
    contextSource.setUserDn(userDn); 
    contextSource.setPassword(userPass); 

但是当我再次运行它,应用程序未能启动下面的错误:

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 

我做了什么错?

回答

1

检查这段代码

@Value("${ldap.contextSource.url") 
private static String url; 
    @Value("${ldap.contextSource.managerDn") 
private static String userDn; 
    @Value("${ldap.contextSource.managerPass") 
private static String userPass; 

你需要这样正确关闭括号

@Value("${ldap.contextSource.url}") private static String url; 
@Value("${ldap.contextSource.managerDn}") private static String userDn; 
@Value("${ldap.contextSource.managerPass}") private static String userPass; 

从春天在行动第四版书:

依靠当组件扫描和自动装配来创建和初始化您的应用程序c组件,没有可以指定占位符的配置文件或类。相反,您可以像使用@Autowired注释一样使用@Value批注。 为了使用占位符值,您必须配置一个PropertyPlaceholderConfigurer bean或PropertySourcesPlaceholderConfigurer bean。从Spring 3.1开始,PropertySourcesPlaceholderConfigurer是首选,因为它解析了Spring环境及其属性资源集的占位符。 以下@Bean方法配置PropertySourcesPlaceholderConfigurer 在Java配置:

@Bean 
public 
static PropertySourcesPlaceholderConfigurer placeholderConfigurer() { 
    return new PropertySourcesPlaceholderConfigurer(); 
} 

编辑:完整示例accesing使用SPRING 4.2.5 RELEASE

配置类属性:

@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(); 
    } 
} 

访问属性的组件(Bean):

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; 
    } 

} 

实例属性文件(/your/package/example.properties):

first.property=ONE 
second.property=SECOND 

测试类:

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()); 
    } 
} 
+0

似乎并没有帮助,还相同的错误。 – Nasreddin

+0

看我的编辑。更改$# – Jorge

+0

不幸的是仍然是相同的 – Nasreddin