Spring访问配置 - 使用@Value

时间:2016-04-20 21:23:15

标签: spring spring-security properties spring-boot spring-annotations

我正在使用Spring Security实现ldap身份验证。当我在以下配置类中对所有ldap服务器信息进行硬编码时,它可以正常工作。

//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 个答案:

答案 0 :(得分: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;

来自Spring In Action第四版的书:

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

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

编辑:使用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());
    }
}