Spring Cloud Eureka Server +自定义自动配置的Web安全

时间:2015-07-03 01:51:25

标签: spring-security spring-boot spring-cloud

使用自定义自动配置的网络安全配置来自不同项目以及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

设置

module - my-autoconfiguration

@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验证该课程是肯定的。

module - discovery-server

我将上述模块包含为依赖项以及spring-boot-starter-security

@SpringBootApplication
@EnableEurekaServer
public class DiscoveryServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(DiscoveryServerApplication.class, args);
    }
}

筛选顺序 - 预期(在发现服务器项目中使用Spring Boot基本安全性或自定义安全性时)

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 [/]

过滤器订单 - 结果(自定义自动配置的Web安全性)

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 [/]

1 个答案:

答案 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像自动配置一样。