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

Spring Boot 3.1.4配置permitAll后请求仍过JwtFilter的问题

问题:Spring Boot 3.1.4中配置permitAll路径仍被过滤器拦截

在Spring Boot 3.1.4中,我已配置允许所有请求访问/auth/login路径,但实际请求仍会经过JwtFilter和AuthorizationFilter,最终返回403。

配置代码

package com.example.demo.Auth;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
public class AuthConfig {

    @Autowired
    private JwtFilter jwtFilter;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        return httpSecurity
                .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
                .authorizeHttpRequests(authorizationManagerRequestMatcherRegistry -> {
                    authorizationManagerRequestMatcherRegistry.requestMatchers("/auth/registration").permitAll();
                    authorizationManagerRequestMatcherRegistry.requestMatchers("/auth/login").permitAll();
                    authorizationManagerRequestMatcherRegistry.anyRequest().authenticated();
                })
                .httpBasic(AbstractHttpConfigurer::disable)
                .csrf(AbstractHttpConfigurer::disable)
                .build();
    }

}

请求示例

POST localhost:8080/auth/login
Content-Type: application/json

{
  "userName": "jane_doe",
  "password": "pw12345789"
}

预期与实际结果

  • 预期:请求应通过并由控制器处理
  • 实际:请求仍会经过jwtFilter和AuthorizationFilter,最终返回403

疑问

为何已配置绕过该路径的请求仍会经过过滤器?


解决说明

核心原因:permitAll()仅表示该路径无需身份认证授权,但不会跳过Spring Security过滤器链中的自定义过滤器。你通过addFilterBefore添加的JwtFilter是全局生效的,会拦截所有请求,包括配置了permitAll的路径。

以下两种方案可解决此问题:

方案一:在JwtFilter内部判断路径直接放行

修改JwtFilter的doFilterInternal方法,添加路径判断逻辑,匹配到无需验证的路径时直接放行:

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    String requestUri = request.getRequestURI();
    // 跳过登录、注册路径的JWT验证
    if ("/auth/login".equals(requestUri) || "/auth/registration".equals(requestUri)) {
        filterChain.doFilter(request, response);
        return;
    }
    // 原有JWT验证逻辑
    // ...
}

方案二:配置多SecurityFilterChain分离路径处理

通过定义多个SecurityFilterChain并指定执行顺序,让无需认证的路径走单独的过滤器链,不加载JwtFilter:

@Configuration
public class AuthConfig {

    @Autowired
    private JwtFilter jwtFilter;

    // 第一个过滤器链:处理/auth开头的路径,无需认证,不加载JwtFilter
    @Bean
    @Order(1)
    public SecurityFilterChain publicSecurityFilterChain(HttpSecurity http) throws Exception {
        return http
                .securityMatcher("/auth/**")
                .authorizeHttpRequests(auth -> auth.anyRequest().permitAll())
                .csrf(AbstractHttpConfigurer::disable)
                .httpBasic(AbstractHttpConfigurer::disable)
                .build();
    }

    // 第二个过滤器链:处理其他所有路径,需要认证,加载JwtFilter
    @Bean
    @Order(2)
    public SecurityFilterChain privateSecurityFilterChain(HttpSecurity http) throws Exception {
        return http
                .securityMatcher("/**")
                .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
                .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
                .csrf(AbstractHttpConfigurer::disable)
                .httpBasic(AbstractHttpConfigurer::disable)
                .build();
    }
}

Spring Security会按@Order注解的顺序匹配过滤器链,/auth/login会被第一个链处理,直接放行到控制器,不会经过JwtFilter。


内容的提问来源于stack exchange,提问作者Ero Stefano

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 02:57:16