【问题标题】:Spring Cloud Eureka Server + Custom Auto-Configured Web SecuritySpring Cloud Eureka Server + 自定义自动配置 Web 安全
【发布时间】:2015-09-20 17:36:27
【问题描述】:

当使用自定义自动配置的网络安全配置来自不同的项目和 Spring Cloud Eureka Server 时,我遇到了过滤器顺序问题。使用自定义自动配置的 Web 安全配置时,springSecurityFilterChain 出现在由 EurekaServerConfiguration 创建的 servletContainer 过滤器之后。因此,对 Eureka 仪表板的访问是安全的,但 /eureka/* 没有应用 Spring Security 过滤器链。

如果我使用默认的 Spring Boot 自动配置的 Web Security(即security.basic.* 属性,过滤顺序是正确的。

如果我在相同的项目不同的配置类中使用创建自定义网络安全配置作为发现服务器,则过滤器顺序是正确的。如果我使用 @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);
    }
}

过滤顺序 - 预期(在发现服务器项目中使用 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 [/]

过滤顺序 - 结果(自定义自动配置的网络安全)

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

【问题讨论】:

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


    【解决方案1】:

    这里的问题是当你使用@EnableWebSecurity注解时,它会禁用Spring Boot在SpringBootWebSecurityConfiguration中提供的安全自动配置(见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 没有顺序,它会在OrderComparator 类中得到一个默认值Ordered.LOWEST_PRECEDENCE。这与EurekaServerConfiguration 中定义的jersey bean 的值相同,后者负责对/eureka 前缀的调用。在 Eureka 的引导阶段,jersey bean 在无序的 springSecurityFilterChain 之前被实例化,并且将在过滤器链之前被连接,因此禁用了 /eureka 前缀的安全性。

    要解决此问题,只需在使用 @EnableWebSecurity 注释的 Configuration 类中添加 FilterRegistrationBean 包装 springSecurityChain 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 就好像它是自动配置的。

    【讨论】:

      猜你喜欢
      • 2018-07-31
      • 2016-02-12
      • 2018-12-05
      • 2020-11-06
      • 2019-02-17
      • 2011-02-10
      • 1970-01-01
      • 2018-08-13
      • 1970-01-01
      相关资源
      最近更新 更多