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

NodeJS运行的React可POST请求Spring Boot API,但PUT遇CORS问题

这个问题我太熟了!你遇到的是典型的CORS预检请求失败问题——为啥GET/POST没问题,PUT就炸?因为浏览器对请求分了「简单请求」和「非简单请求」:GET、POST这类符合条件的属于简单请求,直接发送;但PUT、DELETE或者带自定义头的请求,浏览器会先发送一个OPTIONS预检请求,确认服务器允许跨域后才会发真正的请求。你的Spring Boot服务没正确处理这个OPTIONS请求,导致返回403,还没带上Access-Control-Allow-Origin头,所以浏览器直接拦截了请求。

下面给你几个靠谱的解决办法,按推荐程度排序:

1. 全局CORS配置(推荐,一次配置全接口生效)

创建一个Spring配置类,实现WebMvcConfigurer,统一配置跨域规则:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**") // 对所有接口生效
                .allowedOrigins("http://localhost:3000") // 允许你的React应用域名
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 必须包含OPTIONS,否则预检请求会被拒
                .allowedHeaders("*") // 允许所有请求头
                .allowCredentials(true) // 如果需要携带Cookie、Authorization等凭证,开启这个
                .maxAge(3600); // 预检请求的缓存时间,减少重复OPTIONS请求
    }
}

2. 控制器/方法级别的局部配置

如果只想给特定接口开跨域,可以在控制器类或者单个方法上加@CrossOrigin注解:

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
@CrossOrigin(origins = "http://localhost:3000", allowedMethods = {"GET", "POST", "PUT", "OPTIONS"})
public class ProjectController {

    @PutMapping("/project/{id}")
    public ResponseEntity<?> updateProject(@PathVariable Long id, @RequestBody Project project) {
        // 你的更新逻辑
        return ResponseEntity.ok(updatedProject);
    }
}

3. 如果用了Spring Security,必须额外配置!

要是你的Spring Boot项目集成了Spring Security,它默认会拦截所有请求,包括OPTIONS预检请求。这时候除了上面的配置,还要在Security配置里放行OPTIONS,并且启用CORS:

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import static org.springframework.http.HttpMethod.OPTIONS;

@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .cors(withDefaults()) // 启用CORS,复用上面的全局配置
            .csrf(csrf -> csrf.disable()) // 如果前端没处理CSRF令牌,暂时禁用(生产环境需谨慎)
            .authorizeHttpRequests(auth -> auth
                .requestMatchers(OPTIONS, "/**").permitAll() // 放行所有OPTIONS预检请求
                .anyRequest().authenticated() // 其他请求需要认证
            );
        return http.build();
    }
}

最后检查几个关键点:

  • 确保allowedOrigins是你React应用的真实地址(http://localhost:3000),生产环境别用*,要指定具体域名;
  • 如果前端请求带了Cookie或Authorization头,要开启allowCredentials(true),同时前端请求里也要设置withCredentials: true(比如Axios的话就是axios.put(url, data, { withCredentials: true }));
  • 确认allowedMethods里包含了OPTIONS,不然预检请求还是会被拒绝。

试试上面的方法,应该就能解决PUT请求的跨域问题了!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:19:31