maven – 测试和生产环境中的Spring Security

我想在两个环境中运行Spring Security,一个测试环境和一个生产环境.

我尝试了生产环境的配置:

@Configuration
@EnableWebSecurity
@ComponentScan(basePackages = { "com.thalasoft.learnintouch.rest.security" })
@Import({ WebSecurityInitializer.class })
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    private static Logger logger = LoggerFactory.getLogger(WebSecurityConfiguration.class);

    @Autowired
    CustomAuthenticationProvider customAuthenticationProvider;

    @Autowired
    RestAuthenticationEntryPoint restAuthenticationEntryPoint;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(customAuthenticationProvider);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        .csrf().disable()
        .httpBasic()
        .authenticationEntryPoint(restAuthenticationEntryPoint)
        .and()
        .authorizeRequests()
        .antMatchers("/**").hasRole("ADMIN")
        .anyRequest().authenticated();
    }

}

一个用于集成测试环境:

@Configuration
@EnableWebSecurity
@ComponentScan(basePackages = { "com.thalasoft.learnintouch.rest.security" })
@Import({ WebSecurityInitializer.class })
public class WebSecurityTestConfiguration extends WebSecurityConfigurerAdapter {

    private static Logger logger = LoggerFactory.getLogger(WebSecurityConfiguration.class);

    @Autowired
    RestAuthenticationEntryPoint restAuthenticationEntryPoint;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("stephane").password("mypassword").roles("ADMIN");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        .csrf().disable()
        .httpBasic()
        .authenticationEntryPoint(restAuthenticationEntryPoint)
        .and()
        .authorizeRequests()
        .antMatchers("/**").hasRole("ADMIN")
        .anyRequest().authenticated();
    }

}

这两个类位于不同的源中,一个在src / main / java中,另一个在src / test / java中,但它们具有相同的包名.

Maven构建给了我以下例外:

Caused by: java.lang.IllegalStateException: @Order on WebSecurityConfigurers must be unique. Order of 100 was already used, so it cannot be used on com.thalasoft.learnintouch.rest.config.WebSecurityConfiguration$$EnhancerByCGLIB$$2d511ca8@536972 too.

将WebSecurityConfigurerAdapter扩展两次是否再次尝试实例化WebSecurityConfiguration失败的原因是什么?

怎么去呢?

最佳答案
我可以通过将@Order(2)添加到生产环境WebSecurityConfigurerAdapter和@Order(1)到测试环境1来解决问题.

@Configuration
@EnableWebSecurity
@ComponentScan(basePackages = { "com.thalasoft.learnintouch.rest.security" })
@Import({ WebSecurityInitializer.class })
@Order(2)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
}

@Configuration
@EnableWebSecurity
@ComponentScan(basePackages = { "com.thalasoft.learnintouch.rest.security" })
@Import({ WebSecurityInitializer.class })
@Order(1)
public class WebSecurityTestConfiguration extends WebSecurityConfigurerAdapter {
}

编辑:一个更好的解决方案是避免使用@Order注释本身就是凌乱配置的标志.

问题是由于在运行测试时加载了WebSecurityConfiguration和WebSecurityTestConfiguration,当只需要加载其中一个WebSecurityTestConfiguration时,需要加载它.

在条件注释的帮助下,很容易只加载所需的注释.

这是条件定义的接口:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Conditional(EnvNotTestCondition.class)
public @interface EnvNotTest {
}

这是它的实现:

public class EnvNotTestCondition implements Condition {

  private static final String ENV_TEST = "test";

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return context.getEnvironment().getProperty("env") == null || !context.getEnvironment().getProperty("env").equals(ENV_TEST);
    }

}

转载注明原文:maven – 测试和生产环境中的Spring Security - 代码日志