使用自定义自动配置的网络安全配置来自不同项目以及Spring Cloud Eureka Server时,我遇到过滤顺序问题。使用自定义自动配置的网络安全配置时,springSecurityFilterChain
会显示在servletContainer
创建的EurekaServerConfiguration
过滤器之后。因此,对Eureka仪表板的访问是安全的,但/eureka/*
没有应用Spring Security过滤器链。
如果我使用默认的Spring Boot自动配置的Web Security(即security.basic.*
属性,则过滤顺序正确。
如果我使用同一项目中的自定义Web安全配置和不同的配置类作为Discovery Server,则过滤顺序正确。如果我使用@EnableWebSecurity
注释主应用程序类,或者在主应用程序类中使用@EnableWebSecurity
添加静态内部类,我也会得到错误的过滤器顺序。
我在网络安全配置的实施细节中错误地提供了自动配置或遗漏了什么?
包含完整示例的存储库:Eureka Security Config Examples
设置
@Configuration
@AutoConfigureBefore(SecurityAutoConfiguration.class)
@ConditionalOnClass(EnableWebSecurity.class)
public class CustomSecurityConfiguration {
@Configuration
@EnableWebSecurity
public static class WebSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
}
}
}
此项目包含带有spring.factories
文件的META-INF文件夹
以及EnableAutoConfiguration
项下添加的相应类。我已通过-Ddebug
验证该课程是肯定的。
我将上述模块包含为依赖项以及spring-boot-starter-security
。
@SpringBootApplication
@EnableEurekaServer
public class DiscoveryServerApplication {
public static void main(String[] args) {
SpringApplication.run(DiscoveryServerApplication.class, args);
}
}
Mapping filter: 'metricFilter' to: [/*]
Mapping filter: 'characterEncodingFilter' to: [/*]
Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
Mapping filter: 'springSecurityFilterChain' to: [/*]
Mapping filter: 'webRequestTraceFilter' to: [/*]
Mapping filter: 'servletContainer' to urls: [/eureka/*]
Mapping filter: 'applicationContextIdFilter' to: [/*]
Mapping servlet: 'dispatcherServlet' to [/]
Mapping filter: 'metricFilter' to: [/*]
Mapping filter: 'characterEncodingFilter' to: [/*]
Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
Mapping filter: 'webRequestTraceFilter' to: [/*]
Mapping filter: 'servletContainer' to urls: [/eureka/*]
Mapping filter: 'springSecurityFilterChain' to: [/*]
Mapping filter: 'applicationContextIdFilter' to: [/*]
Mapping servlet: 'dispatcherServlet' to [/]
答案 0 :(得分:1)
此处的问题是当您使用@EnableWebSecurity
注释时,它会在SpringBootWebSecurityConfiguration
中禁用Spring Boot提供的安全性自动配置(请参阅http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-security)。
使用@EnableWebSecurity
时,springSecurityFilterChain
bean在WebSecurityConfiguration
中实例化。由于此bean是普通Filter
,因此它没有Order
。使用SpringBootWebSecurityConfiguration
提供的自动配置时,springSecurityFilterChain
bean包含在FilterRegistrationBean
中,其中包含您可以在配置文件中指定的订单或默认值0
(有关详细信息,请参阅https://github.com/spring-projects/spring-boot/issues/1640。
使用Spring Boot时,它会尝试获取Filter
的顺序,然后再将它们连接到容器中。使用@EnableWebSecurity
时,由于springSecurityFilterChain
bean没有订单,因此它将在类Ordered.LOWEST_PRECEDENCE
中获得默认值OrderComparator
。这与jersey
中定义的EurekaServerConfiguration
bean的值相同,后者负责对/eureka
前缀进行的调用。在Eureka的引导阶段,jersey
bean在无序springSecurityFilterChain
之前被实例化,并且将在过滤器链之前连接,因此禁用/eureka
前缀的安全性。
要解决此问题,只需在使用FilterRegistrationBean
注释的Configuration类中添加springSecurityChain
包装@EnableWebSecurity
bean:
@Bean
@ConditionalOnBean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public FilterRegistrationBean securityFilterChainRegistration(@Qualifier(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME) Filter securityFilter)
{
FilterRegistrationBean registration = new FilterRegistrationBean(securityFilter);
registration.setOrder(SecurityProperties.DEFAULT_FILTER_ORDER);
registration.setName(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME);
return registration;
}
我在此处设置了0
的默认顺序,您可以像在SpringBootWebSecurityConfiguration
中那样对其进行配置。这将使springSecurityChain
bean像自动配置一样。