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

Spring应用间歇性CORS错误:编辑WebSecurityCustomizer后时隐时现

解决Spring REST应用Flutter Web端CORS异常问题

你的问题核心在于Spring Security的过滤器执行顺序优先于WebMvc的CORS处理,导致预检请求(OPTIONS)被认证拦截,同时部分端点偶尔报错的情况也和配置加载顺序有关。以下是具体的修复方案:

修复步骤

1. 调整SecurityFilterChain配置,添加CORS支持并放行预检请求

修改securityFilterChain方法,加入CORS配置,同时允许所有OPTIONS请求无需认证(浏览器会先发OPTIONS预检请求,此时还未携带Token):

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        // 配置CORS
        .cors(cors -> cors.configurationSource(corsConfigurationSource()))
        .authorizeHttpRequests((authorize) -> authorize
                // 放行所有OPTIONS预检请求
                .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                .anyRequest().authenticated()
        )
        .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
        .addFilterAfter(createPolicyEnforcerFilter(), BearerTokenAuthenticationFilter.class);
    return http.build();
}

2. 添加CORS配置源Bean

创建CorsConfigurationSource Bean,替代原来的WebMvc CORS配置(因为Security会优先使用这个配置):

@Bean
CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    // 允许所有前端域名(生产环境建议指定具体域名)
    configuration.setAllowedOrigins(Collections.singletonList("*"));
    // 允许所有HTTP方法
    configuration.setAllowedMethods(Collections.singletonList("*"));
    // 允许所有请求头
    configuration.setAllowedHeaders(Collections.singletonList("*"));
    // 如果需要携带Cookie或认证信息,开启此选项(根据你的业务需求调整)
    configuration.setAllowCredentials(true);
    
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    // 对所有路径应用CORS配置
    source.registerCorsConfiguration("/**", configuration);
    return source;
}

3. 移除冗余的WebMvc CORS配置

可以删除原来的corsConfigurer Bean,因为现在Security已经处理了CORS,避免配置冲突:

// 移除这个Bean
/*
@Bean
public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurer() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
            .allowedMethods("*")
            .allowedOrigins("*");
        }
    };
}
*/

问题原因说明

  • CORS预检请求被拦截:浏览器发送跨域请求前会先发OPTIONS预检请求,你的原配置中anyRequest().authenticated()会要求该请求携带Token,导致返回401,触发CORS错误。
  • Security优先级高于WebMvc:WebMvc的CORS配置只有在请求通过Security过滤后才会生效,无法处理被Security拦截的预检请求。
  • 偶尔报错的情况:这是Spring上下文加载时过滤器顺序不稳定导致的,重启后上下文重新初始化,过滤器顺序恢复正常,所以问题暂时消失,本质还是配置缺失。

额外注意事项

  • 生产环境不要使用allowedOrigins("*"),建议指定具体的前端域名(比如https://your-flutter-app.com),提升安全性。
  • 如果你的业务需要携带认证Cookie,确保setAllowCredentials(true),同时前端请求要设置withCredentials: true(Flutter Web中对应HttpClient的withCredentials属性)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 12:07:45