ReactJS+Spring Boot跨域报错:No 'Access-Control-Allow-Origin'问题
跨域问题排查与解决:React + Spring Boot 调用API时出现No 'Access-Control-Allow-Origin' header错误
我使用ReactJS作为前端、Spring Boot作为后端,调用API接口http://localhost:8080/api/v1/admin/member/checkIn?gymId=1&email=xyz@gmail.com时,出现报错:No 'Access-Control-Allow-Origin' header is present on the requested resource。
原ReactJS API调用代码
export const checkInMembers = (gymId, email) => { const adminData = JSON.parse(window.sessionStorage.getItem("USER_DETAILS")); return axios.post('http://localhost:8080/api/v1/admin/member/checkIn', { gymId, email }, { headers: { 'Authorization': `Bearer ${adminData.token}`, }, }); }
Spring Boot后端控制器代码
package com.CMPE202.healthclub.controller; import com.CMPE202.healthclub.entity.user.User; import com.CMPE202.healthclub.entity.user.UserGymVisit; import com.CMPE202.healthclub.exceptions.BadServerException; import com.CMPE202.healthclub.exceptions.InvalidOperationException; import com.CMPE202.healthclub.exceptions.RecordNotFoundException; import com.CMPE202.healthclub.model.UserDetailsResponse; import com.CMPE202.healthclub.service.AdminService; import jakarta.annotation.security.RolesAllowed; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.Optional; @RestController @RequestMapping("/api/v1/admin") @RequiredArgsConstructor @CrossOrigin(origins = "*", allowedHeaders = "*") @RolesAllowed("STAFF") @Validated public class AdminController { private final AdminService adminService; @GetMapping({"/member"}) public UserDetailsResponse getUserDetailsFromEmail(@RequestParam String email) throws RecordNotFoundException { return adminService.getUserDetailsFromEmail(email); } @PostMapping({"/member/checkIn"}) public UserGymVisit checkInUserToGym(@RequestParam(required = true) Long gymId, @RequestParam(required = true) String email) throws RecordNotFoundException, InvalidOperationException, BadServerException { return adminService.checkInUsers(gymId, email); } @PutMapping({"/member/checkOut"}) public UserGymVisit checkOutUserToGym(@RequestParam(required = true) Long userGymVisitId) throws InvalidOperationException { return adminService.checkOutUsers(userGymVisitId); } @GetMapping({"/member/currentCheckedInList"}) public List<UserDetailsResponse> getAllCurrentCheckedInUsers(@RequestParam(required = true) Long gymId){ return adminService.getAllCurrentCheckedInUsers(gymId); } }
尝试过的修改(未解决问题)
export const checkInMembers = (gymId, email) => { const adminData = JSON.parse(window.sessionStorage.getItem("USER_DETAILS")); const corsOptions = { origin: 'http://localhost:8080', // specify the URL of your server }; const axiosInstance = axios.create(); axiosInstance.interceptors.request.use(cors(corsOptions)); return axiosInstance.post('http://localhost:8080/api/v1/admin/member/checkIn', { gymId, email }, { headers: { 'Authorization': `Bearer ${adminData.token}`, 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': '*' }, mode: 'cors', credentials: 'include' }); }
问题根源与解决方法
1. 请求参数传递不匹配
后端checkInUserToGym方法用@RequestParam声明要从URL查询参数中获取gymId和email,但前端是通过POST请求的请求体传递参数,导致后端无法获取到必填参数,触发参数校验失败。这种情况下请求会在进入控制器前被拦截,@CrossOrigin注解的CORS头无法正常返回,最终出现跨域报错。
解决方式二选一:
- 前端修改为传递URL参数:
export const checkInMembers = (gymId, email) => { const adminData = JSON.parse(window.sessionStorage.getItem("USER_DETAILS")); return axios.post(`http://localhost:8080/api/v1/admin/member/checkIn?gymId=${gymId}&email=${email}`, {}, { headers: { 'Authorization': `Bearer ${adminData.token}`, }, }); }
- 后端修改为接收请求体参数:
先创建请求DTO类:
public class CheckInRequest { private Long gymId; private String email; // 构造函数、getter和setter }
再修改控制器方法:
@PostMapping({"/member/checkIn"}) public UserGymVisit checkInUserToGym(@RequestBody CheckInRequest request) throws RecordNotFoundException, InvalidOperationException, BadServerException { return adminService.checkInUsers(request.getGymId(), request.getEmail()); }
2. 移除前端无效的CORS请求头
Access-Control-Allow-Origin和Access-Control-Allow-Headers是后端返回给前端的响应头,不需要前端在请求中添加,这些请求头对跨域解决没有任何帮助,直接去掉即可。
3. 集成Spring Security时需额外配置CORS
如果项目使用了Spring Security,仅在控制器添加@CrossOrigin可能不生效,需要在Security配置中明确允许CORS:
@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.cors(cors -> cors.configurationSource(corsConfigurationSource())) // 其他Security配置... return http.build(); } @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(List.of("*")); // 生产环境建议指定具体域名 configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE")); configuration.setAllowedHeaders(List.of("*")); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; } }
内容的提问来源于stack exchange,提问作者adesh landge
相关产品推荐
相关产品推荐

