【问题标题】:Use @Autowired with a Filter configured in SpringBoot将 @Autowired 与 Spring Boot 中配置的过滤器一起使用
【发布时间】:2023-03-29 09:59:01
【问题描述】:

我需要在过滤器中使用自动装配。所以我使用@Component注释我的过滤器类,

import org.springframework.web.filter.GenericFilterBean;
@Component
public class TokenAuthorizationFilter extends GenericFilterBean {
    @Autowired
    public EnrollCashRepository enrollCashRepository;
}

然后我在 SecurityConfig 中添加如下过滤器,

   @Configuration
    @EnableWebMvcSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {

        @Override
        public void configure(WebSecurity webSecurity) throws Exception
        {
            webSecurity.ignoring().antMatchers(HttpMethod.GET, "/health");
        }
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.addFilterBefore(new TokenAuthorizationFilter(), BasicAuthenticationFilter.class);  
            http.authorizeRequests().antMatchers("/api/**").authenticated();    
    }

我的问题是我的过滤器被@Component 注释调用了两次。如果我删除 @Component 注释,它只会调用一次。

然后我在我的 Spring Boot 主类中添加以下作为修复。然后我在 SecurityConfig 中注释 addFilterBefore 行。

 @Bean
    public FilterRegistrationBean tokenAuthFilterRegistration() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new PITokenAuthorizationFilter());
        filterRegistrationBean.setOrder(1);
        filterRegistrationBean.setEnabled(false);
        return filterRegistrationBean;
    }

然后我的过滤器被调用一次。但即使我将 setEnabled 设为 true 或 false,当我调用我的 rest api 时,我也会收到 403 Forbiddon 错误,http://localhost:8080/api/myservice

如何解决这种情况,我可以在 Spring 过滤器中使用 @Autowired?

编辑:添加控制器和过滤器类,

@RestController
@RequestMapping(value = "/api")
public class SpringToolController { 
    @RequestMapping(value = "/myservice", method = RequestMethod.GET)
    public HttpEntity<String> myService() {
        System.out.println("-----------myService invoke-----------");
        return new ResponseEntity<String>(HttpStatus.OK);
    }
}



public class TokenAuthorizationFilter extends GenericFilterBean {
    public TokenAuthorizationFilter(EnrollCashRepository enrollCashRepository) {
        this.enrollCashRepository = enrollCashRepository;
    }

    public EnrollCashRepository enrollCashRepository;

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("before PITokenAuthorizationFilter");
        chain.doFilter(servletRequest, servletResponse);
        System.out.println("after PITokenAuthorizationFilter");
    }

    public EnrollCashRepository getEnrollCashRepository() {
        return enrollCashRepository;
    }

    public void setEnrollCashRepository(EnrollCashRepository enrollCashRepository) {
        this.enrollCashRepository = enrollCashRepository;
    }

}

【问题讨论】:

    标签: java spring spring-boot


    【解决方案1】:

    删除您的FilterRegistrationBean 并在您的SecurityConfig 中初始化TokenAuthorizationFilter,如下所示:

    @Configuration
    @EnableWebMvcSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        public EnrollCashRepository enrollCashRepository;
    
        @Override
        public void configure(WebSecurity webSecurity) throws Exception
        {
            webSecurity.ignoring().antMatchers(HttpMethod.GET, "/health");
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception 
        {
            http.addFilterBefore(tokenAuthorizationFilter(), BasicAuthenticationFilter.class);  
            http.authorizeRequests().antMatchers("/api/**").authenticated();    
        }
    
        private TokenAuthorizationFilter tokenAuthorizationFilter() 
        {
            return new TokenAuthorizationFilter(enrollCashRepository);
        }
    }
    

    删除@Autowired@Component 注释并使用构造函数注入设置EnrollCashRepository

    import org.springframework.web.filter.GenericFilterBean;
    
    public class TokenAuthorizationFilter extends GenericFilterBean {
    
        private final EnrollCashRepository enrollCashRepository;
    
        public TokenAuthorizationFilter(EnrollCashRepository enrollCashRepository) 
        {
            this.enrollCashRepository = enrollCashRepository
        }
    }
    

    【讨论】:

    • 谢谢。现在,enrollCashRepository 正在被填充。但是当我调用其余 api 时,我得到 403 - Forbidden 错误。我编辑答案以显示其余控制器。
    • 您能否在org.springframework.security 上将日志级别设置为DEBUG 并将堆栈跟踪添加到您的问题中?
    • 它在 PITokenAuthorizationFilter 之前、PITokenAuthorizationFilter 之后打印出我添加的过滤器的 sys。但以上 403 错误来自休息端点
    • 我相信你,但调试日志显示了你的 403 的根本原因。
    • 我知道是什么问题。由于我在我的 pom 中添加了 spring-boot-starter-security,我的整个应用程序都通过基本身份验证受到保护。我需要提供用户名和默认安全密码。你知道我怎么能禁用这个,因为我自己分别处理身份验证和授权?
    【解决方案2】:

    我现在为我的工人阶级添加了一个测试过滤器,它运行良好。这是相关的代码。

    过滤器

    @Component
    public class TestFilter extends GenericFilterBean {
    
    private static final Logger logger = LoggerFactory.getLogger(TestFilter.class);
    
    @Autowired
    UserService userService;
    
     @Override
     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
         logger.error("=====================AWESOME=======================");
         chain.doFilter(request, response);
         userService.activate("123"); //this works
     }
    
    }
    

    应用安全配置

    @Configuration
    @EnableWebSecurity
    public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Autowired
    private TestFilter testFilter;
    
         @Override
         protected void configure(HttpSecurity http) throws Exception {
         //loginFailureHandler.setDefaultFailureUrl("/login?error=true");
         http.addFilterBefore(testFilter, BasicAuthenticationFilter.class);
         //Http other config here.
     }
    }
    

    应用配置

    @Configuration
    @ImportResource({
        "classpath*:/context.xml"
    })
    @PropertySources(
        @PropertySource({
                "classpath:/application.yml"
        })
    )
    @Import({AppSecurityConfig.class, WebConfig.class,TestFilter.class})
    public class AppConfig {
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-09
      • 2016-02-23
      • 2015-12-10
      • 2010-10-30
      • 2013-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多