You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Security 6自定义过滤器未按指定URL路径生效,反而作用于所有URL(含/login)

Spring Security 6自定义过滤器未按指定URL路径生效,反而作用于所有URL(含/login)

兄弟,我太懂你这个糟心的情况了!之前在项目里也踩过Spring Security过滤器路径匹配的坑,明明只想让自定义过滤器管/api相关的路径,结果连/login都被拦截了,简直头大。咱们先捋清楚问题根源,再给你搞定它!

首先得明确:Spring Security里如果直接把自定义过滤器加到SecurityFilterChain里,默认是对所有请求生效的,除非你明确给它划定作用范围。结合你的描述,大概率是没给过滤器所在的FilterChain指定匹配路径,或者多个FilterChain的优先级/范围配置冲突了。

给你两个最靠谱的解决方案,按需选:

方案一:给FilterChain绑定专属路径(推荐)

这个方法最优雅,直接让整个FilterChain只处理你指定的/api开头的请求,自然过滤器也不会碰/login这类路径。你可以这么改你的配置:

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SLWebConfig{

    // 处理API路径的FilterChain,优先级设为1(值越小优先级越高)
    @Bean
    @Order(1)
    public SecurityFilterChain apiSecurityFilterChain(HttpSecurity http) throws Exception {
        http
            // 关键!指定这个FilterChain只处理这些路径
            .securityMatcher("/api/**", "/api/v1/**")
            // 添加你的自定义过滤器,比如放在用户名密码认证过滤器之前
            .addFilterBefore(new SecFilters(), UsernamePasswordAuthenticationFilter.class)
            // 配置API路径的授权规则
            .authorizeHttpRequests(auth -> auth
                .anyRequest().authenticated()
            );
        return http.build();
    }

    // 单独处理登录的FilterChain,优先级设为2
    @Bean
    @Order(2)
    public SecurityFilterChain loginSecurityFilterChain(HttpSecurity http) throws Exception {
        http
            // 明确这个FilterChain只处理/login路径
            .securityMatcher("/login")
            // 登录路径允许所有人访问
            .authorizeHttpRequests(auth -> auth
                .anyRequest().permitAll()
            )
            // 这里放你的登录相关配置,比如表单登录、OAuth2登录等
            .formLogin(form -> form
                .loginProcessingUrl("/login")
                .permitAll()
            );
        return http.build();
    }
}

这么配置后,两个FilterChain各司其职:Order(1)的只管/api开头的请求,自定义过滤器只会在这些请求里生效;Order(2)的专门处理/login,完全不会被自定义过滤器干扰。

方案二:在过滤器内部判断路径(应急用)

如果暂时不想改FilterChain的结构,也可以在你的SecFilters过滤器里自己判断请求路径,遇到/login直接放行:

public class SecFilters extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String requestUri = request.getRequestURI();
        // 如果是登录路径,直接跳过过滤逻辑
        if ("/login".equals(requestUri)) {
            filterChain.doFilter(request, response);
            return;
        }
        // 这里写你的自定义过滤逻辑
        // ... 比如校验token、权限等
        // 执行完后放行
        filterChain.doFilter(request, response);
    }
}

不过这个方法不如方案一优雅,毕竟硬编码路径不够灵活,后续路径变更还要改过滤器代码,优先推荐方案一。

最后再提醒你注意Order的优先级:Order值越小,FilterChain越先执行。所以如果你的登录FilterChain Order值比API的大,就会让API的FilterChain先处理请求——但只要给每个FilterChain都加上securityMatcher,就不会出现跨路径拦截的问题啦!

备注:内容来源于stack exchange,提问作者RituV

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 17:19:26