SpringBoot实战:统一接口返回 + 全局跨域配置
前言
前后端分离架构下,前端页面(Vue/React)通常部署在不同域名/端口,浏览器出于安全同源策略,会拦截跨域请求。
常见报错:Access to XMLHttpRequest at 'xxx' from origin 'xxx' has been blocked by CORS policy。
很多初学者的临时方案:在每个Controller类上加@CrossOrigin。
缺点:
- 分散在各个控制器,修改策略需要改动多处代码;
- 无法统一配置允许的请求头、请求方法、最大有效期;
- 项目模块多的时候,容易漏加,线上偶现跨域问题。
企业项目一般采用全局统一CORS配置,一次性对所有接口生效。本文提供两套方案:
方案A:WebMvcConfigurer(推荐,简单项目首选)
方案B:CorsFilter过滤器(优先级更高,适合搭配Filter链路场景)
复用前篇的Result统一返回实体,不再重复贴代码。
技术栈
- Java 17
- SpringBoot 2.7.x
- spring-boot-starter-web
方案A:WebMvcConfigurer 全局跨域(推荐)
新建配置类 CorsConfig.java,实现WebMvcConfigurer接口,重写addCorsMappings方法。
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 匹配所有接口路径
.allowedOriginPatterns("*") // 允许来源域名,*代表全部;生产环境建议写前端域名
.allowedMethods("GET","POST","PUT","DELETE","OPTIONS") // 允许请求方法
.allowCredentials(true) // 是否允许携带Cookie
.maxAge(3600) // 预检请求有效期,单位秒
.allowedHeaders("*"); // 允许所有请求头
}
}
⚠️ 重要:
allowCredentials=true时,不能直接写 allowedOrigins(“*”),SpringBoot高版本会报错,要用allowedOriginPatterns("*")。
方案B:CorsFilter 过滤器方式(高优先级)
如果项目中存在自定义Filter链、权限过滤器,WebMvc的跨域配置有时会被拦截器提前截断,此时使用CorsFilter方案。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CorsFilterConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
// 允许域名,生产环境改成前端域名
config.addAllowedOriginPattern("*");
config.setAllowCredentials(true);
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
测试Controller
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/cors")
public class CorsTestController {
@GetMapping("/test")
public Result<String> test(){
return Result.success("跨域请求成功!");
}
}
两种方案对比
| 方案 | 实现方式 | 优先级 | 适用场景 |
|---|---|---|---|
| WebMvcConfigurer | WebMvc层配置 | 较低 | 普通业务项目,无复杂Filter,简单易维护 |
| CorsFilter | Servlet过滤器 | 更高 | 存在自定义Filter、登录鉴权过滤器场景;过滤器内异常也能处理跨域头 |
注意:不要同时启用两套全局跨域配置,避免重复添加响应头。
核心知识点讲解
- 预检请求 OPTIONS
浏览器在发送PUT/DELETE、带自定义Header的请求前,会先发OPTIONS预检请求,询问服务器是否允许跨域。maxAge用来缓存预检结果,减少OPTIONS请求次数,提升性能。 allowCredentials携带Cookie
开启后前端axios需要配置withCredentials:true,生产环境禁止*通配域名,必须指定前端域名,否则存在安全风险。- 跨域本质是浏览器安全限制
跨域限制是浏览器行为,Postman、后端服务之间调用不存在跨域问题。很多新手混淆这点,后端调后端报跨域基本是理解误区。
常见踩坑
- 同时加了
@CrossOrigin+ 全局CORS,会重复返回Access-Control-Allow-Origin响应头,浏览器报错; - 生产环境直接
allowedOriginPatterns("*"),所有人都可以跨域调用接口,有安全风险; - 全局异常处理器 + 跨域:如果异常在Filter抛出,WebMvc跨域配置失效,必须使用CorsFilter;
- Nginx反向代理部署场景:Nginx也可以配置CORS,Nginx和后端不要同时配置跨域,容易冲突。
生产环境优化建议
- 使用配置文件读取允许域名,不要硬编码,区分开发/测试/生产环境;
# application.yml
cors:
allow-origins: [http://localhost:8080](http://localhost:8080),[https://xxx-front.com](https://xxx-front.com)
- 封装读取配置,从配置文件加载域名列表,避免改代码重启服务;
- 增加白名单机制,只信任指定前端域名;
- 线上环境关闭
*通配,严格限制域名。
总结
跨域是前后端分离项目的基础配置,推荐新项目优先使用WebMvcConfigurer方案;如果项目有自定义过滤器,就切换到CorsFilter。
搭配上一篇全局异常处理器,现在你的SpringBoot项目已经具备:统一返回格式、全局异常捕获、全局跨域,这一套就是企业后端项目基础脚手架底座。
后续可以继续集成参数校验、统一日志、接口文档Swagger/Knife4j。
- 点赞
- 收藏
- 关注作者
评论(0)