前后端分离架构下,前端应用运行在 http://localhost:8080,后端接口部署在 http://localhost:8081,浏览器发起请求时就会因为同源策略而被拦截,控制台报出经典的 CORS 错误。跨域资源共享(Cross-Origin Resource Sharing)是 W3C 制定的标准机制,它允许服务端通过一系列响应头明确告知浏览器哪些来源、哪些方法、哪些请求头是允许的。Spring Boot 对 CORS 提供了非常完善的支持,实现方式主要有三种:接口级注解、全局配置类以及 CorsFilter 过滤器。本文逐一分析这几种方案的用法、原理和适用场景。

一、使用 @CrossOrigin 注解实现局部跨域
@CrossOrigin 是 Spring Framework 4.2 之后提供的注解,用起来最简单直接。把它加在 Controller 类上,该类下所有接口都允许跨域;加在方法上,则只对当前方法生效。来看一个实际例子:
@RestController
@RequestMapping("/api/user")
@CrossOrigin(origins = "http://localhost:8080", maxAge = 3600)
public class UserController {
@GetMapping("/list")
public List<String> list() {
return Arrays.asList("张三", "李四", "王五");
}
// 方法级注解会覆盖类级配置
@CrossOrigin(origins = {"http://a.com", "http://b.com"})
@PostMapping("/add")
public String add(@RequestBody User user) {
return "ok";
}
}注解中的 origins 属性指定允许的源,maxAge 表示预检请求结果的缓存时间,单位是秒,配置为 3600 意味着浏览器在一个小时内不会重复发送 OPTIONS 预检请求,能有效减少无效请求量。此外还支持 methods、allowedHeaders、exposedHeaders、allowCredentials 等属性。
这种方式的优点是配置粒度细、见效快,适合只需要开放少量接口的场景。缺点也很明显:当接口数量多的时候,逐个添加注解非常繁琐,而且配置分散在各个 Controller 中,后续维护时很难统一调整。因此在真实项目中,除非只有个别接口需要跨域,一般不推荐大规模使用这种方式。
二、通过 WebMvcConfigurer 实现全局 CORS 配置
更常见的做法是在配置类中实现 WebMvcConfigurer 接口的 addCorsMappings 方法,一次配置即可覆盖所有接口。示例代码如下:
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("https://*.ippipp.com")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.exposedHeaders("Authorization", "Content-Disposition")
.allowCredentials(true)
.maxAge(3600);
}
}这里有一个非常经典的坑需要注意:如果配置了 allowCredentials(true),也就是允许跨域请求携带 Cookie,那么 allowedOrigins 不能设置为通配符星号,否则启动或请求时会抛出异常。浏览器的 CORS 规范本身也禁止在带凭证的响应中返回通配来源,这是为了安全考虑。Spring 5.3 之后提供了 allowedOriginPatterns 方法,允许使用类似 https://*.ippipp.com 的模式匹配来兼顾灵活性和凭证支持。
这种配置方式的底层原理是 Spring MVC 在处理请求时通过 CorsProcessor 处理器检查请求的 Origin,如果命中配置规则,就会在响应头中写入 Access-Control-Allow-Origin、Access-Control-Allow-Methods 等字段,浏览器看到这些响应头后才放行数据给前端 JavaScript。它作用于 MVC 拦截阶段,执行时机比普通 Filter 晚,这一点在集成 Spring Security 时会产生问题,后面会详细说明。
全局映射配置的好处是集中管理、改动一处即可生效,是目前中小型项目的主流选择。需要注意的是,如果项目中已经存在自定义的拦截器并且拦截器拒绝了 OPTIONS 预检请求,跨域配置可能失效,此时要确保 OPTIONS 请求能被放行。
三、注册 CorsFilter 过滤器:优先级最高、控制最精细
第三种方式是直接向容器注册一个 CorsFilter Bean。由于过滤器执行在 Servlet 容器层面,早于 Spring MVC 的 DispatcherServlet,因此它能更早地处理预检请求,避免被安全框架或拦截器提前拦截。配置如下:
@Configuration
public class CorsFilterConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOriginPatterns(Collections.singletonList("*"));
config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
config.setAllowedHeaders(Collections.singletonList("*"));
config.setAllowCredentials(true);
config.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}当项目集成了 Spring Security 时,强烈建议使用这种方式,并且通过 FilterRegistrationBean 把过滤器的执行顺序设置为最小值,确保它先于安全过滤器执行,否则 OPTIONS 预检请求可能先被安全过滤链以 401 拒绝,跨域响应头根本没机会写入。
@Bean
public FilterRegistrationBean<CorsFilter> corsFilterRegistration() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOriginPatterns(Collections.singletonList("*"));
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return bean;
}也可以在 Spring Security 的配置类中直接调用 http.cors(),让 Security 框架接管跨域处理,它会自动查找名为 corsConfigurationSource 的 Bean。两种方式选择一种即可,不要重复配置,否则可能出现响应头重复写入导致浏览器报错的情况。
三种方案对比与生产环境建议
下面对三种方案做一个简单对比:
| 方案 | 作用范围 | 执行时机 | 适用场景 |
|---|---|---|---|
| @CrossOrigin 注解 | 类或方法级 | MVC 处理阶段 | 少量接口需要跨域 |
| WebMvcConfigurer 配置 | 全局路径映射 | MVC 拦截阶段 | 普通项目全局配置 |
| CorsFilter 过滤器 | 全局路径映射 | Servlet Filter 阶段 | 集成 Security 或网关场景 |
最后强调几点生产环境的实践建议。第一,永远不要图省事把所有配置都写成星号通配并把 allowCredentials 设为 true,这等于把接口暴露给任意来源且允许携带凭证,存在严重的 CSRF 风险,正确做法是把允许的来源收敛到明确的域名列表,来源较多时可以用 allowedOriginPatterns 配合配置中心动态管理。第二,遇到跨域不生效时,先确认浏览器Network面板中 OPTIONS 预检请求的状态码,如果是 401 或 403,多半是被 Security 或自定义拦截器拦截了,改用 CorsFilter 方案并调整优先级即可。第三,如果系统采用了微服务架构,跨域配置通常统一放在网关层处理,例如 Spring Cloud Gateway 的 CorsWebFilter,下游服务就无需再重复配置。掌握这几种方案的原理和差异,无论遇到什么样的跨域报错,都能快速定位并选择合适的解决路径。
Spring Boot CORS跨域配置CorsFilter修改时间:2026-09-12 01:36:35