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
相关产品推荐
相关产品推荐

