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

Spring Boot带认证应用出现CORS错误,求排查SecurityFilterChain问题

问题根源分析

你的问题核心是Spring Security拦截了跨域预检的OPTIONS请求:

  • 无需认证的/api/v1/auth/**接口因为配置了permitAll,OPTIONS预检请求能直接通过,WebMvc的CORS配置可以正常给响应添加跨域头;
  • 但需要认证的接口,OPTIONS请求不会携带JWT令牌,被Spring Security的认证逻辑拦截,响应里没有返回CORS头,导致浏览器触发跨域错误。
解决方案

在Spring Security配置里显式开启CORS支持,让它统一处理跨域规则,同时确保预检请求不被拦截。修改后的完整配置代码如下:

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration {

    private final JwtAuthenticationFilter jwtAuthFilter;
    private final AuthenticationProvider authenticationProvider;

    @Bean
    public SecurityFilterChain getSecurityFilterChain(HttpSecurity http) throws Exception {
        http.csrf()
                .disable()
                // 关键:开启Spring Security的CORS支持,会自动绑定下面的CORS配置
                .cors(Customizer.withDefaults())
                .authorizeHttpRequests()
                .requestMatchers(new AntPathRequestMatcher("/api/v1/auth/**"))
                .permitAll()
                // 兜底允许所有OPTIONS预检请求直接通过
                .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authenticationProvider(authenticationProvider)
                .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }

    // 用Spring Security的CorsConfigurationSource替换原WebMvc的CORS配置,统一管理
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        // 开发环境指定具体前端域名,生产环境不要用*,更安全
        configuration.setAllowedOrigins(Collections.singletonList("http://localhost:3000"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS"));
        // 明确允许携带Authorization头(JWT令牌放在这个头里)
        configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type"));
        configuration.setAllowCredentials(false);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}
额外注意事项

如果修改后仍有问题,检查你的JwtAuthenticationFilter是否拦截了OPTIONS请求,需要在过滤器里跳过预检请求的校验:

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    // 跳过OPTIONS预检请求,直接放行
    if (HttpMethod.OPTIONS.name().equalsIgnoreCase(request.getMethod())) {
        response.setStatus(HttpServletResponse.SC_OK);
        filterChain.doFilter(request, response);
        return;
    }
    // 原有JWT校验逻辑...
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 18:42:21