在前后端分离的开发模式中,前端调用后端接口时,经常会遇到 跨域资源共享(CORS) 的问题。Spring Boot 作为常用的后端框架,提供了多种方式来优雅地解决这个问题。本文将全面介绍 Spring Boot 中处理 CORS 的常见方法、原理分析及注意事项,帮助开发者高效排查和解决跨域问题。
一、什么是 CORS?
CORS(Cross-Origin Resource Sharing,跨域资源共享)是浏览器的一种安全策略,用于防止页面被恶意地从一个域加载资源到另一个域。简单来说,只要前端请求的协议、域名、端口与后端接口不完全一致,就属于跨域请求。
例如:
前端地址:http://localhost:3000
后端接口:http://localhost:8080/api/data
这就构成了跨域请求,浏览器会默认拦截这类请求,除非服务器端明确允许跨域访问。
二、Spring Boot 中解决 CORS 的几种方法
Spring Boot 提供了多种方式来配置和处理跨域问题,以下是最常用的三种方法:
方法一:使用 @CrossOrigin
注解(推荐用于小型项目或测试)
这是 Spring Boot 提供的快捷方式,可直接作用于控制器类或方法上:
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "http://localhost:3000")
public class MyController {
@GetMapping("/data")
public String getData() {
return "Hello, CORS!";
}
}
参数说明:
-
origins
:允许的域名(可为*
表示所有)。 -
methods
:允许的方法,如GET
,POST
等。 -
maxAge
:预检请求的有效时间(单位秒)。 -
allowedHeaders
:允许携带的头信息。
缺点:对于中大型项目来说,控制器众多,维护成本高。
方法二:全局 CORS 配置(推荐用于中大型项目)
通过实现 WebMvcConfigurer
接口,全局统一配置跨域规则,适用于大多数项目场景。
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 所有接口
.allowedOrigins("http://localhost:3000") // 允许的前端地址
.allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的方法
.allowedHeaders("*") // 允许的请求头
.allowCredentials(true) // 允许携带 Cookie
.maxAge(3600); // 预检请求缓存时间(秒)
}
}
优点:配置集中,维护简单,推荐使用。
方法三:通过 Filter 手动设置响应头(不推荐,除非特殊需求)
手动注册一个过滤器,向响应中添加 CORS 相关头信息:
@Component
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
HttpServletRequest req = (HttpServletRequest) request;
res.setHeader("Access-Control-Allow-Origin", "http://localhost:3000");
res.setHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
res.setHeader("Access-Control-Allow-Headers", "*");
res.setHeader("Access-Control-Allow-Credentials", "true");
// OPTIONS 预检请求直接返回
if ("OPTIONS".equalsIgnoreCase(req.getMethod())) {
res.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(request, response);
}
}
}
缺点:易出错,不易维护,建议使用
WebMvcConfigurer
方式代替。
三、常见问题排查
-
OPTIONS 请求返回 403 或没有响应?
-
确保后端允许
OPTIONS
方法。 -
确保没有被 Spring Security 拦截。
-
-
携带 Cookie 不生效?
-
后端必须设置:
.allowCredentials(true)
-
前端必须设置:
axios.defaults.withCredentials = true
-
-
Spring Security 拦截 CORS 请求?
- 需要额外配置 CORS 策略,示例如下:
@EnableWebSecurity
public class SecurityConfig {@Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .cors() // 启用 CORS .and() .csrf().disable() .authorizeHttpRequests() .anyRequest().permitAll(); return http.build(); } @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); config.setAllowedOrigins(List.of("http://localhost:3000")); config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS")); config.setAllowedHeaders(List.of("*")); config.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return source; }
}
四、总结
方法 | 场景 | 推荐度 |
---|---|---|
@CrossOrigin 注解 |
控制器少,接口固定 | ⭐⭐ |
实现 WebMvcConfigurer |
中大型项目,统一配置 | ⭐⭐⭐⭐⭐ |
自定义 Filter | 特殊需求(如动态域) | ⭐ |
CORS 配置看似简单,但与前端请求设置、Spring Security 配合使用时需格外注意。建议在项目初始化阶段就进行统一的跨域策略设计,避免后续频繁调整。