在spring boot中使用多个WebSecurityConfigurerAdapter

时间:2014-09-30 06:38:20

标签: spring-security spring-boot

我有2个课程延伸WebSecurityConfigurerAdapter。并且不能让它们一起工作。

这个想法如下:

  1. 只有一个WebSecurityConfigurerAdapter只会向安全链添加自定义过滤器。该过滤器会执行一些自定义身份验证,并将Authentication保存到SecurityContext。这通常很好。配置如下(导入省略):
  2.  @Order(1)
     @Configuration
     @EnableWebMvcSecurity
     public class BestSecurityConfig extends WebSecurityConfigurerAdapter {
    
         @Autowired
         private BestPreAuthenticationFilter ssoAuthenticationFilter;
    
         @Bean
         protected FilterRegistrationBean getSSOAuthenticationFilter() {
             FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(ssoAuthenticationFilter);
    
             // Avoid include to the default chain
             filterRegistrationBean.setEnabled(false);
    
             return filterRegistrationBean;
         }
    
         @Override
         protected void configure(HttpSecurity http) throws Exception {
             http
                .addFilterAfter(ssoAuthenticationFilter, SecurityContextPersistenceFilter.class);
    
         }
    
         @Configuration
         protected static class AuthenticationConfiguration extends
                 GlobalAuthenticationConfigurerAdapter {
    
             @Autowired
             private BestAuthenticationProvider authenticationProvider;
    
             @Override
             public void configure(AuthenticationManagerBuilder auth) throws Exception {
                 auth.authenticationProvider(authenticationProvider);
             }
         }
     }
    
    1. 我希望上面的内容是任何人都可以通过@ComponentScan包含的库类,并对自定义身份验证进行排序。显然,他们希望提供自定义HttpSecurity来保护edpoints。尝试类似:
    2.  @Configuration
       @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
       @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
       public class SecurityConfig extends WebSecurityConfigurerAdapter {
      
           @Override
           protected void configure(HttpSecurity http) throws Exception {
               http
                   .csrf().disable()
                   .authorizeRequests()
                   .antMatchers("/testUrl").hasRole("NON_EXISTING")
                   .anyRequest().authenticated();
           }
       }
      

      显然,我的用户不是角色NON_EXISTING的成员,因此无法访问测试网址。不幸的是,她是。

      如果我将安全authorizeRequests()部分移动到配置类窗体1.在添加安全过滤器之后,它会按预期阻止访问。但在我的情况下,看起来第二种配置被忽略了。

      我还调试了configure()方法并注意到HttpSecurity不是同一个闻起来有点的对象。

      任何提示我如何才能使这项工作受到高度赞赏。

      总结目标:

      • 有一个WebSecurityConfigurerAdapter添加了过滤器,对库的用户隐藏
      • 让用户定义自己的自定义端点安全性

      Spring boot 1.1.6-RELEASE

3 个答案:

答案 0 :(得分:13)

我刚发现的一个选项是:

  1. 从第一个bean
  2. 中删除@Configuration注释

    并将2.更改为:

     @Configuration
     @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
     @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
     public class SecurityConfig extends BestSecurityConfig { //Note the changed extend !
    
         @Override
         protected void configure(HttpSecurity http) throws Exception {
    
             super.configure(http); // Merge of the 2 HTTP configurations
    
             http
                 .csrf().disable()
                 .authorizeRequests()
                 .antMatchers("/testUrl").hasRole("NON_EXISTING")
                 .anyRequest().authenticated();
         }
     }
    

    关于这是对还是错的任何评论都非常感激

    编辑:几年后,我仍然没有找到其他方式,但我越来越喜欢这种方式。即使在默认情况下,您扩展了抽象WebSecurityConfigurerAdapter,也没有理由为什么其他抽象层不能提供另一个提供有意义默认值的抽象扩展。

答案 1 :(得分:7)

我(在我看来)创建了一种更简洁的方法来构建一些默认配置,并通过 Custom DSLs 使其易于集成到新项目中。

我用它来配置JWT身份验证过滤器,但我认为CORS过滤器更简单,更具说服力:

public class CustomCorsFilterDsl extends AbstractHttpConfigurer<CustomCorsFilterDsl, HttpSecurity> {

    @Override
    public void init(HttpSecurity http) throws Exception {
        //your init code here, no needed in this case
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        CorsFilter corsFilter = corsFilter(corsProperties);
        http.addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class);
    }

    private CorsFilter corsFilter(CorsProperties corsProperties) {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("http://localhost:9000");
        config.addAllowedHeader("*");
        config.addAllowedMethod("GET, POST, PUT, PATCH, DELETE");
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }

    public static CustomCorsFilterDsl dsl() {
        return new CustomCorsFilterDsl();
    }
}

在您的WebSecurityConfig中,您可以像这样使用它:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .exceptionHandling()
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/foo/**").permitAll()
                //... your configurations
                .antMatchers("/**").authenticated()
                .and()
                .apply(CustomCorsFilterDsl.dsl());
    }
}

您完成了以更清晰的方式使库具有独立于项目代码的默认配置的目标,因为您可以在项目的WebSecurityConfig中可视化自定义CORS条目。

答案 2 :(得分:3)

我们用于此的另一种解决方案。

定义一个特殊的界面

public interface ServiceWebSecurityConfigurer {
    void configure(HttpSecurity http) throws Exception;
}

然后只有一个ConfigurerAdapter:

public class MyConfigurerAdapter extends WebSecurityConfigurerAdapter {

    @Autowired(required = false)
    ServiceWebSecurityConfigurer serviceSecConfig;

    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests(). // whatever

        if (serviceSecConfig != null) serviceSecConfig.configure(http);

        http.authorizeRequests(). // whatever
    }
}

然后在需要时在其他位置实现ServiceWebSecurityConfigurer。也可以有多个实现,只需将它们作为列表自动装配并迭代并在主配置中使用它们。