这是我的情况:我有一个使用Spring Security的项目。一切都运作良好。
我有这个:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
public AuthenticationFailureHandler getAuthenticationFailureHandler(){
return new PlainFailureHandler();
}
@Override
protected void configure(HttpSecurity httpSec) throws Exception {
AuthFilter filter = new AuthFilter(getAuthenticationFailureHandler());
filter.setAuthenticationManager(authenticationManagerBean());
httpSec.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);
}
}
到目前为止,一切都很棒。现在,我有第二个项目建立在第一个项目之上。
在其中,我需要覆盖AuthenticationFailureHandler。
我在第二个项目中创建了一个新类,它看起来很相似:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class NewProjectSecurityConfig extends SecurityConfig {
@Override
public AuthenticationFailureHandler getAuthenticationFailureHandler() {
return new NewProjectAuthenticationFailureHandler();
}
}
现在我的问题是Spring正在实例化它们,导致两个过滤器。我可以添加一个@Order(1)
以确保一个在另一个之前完成,但我真正想要的是仅使用第二个配置,并以某种方式告诉Spring使用它而是的第一个。我还是春天的新人,所以如果我错过了一张更大的图片,我会道歉。项目。我也无法更改第1项,因此我无法删除原始配置并将其复制。
注意:我根本不使用配置文件,这是以编程方式完成的。
答案 0 :(得分:0)
我认为这是当前设置配置方式的限制。
如果查看WebSecurityConfiguration
类,它具有setFilterChainProxySecurityConfigurer
方法,该方法注入了AutowiredWebSecurityConfigurersIgnoreParents
类解决的所有webSecurityConfigurers。基本上,它会使用所有扩展WebSecurityConfigurerAdapter
或实现WebSecurityConfigurer
的bean。
现在,该方法会将所有那些配置程序添加到WebSecurity
对象中。然后,它是build
方法遍历所有那些配置程序(在init()之类的方法中),并且基本上,对每个配置程序执行以下操作:
configurer.init()
configurer.configure()
WebSecurityConfigurerAdapter的Init方法正在执行此操作:
public void init(final WebSecurity web) throws Exception {
final HttpSecurity http = getHttp();
web.addSecurityFilterChainBuilder(http).postBuildAction(() -> {
FilterSecurityInterceptor securityInterceptor = http
.getSharedObject(FilterSecurityInterceptor.class);
web.securityInterceptor(securityInterceptor);
});
}
因此,每个配置程序都会创建并添加自己的过滤器链。
如果通过使用不同的URL来完美地划分您的配置,则可以假设一个配置程序用于“ / api / v1”,另一个配置程序用于“ / api / v2”。
但是,如果您的配置是全局配置或至少相交,那么您将遇到很大麻烦。
让我们说一个定义了csrf.disable(),而另一个没有csrf.disable()。
您的Web请求将通过安全链,如果没有csrf令牌,它将通过第一个链,但不会通过第二个链。因此,有效地取代了配置(一个覆盖/重新定义另一个)的单一配置,而得到了配置(其中两个)作为两个的交集。
一种可能的解决方案是扩展现有配置,调用super()并重新定义一些配置,但是同时您需要确保原始配置不在spring所发现的bean列表中。