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

SpringBoot3迁移:公共URL触发认证过滤器致401问题解决

问题解决:SpringBoot3中公共URL仍触发自定义认证过滤器

问题原因

你的CustomAuthenticationFilter标注了@Component注解,这会让Spring将它自动注册到Servlet全局过滤器链中,不受Spring Security配置的securityMatcher(protectedUrls)限制。也就是说,即使是公共URL(/api/auth/login、/api/auth/register),也会先经过这个全局过滤器,导致返回401。

解决方案

方案一:移除全局过滤器注册,仅在Security链中使用

  1. 去掉CustomAuthenticationFilter类上的@Component注解
  2. 在SecurityConfig中手动创建该过滤器的Bean,避免全局注册:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {

    public static final RequestMatcher PUBLIC_URLS = new OrRequestMatcher(
            new AntPathRequestMatcher("/api/auth/login"),
            new AntPathRequestMatcher("/api/auth/register")
    );

    // 手动创建CustomAuthenticationFilter Bean,注入依赖
    @Bean
    public CustomAuthenticationFilter customAuthenticationFilter(UserCrudService userCrudService) {
        return new CustomAuthenticationFilter(userCrudService);
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        var protectedUrls = new NegatedRequestMatcher(PUBLIC_URLS);
        http
                .securityMatcher(protectedUrls)
                .cors(cors -> cors.configurationSource(corsConfigurationSource()))
                .csrf(csrf -> csrf.disable())
                .sessionManagement(sessionManagement ->
                        sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .exceptionHandling(exceptionHandling ->
                        exceptionHandling.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.FORBIDDEN)))
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers("/api/data-transfer/**").hasAnyAuthority("ADMIN")
                        .requestMatchers("/api/discount-code/**").hasAnyAuthority("USER")
                        .anyRequest().authenticated())
                .addFilterAfter(customAuthenticationFilter(userCrudService), BasicAuthenticationFilter.class);
        return http.build();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {       
    [...]
    }
}

同时修改CustomAuthenticationFilter的构造方法,注入UserCrudService:

public class CustomAuthenticationFilter extends OncePerRequestFilter {
    private static final String BEARER_PREFIX = "Bearer ";
    private final UserCrudService userCrudService;

    // 构造注入依赖
    public CustomAuthenticationFilter(UserCrudService userCrudService) {
        this.userCrudService = userCrudService;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    [...]
    }
}

方案二:在过滤器中添加忽略路径逻辑

如果不想移除@Component注解,可以重写OncePerRequestFilter的shouldNotFilter方法,指定公共URL不执行过滤逻辑:

@Component
public class CustomAuthenticationFilter extends OncePerRequestFilter {
    private static final String BEARER_PREFIX = "Bearer ";

    @Autowired
    private UserCrudService userCrudService;

    // 重写该方法,判断请求是否为公共URL,是则跳过过滤
    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
        return SecurityConfig.PUBLIC_URLS.matches(request);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    [...]
    }
}

说明

两种方案都能解决问题:方案一从根源上避免全局过滤器干扰,更符合Spring Security的配置逻辑;方案二灵活调整过滤范围,适合需要保留全局过滤器但部分路径例外的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 00:52:23