我想在两个环境(测试环境和生产环境)中运行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的尝试的原因?
那怎么办呢?
我可以通过在生产环境WebSecurityConfigurerAdapter中添加@Order(2)和在测试环境中添加@Order(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);
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句