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

React调用Spring Boot API遇CORS错误,求跨域解决方案

解决Spring Boot API的CORS跨域问题

问题根源

你的Spring Security配置会在Spring MVC的@CrossOrigin注解生效前拦截请求,尤其是浏览器发送的OPTIONS预检请求未被正确放行,导致CORS头无法返回给前端,最终触发跨域错误。

解决方案

1. 在Spring Security中配置全局CORS规则

修改SecurityConfig类,添加CORS配置并确保OPTIONS预检请求被全局放行:

package com.brs.securityconfiguration;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private JwtAuthenticationFilter jwtAuthenticationFilter;
    @Autowired
    CustomUserDetailsService customUserDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                // 启用CORS配置
                .cors()
                .and()
                .authorizeRequests()
                // 全局放行OPTIONS预检请求
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                .antMatchers( "/token", "/addUser")
                .permitAll()
                .antMatchers(HttpMethod.GET, "/bus")
                .hasRole("ADMIN")
                .antMatchers(HttpMethod.DELETE, "/bus", "/deleteReservation", "/deleteUser")
                .hasRole("ADMIN")
                .antMatchers(HttpMethod.POST, "/bus", "/addReservation")
                .hasRole("ADMIN")
                .antMatchers(HttpMethod.PUT, "/bus", "/updateReservation", "/updateUser")
                .hasRole("ADMIN")
                .antMatchers(HttpMethod.GET, "/buses", "/viewAllReservation", "/viewReservation")
                .hasRole("ADMIN")
                .antMatchers(HttpMethod.GET, "/buses", "/viewFeedback", "/viewAllFeedBack", "/viewReservation", "/viewUser", "/viewAllUsers", "/searchBus")
                .hasRole("USER")
                .antMatchers(HttpMethod.GET, "/viewBusByType")
                .hasRole("ADMIN")
                .antMatchers(HttpMethod.GET, "/viewBusByType")
                .hasRole("USER")
                .antMatchers(HttpMethod.POST, "/addFeedback", "/addReservation")
                .hasRole("USER")
                .antMatchers(HttpMethod.PUT, "/updateFeedback", "/updateReservation")
                .hasRole("USER")
                .antMatchers(HttpMethod.DELETE, "/deleteReservation")
                .hasRole("USER")
                .anyRequest().authenticated()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        http.addFilterBefore(jwtAuthenticationFilter , UsernamePasswordAuthenticationFilter.class);

    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
    }

    // 配置全局CORS规则:允许任意域名、方法、请求头
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        // 允许所有域名跨域
        configuration.setAllowedOrigins(Arrays.asList("*"));
        // 允许所有HTTP请求方法
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        // 允许所有请求头
        configuration.setAllowedHeaders(Arrays.asList("*"));
        // 允许携带凭证(如Cookie,按需开启)
        configuration.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        // 对所有API路径应用该配置
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

2. 移除冗余配置(可选)

既然已经配置了全局CORS规则,可以移除UsersController中@PostMapping("/addUser")上的@CrossOrigin(origins = "*")注解,避免配置冲突。

原配置无效的原因

  1. Security过滤器优先级更高:Spring Security的过滤器链会先于Spring MVC的CORS处理逻辑拦截请求,导致@CrossOrigin注解的配置无法生效。
  2. 预检请求未放行:浏览器发送POST/PUT等非简单请求前,会先发送OPTIONS预检请求验证跨域权限,原Security配置未放行这类请求,导致预检失败触发CORS错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 07:27:04