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 = "*")注解,避免配置冲突。
原配置无效的原因
- Security过滤器优先级更高:Spring Security的过滤器链会先于Spring MVC的CORS处理逻辑拦截请求,导致
@CrossOrigin注解的配置无法生效。 - 预检请求未放行:浏览器发送POST/PUT等非简单请求前,会先发送OPTIONS预检请求验证跨域权限,原Security配置未放行这类请求,导致预检失败触发CORS错误。
内容的提问来源于stack exchange,提问作者asskayy
相关产品推荐
相关产品推荐

