Jou*_*ner 11 java captcha spring spring-security
我正在寻找一种非侵入性的方法来为某些api调用添加验证码过滤器.
我的设置包括两个WebSecurityConfigurerAdapters,每个都有一个过滤器(不是验证码过滤器):
如何在Spring Security内容,公共内部api或外部api调用之前添加过滤器?我不需要SecurityContext,只需要检查请求头中的Captcha,转发到filterChain(普通过滤器)或手动拒绝访问.我尝试在web.xml中声明一个过滤器,但这会破坏使用依赖注入的能力.
这是我的Spring安全配置:
@EnableWebSecurity
public class SpringSecurityConfig {
    @Configuration
    @Order(1)
    @EnableGlobalMethodSecurity(securedEnabled = true)
    public static class InternalApiConfigurerAdapter extends WebSecurityConfigurerAdapter {
        @Autowired
        private Filter filterA;
        public InternalApiConfigurerAdapter() {
            super(true);
        }
        @Override
        public void configure(WebSecurity web) throws Exception {
            web
                    .ignoring()
                    .antMatchers("/public/**");
        }
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .antMatcher("/iapi/**")
                    .exceptionHandling().and()
                    .anonymous().and()
                    .servletApi().and()
                    .authorizeRequests()
                    .anyRequest().authenticated().and()
                    .addFilterBefore(filterA, (Class<? extends Filter>) UsernamePasswordAuthenticationFilter.class);
        }
        @Override
        @Bean
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return authenticationManager();
        }
    }
    @Configuration
    @Order(2)
    @EnableGlobalMethodSecurity(securedEnabled = true)
    public static class ExternalApiConfigurerAdapter extends WebSecurityConfigurerAdapter {
        @Autowired
        private FilterB filterB;
        public ExternalApiConfigurerAdapter() {
            super(true);
        }
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .antMatcher("/external/**")
                    .exceptionHandling().and()
                    .anonymous().and()
                    .servletApi().and()
                    .authorizeRequests()
                    .anyRequest().authenticated().and()
                    .addFilterBefore(filterB, (Class<? extends Filter>) UsernamePasswordAuthenticationFilter.class);
        }
        @Override
        @Bean
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return authenticationManager();
        }
    }
更新:目前我有一个工作配置,在web.xml中声明了一个过滤器.但是,它的缺点是与Spring Context分离(例如没有bean的自动装配),所以我正在寻找一个利用Spring的更好的解决方案.
摘要:还有两个问题:
您已经有一个工作配置,之前插入了过滤器A和B,UsernamePasswordAuthenticationFilter因此应该很容易添加另一个自定义过滤器.
首先,创建过滤器,并将其声明为bean,或者使用@Component或者作为类的@Bean内部注释@Configuration类,以便可以注入它@Autowired.
现在您可以将其作为过滤器A和B注入,并使用它.根据Spring Security参考文档中的Filter Ordering部分,链中的第一个Filter是ChannelProcessingFilter,所以为了在Spring Security过滤器链中的任何其他内容之前插入过滤器,您可以这样做:
@Autowired
private CaptchaFilter captchaFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .antMatcher("/iapi/**")
            .addFilterBefore(captchaFilter, (Class<? extends Filter>) ChannelProcessingFilter.class)
            .addFilterBefore(filterA, (Class<? extends Filter>) UsernamePasswordAuthenticationFilter.class)
            .authorizeRequests()
                .anyRequest().authenticated();
    }
顺便说一句,exceptionHandling() anonymous()并且servletApi()不需要,因为在扩展时WebSecurityConfigurerAdapter,这些已经包含在内,除非anonymous()您实际指定了更多配置详细信息,因为它声明了HttpSecurityjavadoc
请记住Spring Security"入口点",DelegatingFilterProxy仍然会在过滤器之前执行,但是这个组件只将请求委托给链中的第一个过滤器,在本例中是CaptchaFilter,所以你真的会执行你的在Spring Security之前进行过滤.
但是如果您仍然希望在之前执行验证码过滤器DelegatingFilterProxy,则无法在Spring Security配置中执行此操作,您需要在web.xml文件中声明它.
更新:如果您不希望在其他配置中包含验证码过滤器,您可以随时添加第三个配置,配置类如下:
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SpringSecurityConfig {
    @Configuration
    @Order(1)
    public static class CaptchaApiConfigurerAdatper extends WebSecurityConfigurerAdapter {
        @Autowired
        private CaptchaFilter captchaFilter;
        public CaptchaApiConfigurerAdatper() {
            super(true);
        }
        @Override
        public void configure(WebSecurity web) throws Exception {
            web
                    .ignoring()
                    .antMatchers("/public/**");
        }
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .requestMatchers()
                        .antMatcher("/iapi/captcha**")
                        .antMatcher("/external/captcha**")
                        .and()
                    .addFilterBefore(captchaFilter, (Class<? extends Filter>) ChannelProcessingFilter.class)
                    .authorizeRequests()
                        .anyRequest().authenticated();
        }
    }            
    @Configuration
    @Order(2)
    public static class InternalApiConfigurerAdapter extends WebSecurityConfigurerAdapter {
        // ommiting code for the sake of clarity
    }
    @Configuration
    @Order(3)
    public static class ExternalApiConfigurerAdapter extends WebSecurityConfigurerAdapter {
         // ommiting code for the sake of clarity
    }
顺便说一句,另一个提示,你可以将特定配置之外的所有常见配置重构为主类,如@EnableGlobalMethodSecurity(securedEnabled = true)AuthenticationManager,WebSecurity以跳过公众的安全性,但对于那些因为主类没有扩展任何你应该@Autowire的方法声明.
虽然会有一个问题了WebSecurity,如果你是忽略/public/**了的匹配HttpSecurity与/public/captcha**将被忽略,所以我想,你不应该重构出来的WebSecurity,并有在CaptchaConfig类不同的模式,以便它不重叠.
| 归档时间: | 
 | 
| 查看次数: | 8910 次 | 
| 最近记录: |