当前位置: 首页 > 知识库问答 >
问题:

如何为特定URL添加Spring Security captcha筛选器

晁砚
2023-03-14

我正在寻找一种非侵入性的方式来为某些api调用添加验证码过滤器。

我的安装程序由两个WebSecurityConfigurerAdapter组成,每个WebSecurityConfigurerAdapter具有一个筛选器(不

  • 内部api(“/iapi”对所有调用使用筛选器A,但也忽略某些公共请求,如/authenticate)
  • 外部api(“/eAPI”对所有调用使用筛选器B)

如何在Spring Security材料之前,在公共、内部api或外部api调用上添加过滤器?我不需要SecurityContext,只需要检查请求头中的验证码,转发到filterChain(普通过滤器)或手动拒绝访问。我尝试在web.xml中声明一个过滤器,但这破坏了使用依赖注入的能力。

下面是我的Spring Security配置:

@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();
        }
    }
  1. 仅为特定URL添加筛选器-使用beforeFilter(...)在任何配置中,都会为该配置的所有URL添加一个筛选器。Antmatchers不工作。我需要类似的内容:/iapi/captcha/,/external/captcha/,/public/captcha/*。
  2. 我有一个完全绕过Spring Security性的公共api:(web.忽略().antMatchers(“/public/**”);)。我需要绕过Spring Security但仍在那里声明一个筛选器,使用Spring自动但不一定使用Spring Security特性,因为我的captcha筛选器仅以无状态的方式拒绝或转发调用。

共有1个答案

范承望
2023-03-14

您已经有了一个工作配置,在UsernamePasswordAuthenticationFilter之前插入了筛选器a和B,因此添加另一个自定义筛选器应该很容易。

首先,创建过滤器,并将其声明为一个bean,或者使用@component对类进行注释,或者在@configuration类内使用@bean进行注释,这样它就可以用@autowired注入了。

现在您可以注入它,作为过滤器A和B,并使用它。根据Spring Security reference文档中的筛选器排序部分,链中的第一个筛选器是ChannelProcessingFilter,因此为了在Spring Security Filter链中的其他内容之前插入筛选器,您需要执行以下操作:

@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();
    }

顺便说一下,ExceptionHanding()Anonymes()ServletAPI()不是必需的,因为在扩展WebSecurityConfigurerAdapter时,已经包含了这些内容,但Anonymes()除外,因为它实际上指定了更多配置细节,如它声明的HttpSecurityjavadoc

请记住Spring Security“entrypoint”、DelegatingFilterProxy仍然将在筛选器之前执行,但该组件只将请求委托给链中的第一个筛选器,在本例中,该筛选器将是CaptchaFilter,因此您实际上将在Spring Security的任何其他内容之前执行筛选器。

但是,如果您仍然希望验证码过滤器在DelegatingFilterProxy之前执行,那么在Spring Security配置中没有办法这样做,您需要在web.xml文件中声明它。

更新:如果您不希望在其他配置中包含验证码筛选器,则始终可以添加第三个配置,并且configurations类如下所示:

@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类中使用不同的模式,这样它就不会重叠。

 类似资料:
  • 我有一个Spring Boot应用程序,在其中我试图创建一个自定义安全过滤器,如下所示:

  • 我正在尝试将基于Spring MVC xml的项目配置重构为基于Spring Boot java的配置。同时按如下方式设置shiro配置:

  • 我正在使用规范来构建使用Java的web服务。我使用过滤器进行身份验证和授权,为每个请求调用所有过滤器,我不需要为某个请求只指定一个过滤器,我如何做到这一点?我只想阻止另一个过滤器调用。我不使用,而是使用扩展带有注释的类,如下所示:

  • 我正在构建一个简单的实体分页列表,支持使用ReactJS的动态过滤器。数据是在react查询库的帮助下从RESTful API层获取的。它在服务器上进行分页和筛选。所选过滤器需要存储在URL的查询参数中,以便在刷新页面时恢复。我正在努力寻找最干净的方法,将过滤器的状态与当前URL同步。我不想引入其他依赖项,如React Router,但我已经在应用程序中使用了redux。但是,我不想在redux存

  • 问题内容: 我正在尝试编写一个可以检索请求URL的过滤器,但是我不确定该怎么做。 这是我到目前为止的内容: 当我在服务器上点击页面时,唯一看到的输出是“ Url:null”。 从过滤器中给定的ServletRequest对象获取请求的URL的正确方法是什么? 问题答案: 这是您要找的东西吗? 重建: 和的信息。

  • 我对meta_query有些情境问题。客户搜索四,但结果包括私人(原始词是私人的)。我想只显示IV(罗马数字)包括后。我的meta_query搜索从标题,子标题和自定义插件的描述。我找到了REGEXP,但我找不到从标题、子标题和描述中找到漫游数字的正确方法。 客户只能找到罗马数字,也可以找到任何单词等。