如何解决Spring Security自定义过滤器对所有路径生效的问题?
问题:自定义过滤器无法仅对指定路径生效
我正在构建一个RESTful服务器,需要为部分路径而非全部应用自定义过滤器,但配置后出现异常。按预期,过滤器应该只对/auth/user/**路径生效,但实际所有请求都会触发该过滤器。
相关代码
Security配置类
@Configuration @EnableWebSecurity public class AppSecurityConfig extends WebSecurityConfigurerAdapter { private final CustomFilter customFilter; @Autowired public AppSecurityConfig(CustomFilter filter) { customFilter = filter; } @Override protected void configure(HttpSecurity http) throws Exception { http .antMatcher("/auth/user/**") .addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class); } }
自定义过滤器类
@Component public class CustomFilter extends OncePerRequestFilter { private static final Logger log = LoggerFactory.getLogger(CustomFilter.class); @Override protected void doFilterInternal( final HttpServletRequest request, final HttpServletResponse response, final FilterChain filterChain ) throws ServletException, IOException { log.trace("Executing CustomFilter"); filterChain.doFilter(request, response); } }
问题原因
问题根源在于CustomFilter上的@Component注解。当添加该注解后,Spring会自动将过滤器注册到全局Servlet过滤器链中,这意味着所有请求都会经过该过滤器,不受HttpSecurity中路径匹配规则的限制。HttpSecurity的配置只是将过滤器额外添加到Spring Security的过滤链中,导致过滤器被双重注册,最终所有请求都会触发它。
解决方法
方法1:移除过滤器的@Component注解(推荐)
去掉CustomFilter的@Component,阻止Spring自动将其注册到全局过滤器链,仅通过HttpSecurity配置让它作用于指定路径。
修改后的过滤器类:
public class CustomFilter extends OncePerRequestFilter { private static final Logger log = LoggerFactory.getLogger(CustomFilter.class); @Override protected void doFilterInternal( final HttpServletRequest request, final HttpServletResponse response, final FilterChain filterChain ) throws ServletException, IOException { log.trace("Executing CustomFilter"); filterChain.doFilter(request, response); } }
若过滤器需要依赖注入,可在Security配置类中通过@Bean注册:
@Configuration @EnableWebSecurity public class AppSecurityConfig extends WebSecurityConfigurerAdapter { @Bean public CustomFilter customFilter() { // 若有依赖,在此注入 return new CustomFilter(); } @Override protected void configure(HttpSecurity http) throws Exception { http .antMatcher("/auth/user/**") .addFilterBefore(customFilter(), UsernamePasswordAuthenticationFilter.class); } }
方法2:在过滤器内部添加路径匹配逻辑
如果保留@Component,可在过滤器内部手动判断请求路径,仅在匹配/auth/user/**时执行逻辑:
@Component public class CustomFilter extends OncePerRequestFilter { private static final Logger log = LoggerFactory.getLogger(CustomFilter.class); private final AntPathMatcher pathMatcher = new AntPathMatcher(); @Override protected void doFilterInternal( final HttpServletRequest request, final HttpServletResponse response, final FilterChain filterChain ) throws ServletException, IOException { String requestPath = request.getRequestURI(); if (pathMatcher.match("/auth/user/**", requestPath)) { log.trace("Executing CustomFilter"); } filterChain.doFilter(request, response); } }
此方法的缺点是过滤器仍会被所有请求触发,仅内部跳过逻辑,不如方法1优雅。
内容的提问来源于stack exchange,提问作者MiguelMunoz
相关产品推荐
相关产品推荐

