本地部署React与SpringBoot时遭遇CORS错误求助
解决React调用SpringBoot API的CORS重定向错误
问题根源
错误核心是Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request,原因是:
- Spring Security的
formLogin会对未认证请求重定向到登录页,但预检请求(OPTIONS)不允许被重定向 - 请求路径未被正确放行,导致OPTIONS请求被拦截触发重定向
- 多份CORS配置冲突、React代理配置无效
具体解决方案
1. 修正Spring Security路径匹配与CORS配置
你的React请求路径是/createUser,但原配置放行的是/v1/createUser/**,路径不匹配导致拦截。同时统一用Security的CORS配置,避免冲突:
@Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.ldapAuthentication() .userDnPatterns("uid={0},ou=users") .contextSource(contextSource()) .passwordCompare() .passwordAttribute("userPassword"); } @Bean public DefaultSpringSecurityContextSource contextSource() { return new DefaultSpringSecurityContextSource("ldap://localhost:8389/dc=example,dc=com"); } @Override protected void configure(HttpSecurity http) throws Exception { http.cors() .configurationSource(corsConfigurationSource()) .and() .csrf() .disable() .authorizeRequests() .antMatchers("/actuator/**") .permitAll() .antMatchers("/createUser/**") // 匹配React实际请求路径 .permitAll() .antMatchers("/login/**") .permitAll() .anyRequest() .authenticated() .and() .formLogin(); } // 自定义全局CORS配置 @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); config.setAllowedOrigins(Arrays.asList("http://localhost:3000")); config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS")); config.setAllowedHeaders(Arrays.asList("*")); config.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return source; } }
2. 删除重复的WebConfig配置
移除WebConfig类,避免Spring MVC和Security的CORS规则冲突,统一使用Security层面的配置即可。
3. 修复React代理配置
原package.json的proxy指向自身(http://localhost:3000/)完全无效,改为SpringBoot API地址:
"name": "task-management-app", "version": "0.1.0", "private": true, "proxy": "http://localhost:8080", // 修正为SpringBoot端口 "dependencies": { // ... 依赖不变 }
同时简化React的fetch请求(无需手动配置跨域参数):
const handleSubmit = async (e) => { e.preventDefault(); const validationErrors = validate(); if (Object.keys(validationErrors).length > 0) { setErrors(validationErrors); } else { try { // 使用相对路径,由proxy自动转发到SpringBoot const response = await fetch('/createUser', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ username, password }), }); const data = await response.json(); if (response.ok) { console.log('Registration successful:', data); } else { setErrors({ api: data.message || 'Registration failed' }); } } catch (error) { setErrors({ api: 'An error occurred. Please try again.' }); } } };
4. 校验控制器路径一致性
确保SpringBoot控制器的请求路径与React调用一致:
@RestController // 无需再添加@CrossOrigin,全局配置已覆盖 public class UserController { @PostMapping("/createUser") // 与React请求路径匹配 public ResponseEntity<?> createUser(@RequestBody UserRequest request) { // 业务逻辑实现 return ResponseEntity.ok("User created successfully"); } }
验证步骤
- 重启SpringBoot和React开发服务器
- 提交请求,查看浏览器控制台是否消除CORS错误
- 打开开发者工具Network标签,确认OPTIONS请求返回200状态码
内容的提问来源于stack exchange,提问作者Abhinash Jha
相关产品推荐
相关产品推荐

