Spring Boot配置CORS后仍遇POST跨域错误,GET请求正常
解决方案
问题根源
POST请求会触发浏览器发送OPTIONS预检请求,你的Spring Security配置未对这类请求做处理,导致预检请求被拦截,无法返回CORS响应头,进而引发跨域错误。而GET请求多数情况下不会触发预检,所以能正常工作。
修复方案
方案1:在Spring Security中启用CORS配置
直接在SecurityFilterChain中集成CORS配置,确保Security过滤器优先处理CORS规则:
首先更新WebConfig,新增CORS配置源Bean:
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://localhost:5173") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .exposedHeaders("Authorization") .allowCredentials(true); } // 定义供Security使用的CORS配置源 @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(Collections.singletonList("http://localhost:5173")); configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS")); configuration.setAllowedHeaders(Collections.singletonList("*")); configuration.setExposedHeaders(Collections.singletonList("Authorization")); configuration.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; } }
然后修改SecurityFilterChain,添加CORS支持:
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception { httpSecurity .cors(cors -> cors.configurationSource(corsConfigurationSource())) // 启用Security的CORS处理 .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests((auth) -> auth .requestMatchers("/auth/**", "/drive/**").permitAll() .requestMatchers("/enrollments/**").hasAnyAuthority("LECTURER", "STUDENT") .requestMatchers(HttpMethod.POST, "/courses/**").hasAuthority("LECTURER") .requestMatchers(HttpMethod.GET, "/courses/**").hasAnyAuthority("LECTURER", "STUDENT") .requestMatchers(HttpMethod.POST, "/school/**").hasAuthority("LECTURER") .requestMatchers(HttpMethod.GET, "/school/**").hasAnyAuthority("LECTURER", "STUDENT") ) .sessionManagement(manager -> manager.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authenticationProvider(authenticationProvider()) .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class); return httpSecurity.build(); }
方案2:直接放行所有OPTIONS预检请求
如果不想改动CORS配置源,也可以在Security的授权规则里直接放行所有OPTIONS请求:
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception { httpSecurity.csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests((auth) -> auth .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 放行所有OPTIONS预检请求 .requestMatchers("/auth/**", "/drive/**").permitAll() .requestMatchers("/enrollments/**").hasAnyAuthority("LECTURER", "STUDENT") .requestMatchers(HttpMethod.POST, "/courses/**").hasAuthority("LECTURER") .requestMatchers(HttpMethod.GET, "/courses/**").hasAnyAuthority("LECTURER", "STUDENT") .requestMatchers(HttpMethod.POST, "/school/**").hasAuthority("LECTURER") .requestMatchers(HttpMethod.GET, "/school/**").hasAnyAuthority("LECTURER", "STUDENT") ) .sessionManagement(manager -> manager.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authenticationProvider(authenticationProvider()) .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class); return httpSecurity.build(); }
验证建议
修改后重启Spring Boot服务,重新触发POST请求,检查浏览器控制台是否仍有跨域错误。同时可以通过浏览器开发者工具的网络标签,查看OPTIONS请求的响应头是否包含Access-Control-Allow-Origin等CORS相关字段。
内容的提问来源于stack exchange,提问作者Duy Hung
相关产品推荐
相关产品推荐

