针对不同网址格式的不同过滤器

时间:2016-03-17 16:41:31

标签: spring spring-security spring-boot

我有一个主要提供REST端点的spring启动应用程序,通过令牌(在Authorization标头中发送)进行身份验证,我在TokenAuthenticationFilter之前添加了自己的LogoutFilter来设置安全背景。

在创建管理控制台的过程中,我希望管理员身份验证与常规用户分开,因为我不会在AdminsUsers之间共享表格,原因如下:数据库级别我有以下user,user_token,admin,admin_token。所以为了实现这个目标,我想到了几个解决方案:

  1. 让当前TokenAuthenticationFilter处理用户/管理员令牌 AUTH。但是,这需要:将过滤器修改为 根据网址格式确定它是管理员还是用户令牌 (例如,如果它是/admin/**,过滤器将知道哪个 要拨打的服务,管理员标头是用户唯一的 (即用户发送U-Auth标头,Admin发送A-Auth标头),过滤器将根据标头名称进行操作。这一切 对我来说听起来不太好。
  2. 例如,指定一组过滤器以应用每个网址模式 /admin/**AdminTokenAuthFilter添加到链中, 而任何其他模式都会有旧的 链中TokenAuthenticationFilter。这听起来比 早期的方法,但我很难实现它。我试过了 在我的FilterRegistrationBean
  3. 中注册我自己的WebSecurityConfigurerAdapter

    示例:

     @Bean
     public FilterRegistrationBean adminFilter(){
         FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
         filterRegBean.setFilter(new AdminTokenAuthFilter());
         List<String> urlPatterns = new ArrayList<>();
         urlPatterns.add("/admin/*");
         filterRegBean.setUrlPatterns(urlPatterns);
         return filterRegBean;
     }
    

    这似乎有效,但我不确定它是否适当的做法我也关注一件事,我发现这会将过滤器添加到过滤器的弹簧originalChain ,而不是使用additionalFiltersWebSecurityConfigurerAdapter中定期添加过滤器时似乎适用的http.addFilterBefore(tokenAuthenticationFilter, LogoutFilter.class)。我不想改变spring原始过滤器链,我宁愿在附加过滤器链中使用我的自定义过滤器。有人可以详细说明吗?

    1. 创建两个单独的调度程序servlet并使每个调度程序都可以监听 一个特定的url模式,我想每个dispatcherServlet都有自己的安全配置。
    2. 任何人都可以分享一些关于这种情况下最佳方法的知识吗?

1 个答案:

答案 0 :(得分:7)

结束编写两个安全配置,第一个适用于特定的antmatcher,第二个适用于任何其他url模式。像这样:

@Configuration
@EnableWebSecurity
@ComponentScan(basePackages = "x.x.x")
public class NewSecurityConfiguration {
    @Configuration
    @Order(1)
    public static class BackendSecurityConfiguration extends WebSecurityConfigurerAdapter {
        @Autowired CustomSystemUserDetailsService customSystemUserDetailsService;
        @Autowired SystemTokenAuthFilter systemTokenAuthFilter;
        @Autowired CustomLogoutFilter customLogoutFilter;
        @Autowired UnauthorizedEntryPoint unauthorizedEntryPoint;

        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }

        @Bean(name="systemAuthenticationManager")
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }

        @Override
        public void configure(AuthenticationManagerBuilder auth) throws Exception {                auth.userDetailsService(customSystemUserDetailsService).passwordEncoder(passwordEncoder());
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {    
            http.antMatcher("/system/**")
                    .addFilterBefore(systemTokenAuthFilter, LogoutFilter.class)
                    .addFilterBefore(customLogoutFilter, LogoutFilter.class)
                    .authorizeRequests()
                    .antMatchers("/system/login").permitAll()
                    .anyRequest().authenticated()
                    .and()
                    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and()
                    .exceptionHandling().authenticationEntryPoint(unauthorizedEntryPoint)
                    .and()
                    .httpBasic().disable()
                    .csrf().disable()
                    .logout().disable();
        }
    }

    @Configuration
    @Order(2)
    public static class FrontEndSecurityConfiguration extends WebSecurityConfigurerAdapter {

        @Override
        public void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .addFilterBefore(userTokenAuthFilter, LogoutFilter.class)
                    .addFilterBefore(customLogoutFilter, LogoutFilter.class)
                    .authorizeRequests()
                    .antMatchers("/access/*").permitAll()
                    .antMatchers("/ref/*").permitAll()
                    .antMatchers("/ticket_parser/*").permitAll()
                    .antMatchers("/reset_password/**").permitAll()
                    .antMatchers("/link_profile/**").permitAll()
                    .antMatchers("/email_verification/**").permitAll()
                    .antMatchers("/ref").permitAll()
                    .antMatchers("/flightstats/alert").permitAll()
                    .antMatchers("/airline/list").access("authenticated or hasIpAddress('127.0.0.1') or hasIpAddress('0:0:0:0:0:0:0:1')")
                    .antMatchers("/airport/list").access("authenticated or hasIpAddress('127.0.0.1') or hasIpAddress('0:0:0:0:0:0:0:1')")
                    .and()
                    .authorizeRequests().anyRequest().authenticated().and().authorizeRequests()
                    .and()
                    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and()
                    .exceptionHandling().authenticationEntryPoint(unauthorizedEntryPoint)
                    .and()
                    .httpBasic().disable()
                    .csrf().disable()
                    .formLogin().disable()
                    .logout().disable();
        }
    }
}